--- 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"