I am trying to create a Manga viewer which needs to load JPG
images with large sizes like 1000*16000, my application is in delphi FMX and i have already tried using TImage
, TImageViewer
, TImageControl
but all of them use TBitmap
which trims the size to 8192
after loading the image
I tried searching for image libraries but i was unable to find anything for FMX (firemonkey)
I was thinking maybe i could load the image in a Memory stream
and then copy and draw it in smaller sizes to several bitmaps ? but i don't how can i read and parse the memory stream and only pick to a certain clean height !
In the end i'm looking for a way to load and show these large (1000*16000
) images in Delphi FMX
I am using delphi 10.2.3
Thanks.
Edit 01 :
I think i have found a way that might make things easy, i added the Vcl.Imaging.jpeg
to uses clause in the FMX (FireMonkey)
and then i used TJPEGImage
and loaded the image, and i printed the width and height and they are correct and not trimmed ! so i was thinking, maybe i can read each pixel from TJPEGImage.canvas
and then print it into FMX TBitmap
?, what do you think about this approach ?, do you know a good way to copy the data inside TJPEGImage
to FMX TBitmap
?
Edit 02 :
I have found a new solution, the TBitmapSurface
, it seems this class doesn't have the TBitmap
limitations and i was able to load the image inside of it without getting trimmed ! but there is a problem! how can i give this to TImage
? if i simply say Image.bitmap.assign(TBitmapsurface)
, then the image gets trimmed again ! so it seems the only possible way is rewriting the TImage
so it uses TBitmapSurface
instead of TBitmap
, any help regarding this issue is appreciated, thanks.
Here is the code for the TBitmapSurface
:
bitmapSurf := TBitmapSurface.Create;
TBitmapCodecManager.LoadFromFile(path, bitmapSurf);
Unlike FMX.Graphics.TBitmap
which has a size limitations of 8192 * 8192
, FMX.Surface.TBitmapSurface
seems to support up to 16k * 16k
and possibly even more (i haven't tested), so using FMX.Surface.TBitmapSurface
you can load the image without getting trimmed, and then you can easily split it into two FMX.Graphics.TBitmap
(or possible more parts using the same approach)
Below you can see the code which first loads the JPG
into TBitmapSurface
, and then the code which splits that into two TBitmap
:
var
srce, dest: TBitmapSurface;
path: string;
scan: integer;
w, h1, h2: integer;
begin
path := 'C:\tmp\Imgs\res.bmp';
srce := TBitmapSurface.Create;
TBitmapCodecManager.LoadFromFile(path, srce);
dest := TBitmapSurface.Create;
// first half
w := srce.Width;
h1 := srce.Height div 2;
dest.SetSize(w, h1, TPixelFormat.RGBA);
for scan := 0 to h1-1 do
Move(srce.Scanline[scan]^, TBitmapSurface(dest).Scanline[scan]^, srce.Width * 4);
Image1.Bitmap.Assign(dest);
// second half
h2 := srce.Height - h1;
dest.SetSize(w, h2, TPixelFormat.RGBA);
for scan := h1 to srce.Height-1 do
Move(srce.Scanline[scan]^, TBitmapSurface(dest).Scanline[scan-h1]^, srce.Width * 4);
Image2.Bitmap.Assign(dest);
end;
This answer was provided using the comments on the first post and the answer to my other question:
How to draw FMX.Surface.TBitmapSurface on FMX.Graphics.TBitmap