Leptonica 1.68
C Image Processing Library
|
00001 /*====================================================================* 00002 - Copyright (C) 2001 Leptonica. All rights reserved. 00003 - This software is distributed in the hope that it will be 00004 - useful, but with NO WARRANTY OF ANY KIND. 00005 - No author or distributor accepts responsibility to anyone for the 00006 - consequences of using this software, or for whether it serves any 00007 - particular purpose or works at all, unless he or she says so in 00008 - writing. Everyone is granted permission to copy, modify and 00009 - redistribute this source code, for commercial or non-commercial 00010 - purposes, with the following restrictions: (1) the origin of this 00011 - source code must not be misrepresented; (2) modified versions must 00012 - be plainly marked as such; and (3) this notice may not be removed 00013 - or altered from any source or modified source distribution. 00014 *====================================================================*/ 00015 00016 00017 /* 00018 * rotatefastalt.c 00019 * 00020 * Alternative (slightly slower) method for rotating color images, 00021 * with antialiasing. This is here just for comparison with 00022 * the better methods in the library. 00023 * 00024 * Includes these functions: 00025 * pixRotateAMColorFast2() 00026 * pixShiftRGB258() 00027 * rotateAMColorFastLow2() 00028 */ 00029 00030 #include <string.h> 00031 #include <math.h> /* required for sin and tan */ 00032 #include "allheaders.h" 00033 00034 static const l_float32 VERY_SMALL_ANGLE = 0.001; /* radians; ~0.06 degrees */ 00035 00036 static PIX *pixRotateAMColorFast2(PIX *pixs, l_float32 angle, l_uint8 grayval); 00037 static PIX *pixShiftRGB258(PIX *pixs); 00038 static void rotateAMColorFastLow2(l_uint32 *datad, l_int32 w, l_int32 h, 00039 l_int32 wpld, l_uint32 *datas, 00040 l_int32 wpls, l_float32 angle, 00041 l_uint8 grayval); 00042 00043 main(int argc, 00044 char **argv) 00045 { 00046 char *filein, *fileout; 00047 l_float32 angle, deg2rad; 00048 PIX *pixs, *pixd; 00049 static char mainName[] = "rotatefastalt"; 00050 00051 if (argc != 4) 00052 exit(ERROR_INT("Syntax: rotatefastalt filein angle fileout", 00053 mainName, 1)); 00054 filein = argv[1]; 00055 angle = atof(argv[2]); 00056 fileout = argv[3]; 00057 00058 deg2rad = 3.1415926535 / 180.; 00059 00060 if ((pixs = pixRead(filein)) == NULL) 00061 exit(ERROR_INT("pixs not read", mainName, 1)); 00062 00063 startTimer(); 00064 pixd = pixRotateAMColorFast2(pixs, deg2rad * angle, 255); 00065 fprintf(stderr, "Time for rotation: %7.3f sec\n", stopTimer()); 00066 pixWrite(fileout, pixd, IFF_JFIF_JPEG); 00067 00068 pixDestroy(&pixs); 00069 pixDestroy(&pixd); 00070 return 0; 00071 } 00072 00073 00074 /*! 00075 * pixRotateAMColorFast2() 00076 * 00077 * Input: pixs 00078 * angle (radians; clockwise is positive) 00079 * grayval (0 to bring in BLACK, 255 for WHITE) 00080 * Return: pixd, or null on error 00081 * 00082 * Notes: 00083 * - This rotates a color image about the image center. 00084 * A positive angle gives a clockwise rotation. 00085 * - It uses area mapping, dividing each pixel into 00086 * 16 subpixels. 00087 * - It creates a temporary 32-bit color image. 00088 * - It is slightly slower than pixRotateAMColorFast(), 00089 * which uses less memory because it does not create 00090 * a temporary image. 00091 * 00092 * *** Warning: implicit assumption about RGB component ordering *** 00093 */ 00094 PIX * 00095 pixRotateAMColorFast2(PIX *pixs, 00096 l_float32 angle, 00097 l_uint8 grayval) 00098 { 00099 l_int32 w, h, wpls, wpld; 00100 l_uint32 *datas, *datad; 00101 PIX *pixshft, *pixd; 00102 00103 PROCNAME("pixRotateAMColorFast2"); 00104 00105 if (!pixs) 00106 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); 00107 if (pixGetDepth(pixs) != 32) 00108 return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL); 00109 00110 if (L_ABS(angle) < VERY_SMALL_ANGLE) 00111 return pixClone(pixs); 00112 00113 if ((pixshft = pixShiftRGB258(pixs)) == NULL) 00114 return (PIX *)ERROR_PTR("pixshft not defined", procName, NULL); 00115 00116 w = pixGetWidth(pixshft); 00117 h = pixGetHeight(pixshft); 00118 datas = pixGetData(pixshft); 00119 wpls = pixGetWpl(pixshft); 00120 pixd = pixCreateTemplate(pixshft); 00121 datad = pixGetData(pixd); 00122 wpld = pixGetWpl(pixd); 00123 00124 rotateAMColorFastLow2(datad, w, h, wpld, datas, wpls, angle, grayval); 00125 00126 pixDestroy(&pixshft); 00127 return pixd; 00128 } 00129 00130 00131 /*! 00132 * pixShiftRGB258() 00133 * 00134 * Makes a new 32 bpp image with the R, G and B components 00135 * right-shifted by 2, 5 and 8 bits, respectively. 00136 */ 00137 PIX * 00138 pixShiftRGB258(PIX *pixs) 00139 { 00140 l_int32 w, h, wpls, wpld, i, j; 00141 l_uint32 word; 00142 l_uint32 *datas, *datad, *lines, *lined; 00143 PIX *pixd; 00144 00145 PROCNAME("pixShift258"); 00146 00147 if (!pixs) 00148 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); 00149 if (pixGetDepth(pixs) != 32) 00150 return (PIX *)ERROR_PTR("depth not 32 bpp", procName, NULL); 00151 w = pixGetWidth(pixs); 00152 h = pixGetHeight(pixs); 00153 wpls = pixGetWpl(pixs); 00154 datas = pixGetData(pixs); 00155 00156 if ((pixd = pixCreate(w, h, 32)) == NULL) 00157 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00158 wpld = pixGetWpl(pixd); 00159 datad = pixGetData(pixd); 00160 00161 for (i = 0; i < h; i++) { 00162 lines = datas + i * wpls; 00163 lined = datad + i * wpld; 00164 for (j = 0; j < w; j++) { 00165 word = *(lines + j); 00166 *(lined + j) = ((word & 0xff000000) >> 2) | 00167 ((word & 0x00ff0000) >> 5) | 00168 ((word & 0x0000ff00) >> 8); 00169 } 00170 } 00171 00172 return pixd; 00173 } 00174 00175 00176 /*! 00177 * rotateAMColorFastLow2() 00178 * 00179 * Alternative version for fast color rotation 00180 * 00181 * *** Warning: explicit assumption about RGB component ordering *** 00182 */ 00183 void 00184 rotateAMColorFastLow2(l_uint32 *datad, 00185 l_int32 w, 00186 l_int32 h, 00187 l_int32 wpld, 00188 l_uint32 *datas, 00189 l_int32 wpls, 00190 l_float32 angle, 00191 l_uint8 grayval) 00192 { 00193 l_int32 i, j, xcen, ycen, wm2, hm2; 00194 l_int32 xdif, ydif, xpm, ypm, xp, yp, xf, yf; 00195 l_uint32 edgeval, word; 00196 l_uint32 *pword, *lines, *lined; 00197 l_float32 sina, cosa; 00198 00199 xcen = w / 2; 00200 wm2 = w - 2; 00201 ycen = h / 2; 00202 hm2 = h - 2; 00203 sina = 4. * sin(angle); 00204 cosa = 4. * cos(angle); 00205 00206 edgeval = (grayval << 24) | (grayval << 16) | (grayval << 8); 00207 for (i = 0; i < h; i++) { 00208 ydif = ycen - i; 00209 lined = datad + i * wpld; 00210 for (j = 0; j < w; j++) { 00211 xdif = xcen - j; 00212 xpm = (l_int32)(-xdif * cosa - ydif * sina + 0.5); 00213 ypm = (l_int32)(-ydif * cosa + xdif * sina + 0.5); 00214 xp = xcen + (xpm >> 2); 00215 yp = ycen + (ypm >> 2); 00216 xf = xpm & 0x03; 00217 yf = ypm & 0x03; 00218 00219 /* if off the edge, write the input grayval */ 00220 if (xp < 0 || yp < 0 || xp > wm2 || yp > hm2) { 00221 *(lined + j) = edgeval; 00222 continue; 00223 } 00224 00225 lines = datas + yp * wpls; 00226 pword = lines + xp; 00227 00228 switch (xf + 4 * yf) 00229 { 00230 case 0: 00231 word = *pword; 00232 *(lined + j) = ((word & 0x3fc00000) << 2) | 00233 ((word & 0x0007f800) << 5) | 00234 ((word & 0x000000ff) << 8); 00235 break; 00236 case 1: 00237 word = 3 * (*pword) + *(pword + 1); 00238 *(lined + j) = (word & 0xff000000) | 00239 ((word & 0x001fe000) << 3) | 00240 ((word & 0x000003fc) << 6); 00241 break; 00242 case 2: 00243 word = *pword + *(pword + 1); 00244 *(lined + j) = ((word & 0x7f800000) << 1) | 00245 ((word & 0x000ff000) << 4) | 00246 ((word & 0x000001fe) << 7); 00247 break; 00248 case 3: 00249 word = *pword + 3 * (*(pword + 1)); 00250 *(lined + j) = (word & 0xff000000) | 00251 ((word & 0x001fe000) << 3) | 00252 ((word & 0x000003fc) << 6); 00253 break; 00254 case 4: 00255 word = 3 * (*pword) + *(pword + wpls); 00256 *(lined + j) = (word & 0xff000000) | 00257 ((word & 0x001fe000) << 3) | 00258 ((word & 0x000003fc) << 6); 00259 break; 00260 case 5: 00261 word = 2 * (*pword) + *(pword + 1) + *(pword + wpls); 00262 *(lined + j) = (word & 0xff000000) | 00263 ((word & 0x001fe000) << 3) | 00264 ((word & 0x000003fc) << 6); 00265 break; 00266 case 6: 00267 word = *pword + *(pword + 1); 00268 *(lined + j) = ((word & 0x7f800000) << 1) | 00269 ((word & 0x000ff000) << 4) | 00270 ((word & 0x000001fe) << 7); 00271 break; 00272 case 7: 00273 word = *pword + 2 * (*(pword + 1)) + *(pword + wpls + 1); 00274 *(lined + j) = (word & 0xff000000) | 00275 ((word & 0x001fe000) << 3) | 00276 ((word & 0x000003fc) << 6); 00277 break; 00278 case 8: 00279 word = *pword + *(pword + wpls); 00280 *(lined + j) = ((word & 0x7f800000) << 1) | 00281 ((word & 0x000ff000) << 4) | 00282 ((word & 0x000001fe) << 7); 00283 break; 00284 case 9: 00285 word = *pword + *(pword + wpls); 00286 *(lined + j) = ((word & 0x7f800000) << 1) | 00287 ((word & 0x000ff000) << 4) | 00288 ((word & 0x000001fe) << 7); 00289 break; 00290 case 10: 00291 word = *pword + *(pword + 1) + *(pword + wpls) + 00292 *(pword + wpls + 1); 00293 *(lined + j) = (word & 0xff000000) | 00294 ((word & 0x001fe000) << 3) | 00295 ((word & 0x000003fc) << 6); 00296 break; 00297 case 11: 00298 word = *(pword + 1) + *(pword + wpls + 1); 00299 *(lined + j) = ((word & 0x7f800000) << 1) | 00300 ((word & 0x000ff000) << 4) | 00301 ((word & 0x000001fe) << 7); 00302 break; 00303 case 12: 00304 word = *pword + 3 * (*(pword + wpls)); 00305 *(lined + j) = (word & 0xff000000) | 00306 ((word & 0x001fe000) << 3) | 00307 ((word & 0x000003fc) << 6); 00308 break; 00309 case 13: 00310 word = *pword + 2 * (*(pword + wpls)) + *(pword + wpls + 1); 00311 *(lined + j) = (word & 0xff000000) | 00312 ((word & 0x001fe000) << 3) | 00313 ((word & 0x000003fc) << 6); 00314 break; 00315 case 14: 00316 word = *(pword + wpls) + *(pword + wpls + 1); 00317 *(lined + j) = ((word & 0x7f800000) << 1) | 00318 ((word & 0x000ff000) << 4) | 00319 ((word & 0x000001fe) << 7); 00320 break; 00321 case 15: 00322 word = *(pword + 1) + *(pword + wpls) + 00323 2 * (*(pword + wpls + 1)); 00324 *(lined + j) = (word & 0xff000000) | 00325 ((word & 0x001fe000) << 3) | 00326 ((word & 0x000003fc) << 6); 00327 break; 00328 default: /* for testing only; no interpolation, no shift */ 00329 fprintf(stderr, "shouldn't get here\n"); 00330 *(lined + j) = *pword; 00331 break; 00332 } 00333 } 00334 } 00335 00336 return; 00337 } 00338