Recent

Author Topic: ColorSpace support in Cocoa  (Read 457 times)

agorka

  • New Member
  • *
  • Posts: 25
ColorSpace support in Cocoa
« on: May 18, 2020, 10:03:36 pm »
Hello!
I'm trying to add support for NSColorSpace to TCocoaBitmap as it's the only way of displaying image colors correctly on OSX.

Some pieces of my code:
Code: Pascal  [Select][+][-]
  1. FN:='System/Library/ColorSync/Profiles/AdobeRGB1998.icc';
  2. LoadBinFile(FN, data, size);
  3. iccData := NSData.dataWithBytes_length(data, size);

Next, i added to CocoaGDIObjects to TCocoaBitmap class these lines

Code: Pascal  [Select][+][-]
  1.     FICCAssigned : Boolean;
  2.     FNSColorSpace : NSColorSpace;
  3.     FNSColorSpaceData : NSData;
  4.     procedure SetColorspace(iccdata: NSData);

Code: Pascal  [Select][+][-]
  1. procedure TCocoaBitmap.SetColorspace(iccdata: NSData);
  2. begin
  3.   FNSColorSpaceData:=iccdata;
  4.  
  5.   if FNSColorSpaceData<>nil then
  6.     Begin
  7.     if FNSColorSpace <>nil then
  8.       Begin
  9.            FNSColorSpace.release;
  10.       end;
  11.     FNSColorSpace:=NSColorSpace.alloc.initWithICCProfileData(FNSColorSpaceData);
  12.     GFNSColorSpace:=NSColorSpace.alloc.initWithICCProfileData(GFNSColorSpaceData);
  13.     FICCAssigned:=True;
  14.     End;
  15.   SetModified;
  16. End;
  17.  

I modified CreateHandle so it would change bitmap profile after creating:

Code: Pascal  [Select][+][-]
  1. procedure TCocoaBitmap.CreateHandle();
  2. var
  3.   HasAlpha: Boolean;
  4.   BitmapFormat: NSBitmapFormat;
  5.   AImageRep: NSBitmapImageRep;
  6. begin
  7.   HasAlpha := FType in [cbtARGB, cbtRGBA, cbtABGR, cbtBGRA];
  8.   // Non premultiplied bitmaps can't be used for bitmap context
  9.   // So we need to pre-multiply ourselves, but only if we were allowed
  10.   // to copy the data, otherwise we might corrupt the original
  11.   if FFreeData then
  12.     PreMultiplyAlpha();
  13.   BitmapFormat := 0;
  14.   if FType in [cbtARGB, cbtABGR, cbtRGB] then
  15.     BitmapFormat := BitmapFormat or NSAlphaFirstBitmapFormat;
  16.  
  17.   //WriteLn('[TCocoaBitmap.Create] FSamplesPerPixel=', FSamplesPerPixel,
  18.   //  ' FData=', DebugShowData());
  19.  
  20.   // Create the associated NSImageRep
  21.   Assert(FImagerep = nil);
  22.   AImageRep := NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh__colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel(
  23.     @FData, // planes, BitmapDataPlanes
  24.     FWidth, // width, pixelsWide
  25.     FHeight,// height, PixelsHigh
  26.     FBitsPerSample,// bitsPerSample, bps
  27.     FSamplesPerPixel, // samplesPerPixel, spp
  28.     HasAlpha, // hasAlpha
  29.     False, // isPlanar
  30.     GetColorSpace, // colorSpaceName
  31.     BitmapFormat, // bitmapFormat
  32.     FBytesPerRow, // bytesPerRow
  33.     FBitsPerPixel //bitsPerPixel
  34.     );
  35.   If FICCAssigned then
  36.   begin
  37.     FImageRep := AImageRep.bitmapImageRepByRetaggingWithColorSpace(FNSColorSpace);
  38.     AImageRep.release;
  39.   end
  40.      else
  41.        FImageRep := AImageRep;
  42.  
  43.   // Create the associated NSImage
  44.   Assert(FImage = nil);
  45.   FImage := NSImage.alloc.initWithSize(NSMakeSize(FWidth, FHeight));
  46.   //pool := NSAutoreleasePool.alloc.init;
  47.   Image.addRepresentation(FImagerep);
  48.   //pool.release;
  49. end;

This works if I first create bitmap and assign icc:
  TCocoaBitmap(Bmp.Handle).SetColorspace(iccData)
But if this bitmap was ever shown, setting it's color space causes an exception in procedure TCocoaBitmap.FreeHandle();
during FImageRep.release;

I'm using latest lazarus from SVN.
I'd like to have this method added to SVN, but I don't know how to do that. I'd be happy to donate to anyone who can help me solving this problem.

Oleg

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2465
    • havefunsoft.com
Re: ColorSpace support in Cocoa
« Reply #1 on: May 27, 2020, 01:54:32 am »
seems like you're proposing a patch.

You might want to follow these guidelines
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

agorka

  • New Member
  • *
  • Posts: 25
Re: ColorSpace support in Cocoa
« Reply #2 on: May 27, 2020, 11:57:42 pm »
Thank you for answering!
But before proposing a patch I'd like to make it work correctly. I can't understand why it crashes on FImageRep.release.
Is it save just to comment this line out or will it cause leaks?

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2465
    • havefunsoft.com
Re: ColorSpace support in Cocoa
« Reply #3 on: May 28, 2020, 12:52:19 am »
I guess this is the reason
Code: Pascal  [Select][+][-]
  1.     FImageRep := AImageRep.bitmapImageRepByRetaggingWithColorSpace(FNSColorSpace);
  2.     AImageRep.release; // don't release here!
  3.  
according to the description "bitmapImageRepByRetaggingWithColorSpace" converts the imagerep to the colorspace.
It doesn't say that it allocates the imageRep, it's likely the returned object is exactly the same. (you might want to debug, to verify if FImageRep = AImageRep right after the call to bitmapImageRepByRetaggingWithColorSpace).

Now, the bigger question is what the code should do, if the color space conversion failed
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

agorka

  • New Member
  • *
  • Posts: 25
Re: ColorSpace support in Cocoa
« Reply #4 on: May 29, 2020, 09:03:35 am »
I stopped the program right after bitmapImageRepByRetaggingWithColorSpace.
Here's the values
AImageRep^ = NSBitmapImageRep (ISA = $001DFFFF890EE289;
 __REPFLAGS = {record}($0000000112363248);
 _COLORSPACENAME = $00007FFF88DB8568;
 _SIZE = CGSIZE($0000000112363258);
 _PIXELSWIDE = 499;
 _PIXELSHIGH = 0;
 __MOREREPFLAGS = {record}($0000000112363270);
 _BYTESPERROW = 0;
 _DATAOBJ = $0000000000011020;
 _TIFFDATA = $0000000114F04EF0;
 _PROPERTIES = nil)

FImageRep^=NSBitmapImageRep (ISA = $00007FFF890EE288;
 __REPFLAGS = {record}($0000000114F03FB8);
 _COLORSPACENAME = $00007FFF88DB8568;
 _SIZE = CGSIZE($0000000114F03FC8);
 _PIXELSWIDE = 499;
 _PIXELSHIGH = 0;
 __MOREREPFLAGS = {record}($0000000114F03FE0);
 _BYTESPERROW = 0;
 _DATAOBJ = $0000000000011020;
 _TIFFDATA = $0000000114F0D050;
 _PROPERTIES = nil)

It seems to be different pointers except DATAOBJ.
I removed release from CreateHandle and restored it in CocoaBitmap.FreeHandle, it started to crash again.

 

TinyPortal © 2005-2018