Skip to content

Commit

Permalink
Update image to/from string again, use PNG. final change.
Browse files Browse the repository at this point in the history
  • Loading branch information
ollydev committed Mar 4, 2024
1 parent a483c38 commit 4784537
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 98 deletions.
108 changes: 21 additions & 87 deletions Source/image/simba.image_stringconv.pas
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Save/Load bitmaps from/to a base64 string.
Channels (B,G,R,A) are split and compressed with zlib individually for better compression.
Strings are generated as PNG with a small header.
}
unit simba.image_stringconv;

Expand All @@ -25,130 +25,64 @@ interface
TImageStringHeader = packed record
Version: Integer;
Width, Height: Integer;
ChannelSize: record
B,G,R,A: Integer;
end;
Name: String[128];
end;

procedure SimbaImage_FromString(Image: TSimbaImage; Str: String);
procedure SimbaImage_FromString(Image: TSimbaImage; const Str: String);
function SimbaImage_ToString(Image: TSimbaImage): String;

implementation

uses
ZStream,
simba.encoding;

procedure SimbaImage_FromString(Image: TSimbaImage; Str: String);

procedure DecompressChannel(SourceStream: TStream; SourceSize: Integer; ChannelOffset: Integer);
var
Stream: TMemoryStream;
DecompressStream: Tdecompressionstream;
Buffer: array[0.. 16384-1] of Byte;
I, Count, DataIndex: Integer;
begin
Stream := nil;
DecompressStream := nil;
try
Stream := TMemoryStream.Create();
Stream.CopyFrom(SourceStream, SourceSize);
Stream.Position := 0;

DecompressStream := Tdecompressionstream.create(Stream);

DataIndex := 0;
repeat
Count := DecompressStream.Read(Buffer[0], Length(Buffer));
for I := 0 to Count - 1 do
PByte(@Image.Data[DataIndex + I].B + ChannelOffset)^ := Buffer[I];
Inc(DataIndex, Count);
until (Count = 0);
finally
Stream.Free();
DecompressStream.Free();
end;
end;
FPReadPNG, FPWritePNG,
simba.encoding, simba.image_lazbridge;

procedure SimbaImage_FromString(Image: TSimbaImage; const Str: String);
var
Stream: TStringStream;
Header: TImageStringHeader;
begin
if not Str.StartsWith(HeaderPrefix, True) then
SimbaException('TImage.LoadFromString: Invalid string, it should begin with "IMG:"');
Str := Str.After(HeaderPrefix);
SimbaException('TImage.FromString: Invalid string, should begin with "IMG:"');
Str.DeleteRange(1, Length(HeaderPrefix));

Stream := nil;
try
Stream := TStringStream.Create(BaseDecode(BaseEncoding.b64, Str));
Stream.Read(Header, SizeOf(TImageStringHeader));

Image.SetSize(Header.Width, Header.Height);
Image.Name := Header.Name;

DecompressChannel(Stream, Header.ChannelSize.B, 0);
DecompressChannel(Stream, Header.ChannelSize.G, 1);
DecompressChannel(Stream, Header.ChannelSize.R, 2);
DecompressChannel(Stream, Header.ChannelSize.A, 3);
SimbaImage_FromFPImageReader(Image, TFPReaderPNG, Stream);
finally
if (Stream <> nil) then
FreeAndNil(Stream);
Stream.Free();
end;
end;

function SimbaImage_ToString(Image: TSimbaImage): String;

procedure CompressChannel(ChannelOffset: Byte; DestStream: TStream; out Count: Integer);
var
Channel: TByteArray;
I: Integer;
CompressionStream: Tcompressionstream;
begin
CompressionStream := nil;

Count := DestStream.Position;
try
CompressionStream := Tcompressionstream.create(clDefault, DestStream);

SetLength(Channel, Image.Width * Image.Height);
for I := 0 to High(Channel) do
Channel[I] := PByte(@Image.Data[I].B + ChannelOffset)^;

CompressionStream.Write(Channel[0], Length(Channel));
CompressionStream.Flush();
finally
CompressionStream.Free();
end;

Count := DestStream.Position - Count;
end;

var
Stream: TStringStream;
HeaderStream, ImageStream: TStringStream;
Header: TImageStringHeader;
begin
Stream := nil;
try
Stream := TStringStream.Create();
Stream.Write(Header{%H-}, SizeOf(TImageStringHeader)); // write header last, but reserve space

CompressChannel(0, Stream, Header.ChannelSize.B);
CompressChannel(1, Stream, Header.ChannelSize.G);
CompressChannel(2, Stream, Header.ChannelSize.R);
CompressChannel(3, Stream, Header.ChannelSize.A);
HeaderStream := nil;
ImageStream := nil;

try
Header.Version := 1;
Header.Width := Image.Width;
Header.Height := Image.Height;
Header.Name := Image.Name;

Stream.Position := 0;
Stream.Write(Header, SizeOf(TImageStringHeader));
HeaderStream := TStringStream.Create();
HeaderStream.Write(Header, SizeOf(TImageStringHeader));
ImageStream := TStringStream.Create();

SimbaImage_ToFPImageWriter(Image, TFPWriterPNG, ImageStream);

Result := HeaderPrefix + BaseEncode(BaseEncoding.b64, Stream.DataString);
Result := HeaderPrefix + BaseEncode(BaseEncoding.b64, HeaderStream.DataString + ImageStream.DataString);
finally
Stream.Free();
HeaderStream.Free();
ImageStream.Free();
end;
end;

Expand Down
5 changes: 2 additions & 3 deletions Tests/finder_bitmap.simba
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ var
];

var
img := TImage.CreateFromString('IMG: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');
templ := TImage.CreateFromString('IMG:AQAAAAoAAAAKAAAANAAAADUAAAA2AAAAKAAAAAAAAAD4JIgAAQAAAFDjPwEAAAAAwEvxCAAAAADAS/EIAAAAAMBL8QgAAAAAaOZ3AAEAAAABAAAACgAAAAoAAAAgAAAAAAAAAAAAAAAAAAAAAwAAACAIEAgICAAIGAEAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEu4FAHicTYwhEgAwCMPiKmr7/7cOKrj1EIEAcBG4NWSj6ckOtCqRVaKqercKcyDfI5s/D0QgAU14nE2MwQ0AQAjCugZLEPaf7pSHOeKjWhUuAbeGbDI92kFWSXFKVFXvVmEO4ntk8+cBO38GNHicTYzBEQAwCMKyCSOwCvtPU+XhlfMRjQoXQ1pDCZ4e7cCrJMclqqp3qzAHzj1K+PMAimAHynicY2CAg/8wBMT/wQgq8B9MgQFYGiz1H6bwP1QIQkPZDMgAAPu8It4=');

img := TImage.CreateFromString('IMG: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');
templ := TImage.CreateFromString('IMG:AQAAAAoAAAAKAAAAAAAAABAAAAAAAAAAOHuIAAEAAABQ4z8BAAAAAKBoXAcAAAAAoGhcBwAAAACgaFwHAAAAALBWeAABAAAAAQAAAAoAAAAKAAAAIAAAAAAAAAAAAAAAAAAAAAMAAAAgCBAICAgACBgBAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAABnRSTlMAAAAAAABupgeRAAAASElEQVR4nGNgIAj0DdghjAA9bjQGQhooBBEFcuEaQEBeUgRZE0QOoQIoDURAPlAarhXFADQz0c1HthVdDu4uiPn4fAh3P1EAAFhND0kY77/vAAAAAElFTkSuQmCC');
templBrightnessed: TImage;
TPA: TPointArray;
P: TPoint;
Expand Down
Loading

0 comments on commit 4784537

Please sign in to comment.