#BUGFIX by cg
class: OSXOperatingSystem
added: #getFrameBufferImage:in:
fixed: #getFrameBufferImage:
--- a/OSXOperatingSystem.st Fri Feb 24 21:57:08 2017 +0100
+++ b/OSXOperatingSystem.st Sat Feb 25 11:44:42 2017 +0100
@@ -392,73 +392,128 @@
getFrameBufferImage:displayNr
"returns the framebuffer as an image object"
- |width height bytesPerPixel address pixels depth pad img|
+ ^ self getFrameBufferImage:displayNr in:nil
+
+ "
+ self getFrameBufferImage:0
+ "
+
+ "Modified: / 25-02-2017 / 10:57:17 / cg"
+!
+getFrameBufferImage:displayNr in:aRectangleOrNil
+ "returns the framebuffer as an image object"
+
+ |rx ry rwidth rheight bytesPerPixel bytesPerRow address pixels depth pad img|
+
+ aRectangleOrNil notNil ifTrue:[
+ rx := aRectangleOrNil left.
+ ry := aRectangleOrNil top.
+ rwidth := aRectangleOrNil width.
+ rheight := aRectangleOrNil height.
+ ].
%{
#ifndef NO_QUARTZ
- CGImageRef image_ref = CGDisplayCreateImage(CGMainDisplayID());
- CGDataProviderRef provider = CGImageGetDataProvider(image_ref);
- CFDataRef dataref = CGDataProviderCopyData(provider);
- size_t c_width, c_height;
+ CGImageRef image_ref;
+ CGDirectDisplayID displayID = CGMainDisplayID();
+
+ if (rx == nil) {
+ image_ref = CGDisplayCreateImage(displayID);
+ } else {
+ CGRect rect;
+ rect.origin.x = (CGFloat)__intVal(rx);
+ rect.origin.y = (CGFloat)__intVal(rx);
+ rect.size.width = (CGFloat)__intVal(rwidth);
+ rect.size.height = (CGFloat)__intVal(rheight);
+ image_ref = CGDisplayCreateImageForRect(displayID, rect);
+ }
+
+ if (image_ref != NULL) {
+ CGDataProviderRef provider = CGImageGetDataProvider(image_ref);
+ CFDataRef dataref = CGDataProviderCopyData(provider);
+ size_t c_width = CGImageGetWidth(image_ref);
+ size_t c_height = CGImageGetHeight(image_ref);
+ size_t c_bytesPerRow = CGImageGetBytesPerRow(image_ref);
+ size_t c_bytesPerPixel = CGImageGetBitsPerPixel(image_ref) / 8;
+ unsigned char *c_pixels = CFDataGetBytePtr(dataref);
- c_width = CGImageGetWidth(image_ref);
- c_height = CGImageGetHeight(image_ref);
- size_t c_bytesPerPixel = CGImageGetBitsPerPixel(image_ref) / 8;
- pixels = __BYTEARRAY_UNINITIALIZED_NEW_INT(c_width * c_height * c_bytesPerPixel);
- // uint8 *pixels = malloc(c_width * c_height * c_bytesPerPixel);
- memcpy(__byteArrayVal(pixels), CFDataGetBytePtr(dataref), c_width * c_height * c_bytesPerPixel);
- CFRelease(dataref);
- CGImageRelease(image_ref);
-
- width = __MKUINT( c_width );
- height = __MKUINT( c_height );
- bytesPerPixel = __MKUINT( c_bytesPerPixel );
+ pixels = __BYTEARRAY_UNINITIALIZED_NEW_INT(c_width * c_height * c_bytesPerPixel);
-// CGDisplayBaseAddress is deprecated
-//
-// int i, saveFD = -1;
-// uint32_t rowBytes, rowUInt32s, *screen;
-//
-// CGDirectDisplayID targetDisplay = 0;
-//
-// // populate targetDisplay as in Figure 10.23
-// // use listDisplays() from Figure 10.23
-// // ...
-//
-// screen = (uint32_t *)CGDisplayBaseAddress(targetDisplay);
-// rowBytes = CGDisplayBytesPerRow(targetDisplay);
-// rowUInt32s = rowBytes / 4;
-// width = __MKUINT( CGDisplayPixelsWide(targetDisplay) );
-// height = __MKUINT( CGDisplayPixelsHigh(targetDisplay) );
+ if (c_bytesPerPixel == 4) {
+ int row;
+ unsigned char *srcRowPtr = c_pixels;
+ unsigned char *dstRowPtr = __byteArrayVal(pixels);
+
+ for (row=c_height; row>0; row--) {
+ int col;
+ unsigned int *pixSrcPtr = (int*)srcRowPtr;
+ unsigned int *pixDstPtr = (int*)dstRowPtr;
+
+ // swap abgr to argb
+ for (col=c_width; col>0;col--) {
+ unsigned int pix = *pixSrcPtr++;
-// for (i = 0; i < height; i++)
-// write(saveFD, screen + i * rowUInt32s, width * sizeof(uint32_t));
-//
+ pix = ((pix >> 16) & 0x0000FF)|((pix << 16) & 0xFF0000)|(pix & 0x00FF00);
+ *pixDstPtr++ = pix;
+ }
+ dstRowPtr += c_width * c_bytesPerPixel;
+ srcRowPtr += c_bytesPerRow;
+ }
+ } else {
+ }
+ CFRelease(dataref);
+ CGImageRelease(image_ref);
+
+ rwidth = __MKUINT( c_width );
+ rheight = __MKUINT( c_height );
+ bytesPerPixel = __MKUINT( c_bytesPerPixel );
+ bytesPerRow = __MKUINT( c_bytesPerRow );
+ }
+
+ // the following is no longer supported by apple
+ // CGDisplayBaseAddress is deprecated
+ //
+ // uint32_t rowBytes, rowUInt32s, *screen;
+ //
+ // CGDirectDisplayID targetDisplay = 0;
+ //
+ // screen = (uint32_t *)CGDisplayBaseAddress(targetDisplay);
+ // rowBytes = CGDisplayBytesPerRow(targetDisplay);
+ // rowUInt32s = rowBytes / 4;
+ // rwidth = __MKUINT( CGDisplayPixelsWide(targetDisplay) );
+ // rheight = __MKUINT( CGDisplayPixelsHigh(targetDisplay) );
+ //
+
#endif // NO_QUARTZ
%}.
- width isNil ifTrue:[
- ^ self primitiveFailed
+ rwidth isNil ifTrue:[
+ ^ self primitiveFailed
].
- Transcript printf:'w:%d h:%d bpp:%d\n' withAll:{ width . height . bytesPerPixel }.
-
depth := bytesPerPixel * 8.
- Transcript printf:'d:%d\n' withAll:{ depth }.
-
- "/ MUST swap r and b channels - sigh
- "/ pixels swapBGRtoRGB
+ "/ Transcript printf:'w:%d h:%d bpp:%d depth:%d bpr: %d\n'
+ "/ withAll:{ rwidth . rheight . bytesPerPixel . depth . bytesPerRow}.
- img := Image extent:(width @ height) depth:depth bits:pixels.
- depth >= 24 ifFalse:[
- "/ check what we get here...
- ^ self primitiveFailed:'unsupported depth'
+ ( #(16 32) includes:depth) ifFalse:[
+ "/ check what we get here...
+ ^ self primitiveFailed:'unsupported depth'
].
- img bitsPerSample:#[8 8 8].
- img samplesPerPixel:3.
+ img := Image extent:(rwidth @ rheight) depth:depth bits:pixels.
+
+ img bitsPerSample:#[8 8 8 8].
+ img samplesPerPixel:4.
img photometric:#rgb.
^ img
+
+ "
+ self getFrameBufferImage:0 in:nil
+ self getFrameBufferImage:0 in:(100@100 corner:301@303)
+ "
+
+ "Created: / 25-02-2017 / 09:49:07 / cg"
+ "Modified: / 25-02-2017 / 11:42:48 / cg"
! !
!OSXOperatingSystem class methodsFor:'documentation'!
@@ -470,3 +525,4 @@
version_CVS
^ '$Header$'
! !
+