cocoa: cocoa does not support BGR(A) bitmaps

git-svn-id: trunk@38807 -
This commit is contained in:
paul 2012-09-24 09:17:49 +00:00
parent bc0f56fefe
commit 05b660c8dc
5 changed files with 96 additions and 54 deletions

View File

@ -27,9 +27,7 @@ type
cbtGray, // grayscale bitmap
cbtRGB, // color bitmap 8-8-8 R-G-B
cbtARGB, // color bitmap with alpha channel first 8-8-8-8 A-R-G-B
cbtRGBA, // color bitmap with alpha channel last 8-8-8-8 R-G-B-A
cbtBGR, // color bitmap 8-8-8 B-G-R (windows compatible)
cbtBGRA // color bitmap with alpha channel 8-8-8-8 B-G-R-A (windows compatible)
cbtRGBA // color bitmap with alpha channel last 8-8-8-8 R-G-B-A
);
const
@ -728,15 +726,14 @@ begin
FFreeData := False;
end;
HasAlpha := AType in [cbtARGB, cbtRGBA, cbtBGRA];
BitmapFormat := NSAlphaNonpremultipliedBitmapFormat;
if AType = cbtARGB then
HasAlpha := AType in [cbtARGB, cbtRGBA];
if HasAlpha then
BitmapFormat := NSAlphaNonpremultipliedBitmapFormat
else
BitmapFormat := 0;
if AType in [cbtARGB, cbtRGB] then
BitmapFormat := BitmapFormat or NSAlphaFirstBitmapFormat;
{$ifdef VerboseBitmaps}
DebugLn(Format('[TCocoaBitmap.Create] NSBitmapImageRep.alloc HasAlpha=%d',
[Integer(HasAlpha)]));
{$endif}
// Create the associated NSImageRep
FImagerep := NSBitmapImageRep(NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh__colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel(
@FData, // planes, BitmapDataPlanes
@ -820,7 +817,7 @@ begin
32:
begin
FBitsPerSample := 8;
if AType in [cbtRGB, cbtBGR] then
if AType = cbtRGB then
FSamplesPerPixel := 3
else
FSamplesPerPixel := 4;
@ -2484,7 +2481,6 @@ end;
procedure TCocoaBrush.SetImage(AImage: NSImage);
var
AWidth, AHeight: Single;
ACallBacks: CGPatternCallbacks;
Rect: CGRect;
begin

View File

@ -125,7 +125,7 @@ type
function RawImage_DescriptionFromCocoaBitmap(out ADesc: TRawImageDescription; ABitmap: TCocoaBitmap): Boolean;
function RawImage_FromCocoaBitmap(out ARawImage: TRawImage; ABitmap, AMask: TCocoaBitmap; ARect: PRect = nil): Boolean;
function RawImage_DescriptionToBitmapType(ADesc: TRawImageDescription; out bmpType: TCocoaBitmapType): Boolean;
// function GetImagePixelData(AImage: CGImageRef; var bitmapByteCount: PtrUInt): Pointer;
function GetImagePixelData(AImage: CGImageRef; out bitmapByteCount: PtrUInt): Pointer;
property NSApp: NSApplication read FNSApp;
// the winapi compatibility methods
{$I cocoawinapih.inc}

View File

@ -433,7 +433,84 @@ begin
then Result := RawImage_FromCocoaBitmap(ARawImage, TCocoaBitmap(ABitmap), TCocoaBitmap(AMask), ARect)
else Result := False;
end;
(*
{------------------------------------------------------------------------------
Method: TCocoaWidgetSet.GetImagePixelData
Used by RawImage_FromDevice. Copies the data from a CGImageRef into a local
buffer.
The buffer is created using GetMem, and the caller is responsible for using
FreeMem to free the returned pointer.
This function throws exceptions in case of errors and may return a nil pointer.
------------------------------------------------------------------------------}
function TCocoaWidgetSet.GetImagePixelData(AImage: CGImageRef; out bitmapByteCount: PtrUInt): Pointer;
var
bitmapData: Pointer;
context: CGContextRef = nil;
colorSpace: CGColorSpaceRef;
bitmapBytesPerRow, pixelsWide, pixelsHigh: PtrUInt;
imageRect: CGRect;
begin
Result := nil;
// Get image width, height. The entire image is used.
pixelsWide := CGImageGetWidth(AImage);
pixelsHigh := CGImageGetHeight(AImage);
imageRect.origin.x := 0.0;
imageRect.origin.y := 0.0;
imageRect.size.width := pixelsWide;
imageRect.size.height := pixelsHigh;
// The target format is fixed in ARGB, DQWord alignment, with 32-bits depth and
// 8-bits per channel, the default image format on the LCL
bitmapBytesPerRow := ((pixelsWide * 4) + $F) and not PtrUInt($F);
bitmapByteCount := (bitmapBytesPerRow * pixelsHigh);
// Use the generic RGB color space.
colorSpace := CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
if (colorSpace = nil) then
raise Exception.Create('Unable to create CGColorSpaceRef');
// Allocate memory for image data. This is the destination in memory
// where any drawing to the bitmap context will be rendered.
bitmapData := System.GetMem( bitmapByteCount );
if (bitmapData = nil) then
raise Exception.Create('Unable to allocate memory');
{ Creates the bitmap context.
Regardless of what the source image format is, it will be converted
over to the format specified here by CGBitmapContextCreate. }
context := CGBitmapContextCreate(bitmapData,
pixelsWide,
pixelsHigh,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaNoneSkipFirst); // The function fails with kCGImageAlphaFirst
if (context = nil) then
begin
System.FreeMem(bitmapData);
raise Exception.Create('Unable to create CGContextRef');
end;
// Draw the image to the bitmap context. Once we draw, the memory
// allocated for the context for rendering will then contain the
// raw image data in the specified color space.
CGContextDrawImage(context, imageRect, AImage);
// Now we can get a pointer to the image data associated with the context.
// ToDo: Verify if we should copy this data to a new buffer
Result := CGBitmapContextGetData(context);
{ Clean-up }
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
end;
{------------------------------------------------------------------------------
Function: RawImage_FromDevice
Params: ARawImage: Image to create
@ -458,9 +535,9 @@ end;
http://developer.apple.com/qa/qa2007/qa1509.html
------------------------------------------------------------------------------}
function TCarbonWidgetSet.RawImage_FromDevice(out ARawImage: TRawImage; ADC: HDC; const ARect: TRect): Boolean;
function TCocoaWidgetSet.RawImage_FromDevice(out ARawImage: TRawImage; ADC: HDC; const ARect: TRect): Boolean;
var
CBC: TCarbonBitmapContext absolute ADC;
CBC: TCocoaBitmapContext absolute ADC;
Desc: TRawImageDescription absolute ARawImage.Description;
displayID: CGDirectDisplayID;
ScreenImage: CGImageRef;
@ -469,9 +546,9 @@ begin
// Verifies if we are getting the rawimage from a normal DC as opposed to a
// desktop DC
if CheckDC(ADC, 'RawImage_FromDevice') and (CBC is TCarbonBitmapContext) then
if CheckDC(ADC, 'RawImage_FromDevice') and (CBC is TCocoaBitmapContext) then
begin
Result := RawImage_FromCarbonBitmap(ARawImage, CBC.Bitmap, nil, @ARect);
Result := RawImage_FromCocoaBitmap(ARawImage, CBC.Bitmap, nil, @ARect);
Exit;
end;
@ -479,8 +556,7 @@ begin
{ Get's a screenshot }
displayID := CGMainDisplayID();
ScreenImage := grabViaOpenGL(displayID, CGDisplayBounds(displayID));
//dataProvider := CGImageGetDataProvider(ScreenImage);
ScreenImage := CGDisplayCreateImage(displayID);
{ Fills the image description }
ARawImage.Init;
@ -509,7 +585,7 @@ end;
//begin
// // override only when queried formats are different from screen description
//end;
(*
{------------------------------------------------------------------------------
Method: ReleaseDesignerDC
Params: Window - handle of window

View File

@ -52,9 +52,9 @@ function RawImage_CreateBitmaps(const ARawImage: TRawImage; out ABitmap, AMask:
function RawImage_DescriptionFromBitmap(ABitmap: HBITMAP; out ADesc: TRawImageDescription): Boolean; override;
function RawImage_DescriptionFromDevice(ADC: HDC; out ADesc: TRawImageDescription): Boolean; override;
function RawImage_FromBitmap(out ARawImage: TRawImage; ABitmap, AMask: HBITMAP; ARect: PRect = nil): Boolean; override;
{function RawImage_FromDevice(out ARawImage: TRawImage; ADC: HDC; const ARect: TRect): Boolean; override;
function RawImage_FromDevice(out ARawImage: TRawImage; ADC: HDC; const ARect: TRect): Boolean; override;
// override only when queried formats are different from screen description
//function RawImage_QueryDescription(AFlags: TRawImageQueryFlags; var ADesc: TRawImageDescription): Boolean; override;
function ReleaseDesignerDC(Window: HWND; DC: HDC): Integer; override;}
{function ReleaseDesignerDC(Window: HWND; DC: HDC): Integer; override;}

View File

@ -527,7 +527,7 @@ begin
if ADesc.Format = ricfGray then Exit;
// alpha
if ABitmap.BitmapType in [cbtARGB, cbtRGBA, cbtBGRA] then
if ABitmap.BitmapType in [cbtARGB, cbtRGBA] then
ADesc.AlphaPrec := Prec;
case ABitmap.BitmapType of
@ -539,14 +539,6 @@ begin
Dec(Shift, Prec);
ADesc.BlueShift := Shift;
end;
cbtBGR: begin
Shift := 32 - Prec;
ADesc.BlueShift := Shift;
Dec(Shift, Prec);
ADesc.GreenShift := Shift;
Dec(Shift, Prec);
ADesc.RedShift := Shift;
end;
cbtARGB: begin
Shift := 32 - Prec;
ADesc.AlphaShift := Shift;
@ -567,16 +559,6 @@ begin
Dec(Shift, Prec);
ADesc.AlphaShift := Shift;
end;
cbtBGRA: begin
Shift := 32 - Prec;
ADesc.BlueShift := Shift;
Dec(Shift, Prec);
ADesc.GreenShift := Shift;
Dec(Shift, Prec);
ADesc.RedShift := Shift;
Dec(Shift, Prec);
ADesc.AlphaShift := Shift;
end;
end;
Result := True;
@ -646,21 +628,9 @@ begin
and (ADesc.GreenShift = 16 )
and (ADesc.BlueShift = 8 )
then bmpType := cbtRGBA
else
if (ADesc.AlphaShift = 0 )
and (ADesc.RedShift = 8 )
and (ADesc.GreenShift = 16)
and (ADesc.BlueShift = 24)
then bmpType := cbtBGRA
else Exit;
end
else begin
if (ADesc.AlphaShift = 24)
and (ADesc.RedShift = 16)
and (ADesc.GreenShift = 8 )
and (ADesc.BlueShift = 0 )
then bmpType := cbtBGRA
else
if (ADesc.AlphaShift = 0 )
and (ADesc.RedShift = 8 )
and (ADesc.GreenShift = 16)