#BUGFIX by cg
authorClaus Gittinger <cg@exept.de>
Sat, 25 Feb 2017 11:44:42 +0100
changeset 21580 b0c093983502
parent 21579 3500c59c4d3e
child 21581 20d4f3a38e2c
#BUGFIX by cg class: OSXOperatingSystem added: #getFrameBufferImage:in: fixed: #getFrameBufferImage:
OSXOperatingSystem.st
--- 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$'
 ! !
+