0

How to convert an NSImage to Delphis FireMonkey TBitmap? The NSImage is being passed to me from an Objective C API. I am using Delphi XE8.

Nader
  • 47
  • 1
  • 8
  • This link looks promising http://stackoverflow.com/questions/3038820/how-to-save-a-nsimage-as-a-new-file – Jens Borrisholt Oct 13 '15 at 08:06
  • 1
    Thanks, but I am not looking to save the image to a file, I need to convert NSImage object instance received from Objective C API to a Delphi FireMonkey TBitmap instance... – Nader Oct 13 '15 at 14:36

1 Answers1

-1

Try using NSImage.TIFFRepresentation data. Save it to memory stream and then load TBitmap from the stream. Another way is using NSImage.CGImageForProposedRect, you may find a sample here: https://delphi-foundations.googlecode.com/svn/trunk/FMX%20Utilities/CCR.FMXClipboard.Mac.pas https://delphi-foundations.googlecode.com/svn/trunk/XE2%20book/13.%20Native%20APIs/Taking%20a%20screenshot/ScreenshotForm.pas

Update: OK, here comes my solution:

function PutBytesCallback(info: Pointer; buffer: Pointer; count: Longword): Longword; cdecl;
begin
  Result := TStream(info).Write(buffer^, count)
end;

procedure ReleaseConsumerCallback(info: Pointer); cdecl;
begin
end;

function NSImageToBitmap(Image: NSImage; Bitmap: TBitmap): Boolean;
var
  LStream: TMemoryStream;
  LCGImageRef: CGImageRef;
  LCallbacks: CGDataConsumerCallbacks;
  LConsumer: CGDataConsumerRef;
  LImageDest: CGImageDestinationRef;
begin
  Result := False;
  LStream := TMemoryStream.Create;
  LImageDest := nil;
  LConsumer := nil;
  try
    LCallbacks.putBytes := PutBytesCallback;
    LCallbacks.releaseConsumer := ReleaseConsumerCallback;
    LCGImageRef := Image.CGImageForProposedRect(nil, nil, nil);
    LConsumer := CGDataConsumerCreate(LStream, @LCallbacks);
    if LConsumer <> nil then
      LImageDest := CGImageDestinationCreateWithDataConsumer(LConsumer, CFSTR('public.png'), 1, nil);
    if LImageDest <> nil then
    begin
      CGImageDestinationAddImage(LImageDest, LCGImageRef, nil);
      CGImageDestinationFinalize(LImageDest);
      LStream.Position := 0;
      Bitmap.LoadFromStream(LStream);
      Result := True
    end
  finally
    if LImageDest <> nil then CFRelease(LImageDest);
    if LConsumer <> nil then CGDataConsumerRelease(LConsumer);
    LStream.Free
  end;
end;