summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'leptonica/prog/rotatefastalt.c')
-rw-r--r--leptonica/prog/rotatefastalt.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/leptonica/prog/rotatefastalt.c b/leptonica/prog/rotatefastalt.c
new file mode 100644
index 00000000..6dbda05d
--- /dev/null
+++ b/leptonica/prog/rotatefastalt.c
@@ -0,0 +1,351 @@
+/*====================================================================*
+ - Copyright (C) 2001 Leptonica. All rights reserved.
+ -
+ - Redistribution and use in source and binary forms, with or without
+ - modification, are permitted provided that the following conditions
+ - are met:
+ - 1. Redistributions of source code must retain the above copyright
+ - notice, this list of conditions and the following disclaimer.
+ - 2. Redistributions in binary form must reproduce the above
+ - copyright notice, this list of conditions and the following
+ - disclaimer in the documentation and/or other materials
+ - provided with the distribution.
+ -
+ - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
+ - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *====================================================================*/
+
+
+/*
+ * rotatefastalt.c
+ *
+ * Alternative (slightly slower) method for rotating color images,
+ * with antialiasing. This is here just for comparison with
+ * the better methods in the library.
+ *
+ * Includes these functions:
+ * pixRotateAMColorFast2()
+ * pixShiftRGB258()
+ * rotateAMColorFastLow2()
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config_auto.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <math.h> /* required for sin and tan */
+#include "allheaders.h"
+
+static const l_float32 VERY_SMALL_ANGLE = 0.001; /* radians; ~0.06 degrees */
+
+static PIX *pixRotateAMColorFast2(PIX *pixs, l_float32 angle, l_uint8 grayval);
+static PIX *pixShiftRGB258(PIX *pixs);
+static void rotateAMColorFastLow2(l_uint32 *datad, l_int32 w, l_int32 h,
+ l_int32 wpld, l_uint32 *datas,
+ l_int32 wpls, l_float32 angle,
+ l_uint8 grayval);
+
+int main(int argc,
+ char **argv)
+{
+char *filein, *fileout;
+l_float32 angle, deg2rad;
+PIX *pixs, *pixd;
+static char mainName[] = "rotatefastalt";
+
+ if (argc != 4)
+ return ERROR_INT("Syntax: rotatefastalt filein angle fileout",
+ mainName, 1);
+ filein = argv[1];
+ angle = atof(argv[2]);
+ fileout = argv[3];
+
+ setLeptDebugOK(1);
+ deg2rad = 3.1415926535 / 180.;
+ if ((pixs = pixRead(filein)) == NULL)
+ return ERROR_INT("pixs not read", mainName, 1);
+
+ startTimer();
+ pixd = pixRotateAMColorFast2(pixs, deg2rad * angle, 255);
+ lept_stderr("Time for rotation: %7.3f sec\n", stopTimer());
+ pixWrite(fileout, pixd, IFF_JFIF_JPEG);
+
+ pixDestroy(&pixs);
+ pixDestroy(&pixd);
+ return 0;
+}
+
+
+/*!
+ * pixRotateAMColorFast2()
+ *
+ * Input: pixs
+ * angle (radians; clockwise is positive)
+ * grayval (0 to bring in BLACK, 255 for WHITE)
+ * Return: pixd, or null on error
+ *
+ * Notes:
+ * - This rotates a color image about the image center.
+ * A positive angle gives a clockwise rotation.
+ * - It uses area mapping, dividing each pixel into
+ * 16 subpixels.
+ * - It creates a temporary 32-bit color image.
+ * - It is slightly slower than pixRotateAMColorFast(),
+ * which uses less memory because it does not create
+ * a temporary image.
+ *
+ * *** Warning: implicit assumption about RGB component ordering ***
+ */
+PIX *
+pixRotateAMColorFast2(PIX *pixs,
+ l_float32 angle,
+ l_uint8 grayval)
+{
+l_int32 w, h, wpls, wpld;
+l_uint32 *datas, *datad;
+PIX *pixshft, *pixd;
+
+ PROCNAME("pixRotateAMColorFast2");
+
+ if (!pixs)
+ return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+ if (pixGetDepth(pixs) != 32)
+ return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);
+
+ if (L_ABS(angle) < VERY_SMALL_ANGLE)
+ return pixClone(pixs);
+
+ if ((pixshft = pixShiftRGB258(pixs)) == NULL)
+ return (PIX *)ERROR_PTR("pixshft not defined", procName, NULL);
+
+ w = pixGetWidth(pixshft);
+ h = pixGetHeight(pixshft);
+ datas = pixGetData(pixshft);
+ wpls = pixGetWpl(pixshft);
+ pixd = pixCreateTemplate(pixshft);
+ datad = pixGetData(pixd);
+ wpld = pixGetWpl(pixd);
+ rotateAMColorFastLow2(datad, w, h, wpld, datas, wpls, angle, grayval);
+
+ pixDestroy(&pixshft);
+ return pixd;
+}
+
+
+/*!
+ * pixShiftRGB258()
+ *
+ * Makes a new 32 bpp image with the R, G and B components
+ * right-shifted by 2, 5 and 8 bits, respectively.
+ */
+PIX *
+pixShiftRGB258(PIX *pixs)
+{
+l_int32 w, h, wpls, wpld, i, j;
+l_uint32 word;
+l_uint32 *datas, *datad, *lines, *lined;
+PIX *pixd;
+
+ PROCNAME("pixShift258");
+
+ if (!pixs)
+ return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+ if (pixGetDepth(pixs) != 32)
+ return (PIX *)ERROR_PTR("depth not 32 bpp", procName, NULL);
+ w = pixGetWidth(pixs);
+ h = pixGetHeight(pixs);
+ wpls = pixGetWpl(pixs);
+ datas = pixGetData(pixs);
+
+ if ((pixd = pixCreate(w, h, 32)) == NULL)
+ return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
+ wpld = pixGetWpl(pixd);
+ datad = pixGetData(pixd);
+
+ for (i = 0; i < h; i++) {
+ lines = datas + i * wpls;
+ lined = datad + i * wpld;
+ for (j = 0; j < w; j++) {
+ word = *(lines + j);
+ *(lined + j) = ((word & 0xff000000) >> 2) |
+ ((word & 0x00ff0000) >> 5) |
+ ((word & 0x0000ff00) >> 8);
+ }
+ }
+
+ return pixd;
+}
+
+
+/*!
+ * rotateAMColorFastLow2()
+ *
+ * Alternative version for fast color rotation
+ *
+ * *** Warning: explicit assumption about RGB component ordering ***
+ */
+void
+rotateAMColorFastLow2(l_uint32 *datad,
+ l_int32 w,
+ l_int32 h,
+ l_int32 wpld,
+ l_uint32 *datas,
+ l_int32 wpls,
+ l_float32 angle,
+ l_uint8 grayval)
+{
+l_int32 i, j, xcen, ycen, wm2, hm2;
+l_int32 xdif, ydif, xpm, ypm, xp, yp, xf, yf;
+l_uint32 edgeval, word;
+l_uint32 *pword, *lines, *lined;
+l_float32 sina, cosa;
+
+ xcen = w / 2;
+ wm2 = w - 2;
+ ycen = h / 2;
+ hm2 = h - 2;
+ sina = 4. * sin(angle);
+ cosa = 4. * cos(angle);
+
+ edgeval = (grayval << 24) | (grayval << 16) | (grayval << 8);
+ for (i = 0; i < h; i++) {
+ ydif = ycen - i;
+ lined = datad + i * wpld;
+ for (j = 0; j < w; j++) {
+ xdif = xcen - j;
+ xpm = (l_int32)(-xdif * cosa - ydif * sina + 0.5);
+ ypm = (l_int32)(-ydif * cosa + xdif * sina + 0.5);
+ xp = xcen + (xpm >> 2);
+ yp = ycen + (ypm >> 2);
+ xf = xpm & 0x03;
+ yf = ypm & 0x03;
+
+ /* if off the edge, write the input grayval */
+ if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) {
+ *(lined + j) = edgeval;
+ continue;
+ }
+
+ lines = datas + yp * wpls;
+ pword = lines + xp;
+
+ switch (xf + 4 * yf)
+ {
+ case 0:
+ word = *pword;
+ *(lined + j) = ((word & 0x3fc00000) << 2) |
+ ((word & 0x0007f800) << 5) |
+ ((word & 0x000000ff) << 8);
+ break;
+ case 1:
+ word = 3 * (*pword) + *(pword + 1);
+ *(lined + j) = (word & 0xff000000) |
+ ((word & 0x001fe000) << 3) |
+ ((word & 0x000003fc) << 6);
+ break;
+ case 2:
+ word = *pword + *(pword + 1);
+ *(lined + j) = ((word & 0x7f800000) << 1) |
+ ((word & 0x000ff000) << 4) |
+ ((word & 0x000001fe) << 7);
+ break;
+ case 3:
+ word = *pword + 3 * (*(pword + 1));
+ *(lined + j) = (word & 0xff000000) |
+ ((word & 0x001fe000) << 3) |
+ ((word & 0x000003fc) << 6);
+ break;
+ case 4:
+ word = 3 * (*pword) + *(pword + wpls);
+ *(lined + j) = (word & 0xff000000) |
+ ((word & 0x001fe000) << 3) |
+ ((word & 0x000003fc) << 6);
+ break;
+ case 5:
+ word = 2 * (*pword) + *(pword + 1) + *(pword + wpls);
+ *(lined + j) = (word & 0xff000000) |
+ ((word & 0x001fe000) << 3) |
+ ((word & 0x000003fc) << 6);
+ break;
+ case 6:
+ word = *pword + *(pword + 1);
+ *(lined + j) = ((word & 0x7f800000) << 1) |
+ ((word & 0x000ff000) << 4) |
+ ((word & 0x000001fe) << 7);
+ break;
+ case 7:
+ word = *pword + 2 * (*(pword + 1)) + *(pword + wpls + 1);
+ *(lined + j) = (word & 0xff000000) |
+ ((word & 0x001fe000) << 3) |
+ ((word & 0x000003fc) << 6);
+ break;
+ case 8:
+ word = *pword + *(pword + wpls);
+ *(lined + j) = ((word & 0x7f800000) << 1) |
+ ((word & 0x000ff000) << 4) |
+ ((word & 0x000001fe) << 7);
+ break;
+ case 9:
+ word = *pword + *(pword + wpls);
+ *(lined + j) = ((word & 0x7f800000) << 1) |
+ ((word & 0x000ff000) << 4) |
+ ((word & 0x000001fe) << 7);
+ break;
+ case 10:
+ word = *pword + *(pword + 1) + *(pword + wpls) +
+ *(pword + wpls + 1);
+ *(lined + j) = (word & 0xff000000) |
+ ((word & 0x001fe000) << 3) |
+ ((word & 0x000003fc) << 6);
+ break;
+ case 11:
+ word = *(pword + 1) + *(pword + wpls + 1);
+ *(lined + j) = ((word & 0x7f800000) << 1) |
+ ((word & 0x000ff000) << 4) |
+ ((word & 0x000001fe) << 7);
+ break;
+ case 12:
+ word = *pword + 3 * (*(pword + wpls));
+ *(lined + j) = (word & 0xff000000) |
+ ((word & 0x001fe000) << 3) |
+ ((word & 0x000003fc) << 6);
+ break;
+ case 13:
+ word = *pword + 2 * (*(pword + wpls)) + *(pword + wpls + 1);
+ *(lined + j) = (word & 0xff000000) |
+ ((word & 0x001fe000) << 3) |
+ ((word & 0x000003fc) << 6);
+ break;
+ case 14:
+ word = *(pword + wpls) + *(pword + wpls + 1);
+ *(lined + j) = ((word & 0x7f800000) << 1) |
+ ((word & 0x000ff000) << 4) |
+ ((word & 0x000001fe) << 7);
+ break;
+ case 15:
+ word = *(pword + 1) + *(pword + wpls) +
+ 2 * (*(pword + wpls + 1));
+ *(lined + j) = (word & 0xff000000) |
+ ((word & 0x001fe000) << 3) |
+ ((word & 0x000003fc) << 6);
+ break;
+ default: /* for testing only; no interpolation, no shift */
+ lept_stderr("shouldn't get here\n");
+ *(lined + j) = *pword;
+ break;
+ }
+ }
+ }
+
+ return;
+}