如何在FMX中加载大位图(火猴) [英] How to load large bitmap in FMX (fire monkey)

查看:504
本文介绍了如何在FMX中加载大位图(火猴)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个Manga查看器,需要加载 JPG 大尺寸的图像,如1000 * 16000,我的应用程序在delphi FMX中,我已经尝试过使用 TImage TImageViewer TImageControl 但所有人都使用 TBitmap 在加载图片后将大小修剪为 8192

我试图搜索图像库但是我无法找到任何 FMX(firemonkey)

我想也许我可以在内存流中加载图像然后以较小的尺寸复制并绘制到几个位图?但我不知道如何读取和解析内存流,只选择一个干净的高度!

最后我正在寻找一种加载和显示这些大的方法( 1000 * 16000 )图片 Delphi FMX

我使用的是delphi 10.2.3

谢谢。

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.

编辑01:

我想我找到了一种可以让事情变得简单的方法,我将 Vcl.Imaging.jpeg 添加到 FMX(FireMonkey)中的uses子句,然后我使用 TJPEGImage 并加载图像,我打印宽度和高度,它们是正确的,没有修剪!所以我在想,也许我可以从 TJPEGImage.canvas 中读取每个像素,然后将其打印到 FMX TBitmap ?,您如何看待这种方法?,您知道将 TJPEGImage 内的数据复制到 FMX TBitmap 的好方法吗? ?

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 ?

编辑02:

我找到了一个新的解决方案, TBitmapSurface ,似乎这个类没有 TBitmap 的限制,我能够在没有修剪的情况下加载图像内部!但有个问题!我怎么能把这个给 TImage ?如果我只是说 Image.bitmap.assign(TBitmapsurface),那么图像会再次被修剪!所以似乎唯一可行的方法是重写 TImage 所以它使用 TBitmapSurface 而不是 TBitmap ,感谢您对此问题的任何帮助。谢谢。
以下是 TBitmapSurface的代码

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);


推荐答案

FMX.Graphics不同。 TBitmap ,其大小限制为 8192 * 8192 FMX.Surface.TBitmapSurface 似乎支持最高 16k * 16k 甚至可能更多(我还没有测试过),所以使用 FMX.Surface.TBitmapSurface 您可以加载图像而不进行修剪,然后您可以轻松地将其拆分为两个 FMX.Graphics.TBitmap (或使用相同方法可能更多的部分)

您可以在下面看到首先将 JPG 加载到 TBitmapSurface 中的代码,然后将其拆分为两个 TBitmap 的代码:

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;  

这个答案是使用第一篇文章的评论和我的其他问题的答案提供的:

如何在FMX.Graphics.TBitmap上绘制FMX.Surface.TBitmapSurface

这篇关于如何在FMX中加载大位图(火猴)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆