简体   繁体   中英

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.

To my understanding, on iOS, I can only save JPG or PNG file formats. How Do I convert a Bitmap file from delphi into a .JPG or .PNG picture file ? I see in VCL TPNGImages are supported, but not for 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 ? ?

Developing for iOS/Android via Delphi XE5

TBitmap.SaveToFile works perfectly well (at least on Android - I can't speak to iOS) when given a valid filename and location. 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 . They're listed in the Delphi documentation under Standard RTL Path Functions across the Supported Target Platforms ; in this case, you're looking for TPath.GetPicturesPath , which on Android returns something like '/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' .)

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. 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):

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

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:

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

Here's an example of a conversion from bitmap to .png on Windows; 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). Compiled and tested on Win7 64 bit, using XE5 Update 2.

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. One such example of this phobia in XE5 is TBitmap.SaveToFile , which will typically fail silently when given invalid input.

  2. As Ken White says, you shouldn't assume where a system-defined folder is located. That said, I'm not so enthusiastic for IOUtils , even though it has to be used (unless you call native API functions directly). 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'; it is because of this divergence that TPath.Combine comes into play.

  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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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