简体   繁体   English

如何使用Delphi XE5在IOS上保存位图图片

[英]How to save bitmap pictures on IOS using Delphi XE5

I need to, well would like to save images to the user device (iOS or Android) after I download the image from the interwebs so that the user doesn't have to download the image numerous amount of times. 从互联网下载图像后,我非常需要将图像保存到用户设备(iOS或Android),这样用户不必多次下载图像。

To my understanding, on iOS, I can only save JPG or PNG file formats. 据我了解,在iOS上,我只能保存JPG或PNG文件格式。 How Do I convert a Bitmap file from delphi into a .JPG or .PNG picture file ? 如何将位图文件从delphi转换为.JPG或.PNG图片文件? I see in VCL TPNGImages are supported, but not for FMX. 我在VCL中看到TPNGImage受支持,但FMX不支持。

When I use SomeBitmap.bitmap.SaveToFile(GetHomePath+PathDelim+'Documents'+PathDelim+'Pictures'+PathDelim+PictureName+'.png'; it does not do anything nor throw an exception. Help ? ? 当我使用SomeBitmap.bitmap.SaveToFile(GetHomePath+PathDelim+'Documents'+PathDelim+'Pictures'+PathDelim+PictureName+'.png';它什么也不做,也不会引发异常。

Developing for iOS/Android via Delphi XE5 通过Delphi XE5为iOS / Android开发

TBitmap.SaveToFile works perfectly well (at least on Android - I can't speak to iOS) when given a valid filename and location. 当给定有效的文件名和位置时, TBitmap.SaveToFile可以很好地工作(至少在Android上-我无法与iOS通话)。 If you don't, however, it just silently fails without error, presumably because exceptions are difficult to deal with on some mobile operating systems. 但是,如果不这样做,它只会无提示地静默失败,这可能是因为在某些移动操作系统上很难处理异常。 So the actual problem is with the filename or location being provided, and in this case it would appear that it's the location. 因此,实际的问题是提供的文件名或位置,在这种情况下,似乎是它所在的位置。

Never, ever presume you can guess the folder locations across platforms. 永远不要以为您可以猜测跨平台的文件夹位置。 Always use one of the folders that are returned by the functions in TPath . 始终使用TPath的函数返回的文件夹TPath They're listed in the Delphi documentation under Standard RTL Path Functions across the Supported Target Platforms ; 它们在Delphi文档中的受支持目标平台的“标准RTL路径功能”下列出 in this case, you're looking for TPath.GetPicturesPath , which on Android returns something like '/storage/emulated/0/Pictures' . 在这种情况下,您正在寻找TPath.GetPicturesPath ,它在Android上会返回类似'/storage/emulated/0/Pictures' (According to the documentation, there isn't an accessible pictures directory currently on iOS devices, although there seems to be on the simulator. This may be a limitation of iOS itself; you'd have to check the Apple iOS documentation to determine that, however. The appropriate place on iOS appears to be in the location returned by TPath.GetDocumentsPath , which according to the XE5 documentation is something like '/var/mobile/Applications/<application ID>/Documents' .) (根据文档,尽管模拟器上似乎存在iOS设备上目前没有可访问的图片目录。这可能是iOS本身的限制;您必须查看Apple iOS文档以确定但是,iOS上的合适位置似乎是TPath.GetDocumentsPath返回的位置,根据XE5文档,该位置类似于'/var/mobile/Applications/<application ID>/Documents' 。)

Secondly, never ever manually concatenate parts of a path. 其次,永远不要手动连接路径的各个部分。 Use TPath.Combine (from the IOUtils unit), which will automatically add the path delimiter in the proper location if needed. 使用TPath.Combine (来自IOUtils单元),如果需要,它将自动将路径定界符添加到正确的位置。 If you need to do so, you can chain multiple calls to get the required level of sub-folders: 如果需要,您可以链接多个调用以获取所需级别的子文件夹:

For readability/maintainability (iOS location demonstrated): 为了提高可读性/可维护性(显示iOS位置):

Dest := TPath.Combine(TPath.GetDocumentsPath, 'mydir');
Dest := TPath.Combine(Dest, 'tests');

or (for brevity): 或(为简洁起见):

Dest := TPath.Combine(TPath.Combine(TPath.GetDocumentsPath, 'mydir'), 'tests');

If you need to create the folders along the way, TDirectory.CreateDirectory will create them, as will SysUtils.ForceDirectories ; 如果你需要创建沿途的文件夹, TDirectory.CreateDirectory将创建它们,如将SysUtils.ForceDirectories ; both are available on all supported platforms. 两者在所有受支持的平台上都可用。 (Note that it's the SysUtils version of ForceDirectories that is cross-platform, and not the FileCtrl version, which is Windows-specific.) (请注意,它是SysUtils版本ForceDirectories是跨平台的,而不是FileCtrl版本,这是Windows专用。)

if not TDirectory.Exists(Dest, False) then
  TDirectory.CreateDirectory(Dest);

// or
//  SysUtils.ForceDirectories(Dest);

As far as file formats, FMX.Graphics.TBitmap (through the TBitmapCodecManager class) provides support for the following formats across all supported platforms: 至于文件格式,FMX.Graphics.TBitmap(通过TBitmapCodecManager类)为所有受支持的平台提供以下格式的支持:

JPEG (.jpeg, .jpg) 
TIFF (.tiff, .tif) 
GIF 
PNG 
BMP 

Here's an example of a conversion from bitmap to .png on Windows; 这是Windows上从位图转换为.png的示例; I don't have an Android device to test it on there, but similar code should work for you (provided you specify valid folder locations and file names, as mentioned above). 我没有可在此处进行测试的Android设备,但是类似的代码也可以为您工作(如上所述,前提是您指定了有效的文件夹位置和文件名)。 Compiled and tested on Win7 64 bit, using XE5 Update 2. 使用XE5 Update 2在Win7 64位上进行编译和测试。

procedure TForm1.FormShow(Sender: TObject);
var
  BmpIn, BmpOut: TBitmap;
  SaveParams: TBitmapCodecSaveParams;
begin
  BmpIn := TBitmap.Create;
  try
    BmpIn.LoadFromFile('E:\TempFiles\ScreenCaps\CheckBoxChecked.bmp');

    BmpOut := TBitmap.Create;
    try
      BmpOut.Assign(BmpIn);
      SaveParams.Quality := 100;
      BmpOut.SaveToFile('E:\TempFiles\ScreenCaps\CheckBoxChecked.png', @SaveParams);
    finally
      BmpOut.Free;
    end;
  finally
    BmpIn.Free;
  end;
end;

There are various things to clarify here: 这里有很多事情要澄清:

  1. Put bluntly, the FMX source exhibits an extremely stupid exception-phobia, notwithstanding the fact individual cases can get fixed over time. 坦率地说,FMX源代码显示出非常愚蠢的异常恐惧症,尽管个别案例会随着时间的流逝而得到解决。 One such example of this phobia in XE5 is TBitmap.SaveToFile , which will typically fail silently when given invalid input. XE5中这种恐惧症的一个示例是TBitmap.SaveToFile ,当给出无效输入时,它通常会静默失败。

  2. As Ken White says, you shouldn't assume where a system-defined folder is located. 正如Ken White所说,您不应该假设系统定义的文件夹位于何处。 That said, I'm not so enthusiastic for IOUtils , even though it has to be used (unless you call native API functions directly). 也就是说,即使必须使用IOUtils ,我也不是很热衷(除非您直接调用本机API函数)。 In a nutshell, using a simple PathDelim approach would be perfectly valid but for IOUtils foolishly not respecting traditional Delphi RTL naming conventions in which XxxPath meant 'includes a trailing path delimiter'; 简而言之,使用简单的PathDelim方法将是完全有效的,但对于IOUtils愚蠢地不遵循传统的Delphi RTL命名约定,其中XxxPath意思是“包括尾随路径定界符”。 it is because of this divergence that TPath.Combine comes into play. 正是由于这种差异, TPath.Combine发挥作用。

  3. Your apparent assumption that the FMX TBitmap , like the VCL class, saves to the BMP format is incorrect - it saves to PNG by default. 您明显认为FMX TBitmap与VCL类一样保存为BMP格式是不正确的-默认情况下它保存为PNG。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM