Depth8Image.st
changeset 7533 514d5a9f46af
parent 7524 780f829a2e1f
child 7597 5abdbcd771e5
--- a/Depth8Image.st	Wed Aug 31 17:11:57 2016 +0200
+++ b/Depth8Image.st	Wed Aug 31 23:06:44 2016 +0200
@@ -2013,6 +2013,137 @@
 
 !Depth8Image methodsFor:'image manipulations'!
 
+easyRotateBitsInto:destinationImage angle:degrees
+    "tuned helper for rotation - does the actual pixel shuffling, by degrees clockwise. 
+     Here, only 90, 180 and 270 degrees are implemented. 
+     Hard angles are done in #hardRotate:.
+     The code here a tuned version of the inherited for more performance"
+
+    |srcBytesPerRow dstBytesPerRow
+     srcWidth srcHeight
+     dstWidth dstHeight
+     srcBytes dstBytes|
+
+    srcBytesPerRow := self bytesPerRow.
+    srcBytes := self bits.
+    srcWidth := width.
+    srcHeight := height.
+
+    dstBytesPerRow := destinationImage bytesPerRow.
+    dstBytes := destinationImage bits.
+    dstWidth := destinationImage width.
+    dstHeight := destinationImage height.
+%{
+    if (__bothSmallInteger(srcWidth, srcHeight)
+     && __bothSmallInteger(dstWidth, dstHeight)
+     && __bothSmallInteger(dstBytesPerRow, srcBytesPerRow)
+     && __isByteArrayLike(srcBytes)
+     && __isByteArrayLike(dstBytes)
+    ) {
+        int c_srcW = __intVal(srcWidth);
+        int c_srcH = __intVal(srcHeight);
+        int c_dstW = __intVal(dstWidth);
+        int c_dstH = __intVal(dstHeight);
+        int c_srcBytesPerRow = __intVal(srcBytesPerRow);
+        int c_dstBytesPerRow = __intVal(dstBytesPerRow);
+        int c_srcW4 = c_srcW-4;
+        
+        {
+            unsigned char *c_srcBytes = (unsigned char*)__ByteArrayInstPtr(srcBytes)->ba_element;
+            unsigned char *c_dstBytes = (unsigned char*)__ByteArrayInstPtr(dstBytes)->ba_element;
+
+            int c_dstNextRowOffset;
+            int c_dstNextColOffset;
+
+            if (degrees == __mkSmallInteger(90)) {
+                // destinationImage pixelAtX:(h-row) y:col put:pixel
+                c_dstNextRowOffset = -1;                                // going to previous column
+                c_dstNextColOffset = c_dstBytesPerRow;                  // going to next row
+                c_dstBytes += (c_dstW-1);                               // start in the upper-right of dest
+            } else if (degrees == __mkSmallInteger(180)) {
+                // destinationImage pixelAtX:(w-col) y:(h-row) put:pixel
+                c_dstNextRowOffset = -c_dstBytesPerRow;                 // going to previous row
+                c_dstNextColOffset = -1;                                // going to prev col
+                c_dstBytes += (c_dstH-1)*c_dstBytesPerRow+(c_dstW-1);   // start in the lower-right of dest
+            } else {
+                // destinationImage pixelAtX:row y:(w-col) put:pixel
+                c_dstNextRowOffset = 1;                                 // going to next col
+                c_dstNextColOffset = -c_dstBytesPerRow;                 // going to prev row
+                c_dstBytes += (c_dstH-1)*c_dstBytesPerRow;              // start in the lower-left of dest
+            }
+
+            if ((c_srcBytesPerRow * c_srcH) <= __byteArraySize(srcBytes)) {
+                int c_y;
+
+                for (c_y=0; c_y<c_srcH; c_y++) {
+                    unsigned char *c_srcNext = c_srcBytes + c_srcBytesPerRow;
+                    unsigned char *c_dstNext = c_dstBytes + c_dstNextRowOffset;
+                    int c_x;
+
+                    c_x = 0;    
+#if 1
+                    if (sizeof(int) == 4) {
+                        for (c_x = 0; c_x < c_srcW4; c_x += 4) {
+                            int c_value;
+
+                            c_value = ((int *)c_srcBytes)[0];
+
+                            c_dstBytes[0] = (c_value) & 0xFF;
+                            c_dstBytes += c_dstNextColOffset;
+
+                            c_dstBytes[0] = (c_value>>8) & 0xFF;
+                            c_dstBytes += c_dstNextColOffset;
+
+                            c_dstBytes[0] = (c_value>>16) & 0xFF;
+                            c_dstBytes += c_dstNextColOffset;
+
+                            c_dstBytes[0] = (c_value>>24) & 0xFF;
+                            c_dstBytes += c_dstNextColOffset;
+
+                            c_srcBytes += 4;
+                        }
+                    }
+#endif
+                    for (; c_x < c_srcW; c_x++) {
+                        int c_value;
+
+                        c_value = c_srcBytes[0];
+                        c_dstBytes[0] = c_value;
+
+                        c_srcBytes++;
+                        c_dstBytes += c_dstNextColOffset;
+                    }
+                    c_srcBytes = c_srcNext;
+                    c_dstBytes = c_dstNext;
+                }
+                RETURN(self);
+            }
+        }
+    }
+%}.
+    self breakPoint:#cg.
+    super easyRotateBitsInto:destinationImage angle:degrees
+
+    "
+     |i|
+
+     i := Image fromFile:'../../goodies/bitmaps/gifImages/claus.gif'.
+     i inspect.
+     (i rotated:45) inspect.
+     (i rotated:90) inspect.
+     (i rotated:180) inspect.
+     (i rotated:270) inspect.
+    "
+    "
+     |i|
+
+     i := Image fromFile:'../../goodies/bitmaps/gifImages/claus.gif'.
+     Time millisecondsToRun:[
+        1000 timesRepeat:[ (i rotated:90) ].
+     ]
+    "
+!
+
 hardMagnifiedBy:scalePoint
     "return a new image magnified by scalePoint, aPoint.
      This is the general magnification method, handling non-integral values"