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 * rotateorthlow.c 00019 * 00020 * 90-degree rotation (cw) 00021 * void rotate90Low() 00022 * 00023 * LR-flip 00024 * void flipLRLow() 00025 * 00026 * TB-flip 00027 * void flipTBLow() 00028 * 00029 * Byte reverse tables 00030 * l_uint8 *makeReverseByteTab1() 00031 * l_uint8 *makeReverseByteTab2() 00032 * l_uint8 *makeReverseByteTab4() 00033 */ 00034 00035 #include <stdio.h> 00036 #include <stdlib.h> 00037 #include <string.h> 00038 #include "allheaders.h" 00039 00040 00041 00042 /*------------------------------------------------------------------* 00043 * 90 degree rotation * 00044 *------------------------------------------------------------------*/ 00045 /*! 00046 * rotate90Low() 00047 * 00048 * direction: 1 for cw rotation 00049 * -1 for ccw rotation 00050 * 00051 * Notes: 00052 * (1) The dest must be cleared in advance because not 00053 * all source pixels are written to the destination. 00054 */ 00055 void 00056 rotate90Low(l_uint32 *datad, 00057 l_int32 wd, 00058 l_int32 hd, 00059 l_int32 d, 00060 l_int32 wpld, 00061 l_uint32 *datas, 00062 l_int32 wpls, 00063 l_int32 direction) 00064 { 00065 l_int32 i, j, k, m, iend, nswords; 00066 l_uint32 val, word; 00067 l_uint32 *lines, *lined; 00068 00069 PROCNAME("rotate90Low"); 00070 00071 if (direction == 1) { /* clockwise */ 00072 switch (d) 00073 { 00074 case 32: 00075 for (i = 0; i < hd; i++) { 00076 lined = datad + i * wpld; 00077 lines = datas + (wd - 1) * wpls; 00078 for (j = 0; j < wd; j++) { 00079 lined[j] = lines[i]; 00080 lines -= wpls; 00081 } 00082 } 00083 break; 00084 case 16: 00085 for (i = 0; i < hd; i++) { 00086 lined = datad + i * wpld; 00087 lines = datas + (wd - 1) * wpls; 00088 for (j = 0; j < wd; j++) { 00089 if ((val = GET_DATA_TWO_BYTES(lines, i))) 00090 SET_DATA_TWO_BYTES(lined, j, val); 00091 lines -= wpls; 00092 } 00093 } 00094 break; 00095 case 8: 00096 for (i = 0; i < hd; i++) { 00097 lined = datad + i * wpld; 00098 lines = datas + (wd - 1) * wpls; 00099 for (j = 0; j < wd; j++) { 00100 if ((val = GET_DATA_BYTE(lines, i))) 00101 SET_DATA_BYTE(lined, j, val); 00102 lines -= wpls; 00103 } 00104 } 00105 break; 00106 case 4: 00107 for (i = 0; i < hd; i++) { 00108 lined = datad + i * wpld; 00109 lines = datas + (wd - 1) * wpls; 00110 for (j = 0; j < wd; j++) { 00111 if ((val = GET_DATA_QBIT(lines, i))) 00112 SET_DATA_QBIT(lined, j, val); 00113 lines -= wpls; 00114 } 00115 } 00116 break; 00117 case 2: 00118 for (i = 0; i < hd; i++) { 00119 lined = datad + i * wpld; 00120 lines = datas + (wd - 1) * wpls; 00121 for (j = 0; j < wd; j++) { 00122 if ((val = GET_DATA_DIBIT(lines, i))) 00123 SET_DATA_DIBIT(lined, j, val); 00124 lines -= wpls; 00125 } 00126 } 00127 break; 00128 case 1: 00129 nswords = hd / 32; 00130 for (j = 0; j < wd; j++) { 00131 lined = datad; 00132 lines = datas + (wd - 1 - j) * wpls; 00133 for (k = 0; k < nswords; k++) { 00134 word = lines[k]; 00135 if (!word) { 00136 lined += 32 * wpld; 00137 continue; 00138 } 00139 else { 00140 iend = 32 * (k + 1); 00141 for (m = 0, i = 32 * k; i < iend; i++, m++) { 00142 if ((word << m) & 0x80000000) 00143 SET_DATA_BIT(lined, j); 00144 lined += wpld; 00145 } 00146 } 00147 } 00148 for (i = 32 * nswords; i < hd; i++) { 00149 if (GET_DATA_BIT(lines, i)) 00150 SET_DATA_BIT(lined, j); 00151 lined += wpld; 00152 } 00153 } 00154 break; 00155 default: 00156 L_ERROR("illegal depth", procName); 00157 } 00158 } 00159 else { /* direction counter-clockwise */ 00160 switch (d) 00161 { 00162 case 32: 00163 for (i = 0; i < hd; i++) { 00164 lined = datad + i * wpld; 00165 lines = datas; 00166 for (j = 0; j < wd; j++) { 00167 lined[j] = lines[hd - 1 - i]; 00168 lines += wpls; 00169 } 00170 } 00171 break; 00172 case 16: 00173 for (i = 0; i < hd; i++) { 00174 lined = datad + i * wpld; 00175 lines = datas; 00176 for (j = 0; j < wd; j++) { 00177 if ((val = GET_DATA_TWO_BYTES(lines, hd - 1 - i))) 00178 SET_DATA_TWO_BYTES(lined, j, val); 00179 lines += wpls; 00180 } 00181 } 00182 break; 00183 case 8: 00184 for (i = 0; i < hd; i++) { 00185 lined = datad + i * wpld; 00186 lines = datas; 00187 for (j = 0; j < wd; j++) { 00188 if ((val = GET_DATA_BYTE(lines, hd - 1 - i))) 00189 SET_DATA_BYTE(lined, j, val); 00190 lines += wpls; 00191 } 00192 } 00193 break; 00194 case 4: 00195 for (i = 0; i < hd; i++) { 00196 lined = datad + i * wpld; 00197 lines = datas; 00198 for (j = 0; j < wd; j++) { 00199 if ((val = GET_DATA_QBIT(lines, hd - 1 - i))) 00200 SET_DATA_QBIT(lined, j, val); 00201 lines += wpls; 00202 } 00203 } 00204 break; 00205 case 2: 00206 for (i = 0; i < hd; i++) { 00207 lined = datad + i * wpld; 00208 lines = datas; 00209 for (j = 0; j < wd; j++) { 00210 if ((val = GET_DATA_DIBIT(lines, hd - 1 - i))) 00211 SET_DATA_DIBIT(lined, j, val); 00212 lines += wpls; 00213 } 00214 } 00215 break; 00216 case 1: 00217 nswords = hd / 32; 00218 for (j = 0; j < wd; j++) { 00219 lined = datad + (hd - 1) * wpld; 00220 lines = datas + (wd - 1 - j) * wpls; 00221 for (k = 0; k < nswords; k++) { 00222 word = lines[k]; 00223 if (!word) { 00224 lined -= 32 * wpld; 00225 continue; 00226 } 00227 else { 00228 iend = 32 * (k + 1); 00229 for (m = 0, i = 32 * k; i < iend; i++, m++) { 00230 if ((word << m) & 0x80000000) 00231 SET_DATA_BIT(lined, wd - 1 - j); 00232 lined -= wpld; 00233 } 00234 } 00235 } 00236 for (i = 32 * nswords; i < hd; i++) { 00237 if (GET_DATA_BIT(lines, i)) 00238 SET_DATA_BIT(lined, wd - 1 - j); 00239 lined -= wpld; 00240 } 00241 } 00242 break; 00243 default: 00244 L_ERROR("illegal depth", procName); 00245 } 00246 } 00247 00248 return; 00249 } 00250 00251 00252 /*------------------------------------------------------------------* 00253 * Left/right flip * 00254 *------------------------------------------------------------------*/ 00255 /*! 00256 * flipLRLow() 00257 * 00258 * Notes: 00259 * (1) The pixel access routines allow a trivial implementation. 00260 * However, for d < 8, it is more efficient to right-justify 00261 * each line to a 32-bit boundary and then extract bytes and 00262 * do pixel reversing. In those cases, as in the 180 degree 00263 * rotation, we right-shift the data (if necessary) to 00264 * right-justify on the 32 bit boundary, and then read the 00265 * bytes off each raster line in reverse order, reversing 00266 * the pixels in each byte using a table. These functions 00267 * for 1, 2 and 4 bpp were tested against the "trivial" 00268 * version (shown here for 4 bpp): 00269 * for (i = 0; i < h; i++) { 00270 * line = data + i * wpl; 00271 * memcpy(buffer, line, bpl); 00272 * for (j = 0; j < w; j++) { 00273 * val = GET_DATA_QBIT(buffer, w - 1 - j); 00274 * SET_DATA_QBIT(line, j, val); 00275 * } 00276 * } 00277 * (2) This operation is in-place. 00278 */ 00279 void 00280 flipLRLow(l_uint32 *data, 00281 l_int32 w, 00282 l_int32 h, 00283 l_int32 d, 00284 l_int32 wpl, 00285 l_uint8 *tab, 00286 l_uint32 *buffer) 00287 { 00288 l_int32 extra, shift, databpl, bpl, i, j; 00289 l_uint32 val; 00290 l_uint32 *line; 00291 00292 PROCNAME("flipLRLow"); 00293 00294 bpl = 4 * wpl; 00295 switch (d) 00296 { 00297 case 32: 00298 for (i = 0; i < h; i++) { 00299 line = data + i * wpl; 00300 memcpy(buffer, line, bpl); 00301 for (j = 0; j < w; j++) 00302 line[j] = buffer[w - 1 - j]; 00303 } 00304 break; 00305 case 16: 00306 for (i = 0; i < h; i++) { 00307 line = data + i * wpl; 00308 memcpy(buffer, line, bpl); 00309 for (j = 0; j < w; j++) { 00310 val = GET_DATA_TWO_BYTES(buffer, w - 1 - j); 00311 SET_DATA_TWO_BYTES(line, j, val); 00312 } 00313 } 00314 break; 00315 case 8: 00316 for (i = 0; i < h; i++) { 00317 line = data + i * wpl; 00318 memcpy(buffer, line, bpl); 00319 for (j = 0; j < w; j++) { 00320 val = GET_DATA_BYTE(buffer, w - 1 - j); 00321 SET_DATA_BYTE(line, j, val); 00322 } 00323 } 00324 break; 00325 case 4: 00326 extra = (w * d) & 31; 00327 if (extra) 00328 shift = 8 - extra / 4; 00329 else 00330 shift = 0; 00331 if (shift) 00332 rasteropHipLow(data, h, d, wpl, 0, h, shift); 00333 00334 databpl = (w + 1) / 2; 00335 for (i = 0; i < h; i++) { 00336 line = data + i * wpl; 00337 memcpy(buffer, line, bpl); 00338 for (j = 0; j < databpl; j++) { 00339 val = GET_DATA_BYTE(buffer, bpl - 1 - j); 00340 SET_DATA_BYTE(line, j, tab[val]); 00341 } 00342 } 00343 break; 00344 case 2: 00345 extra = (w * d) & 31; 00346 if (extra) 00347 shift = 16 - extra / 2; 00348 else 00349 shift = 0; 00350 if (shift) 00351 rasteropHipLow(data, h, d, wpl, 0, h, shift); 00352 00353 databpl = (w + 3) / 4; 00354 for (i = 0; i < h; i++) { 00355 line = data + i * wpl; 00356 memcpy(buffer, line, bpl); 00357 for (j = 0; j < databpl; j++) { 00358 val = GET_DATA_BYTE(buffer, bpl - 1 - j); 00359 SET_DATA_BYTE(line, j, tab[val]); 00360 } 00361 } 00362 break; 00363 case 1: 00364 extra = (w * d) & 31; 00365 if (extra) 00366 shift = 32 - extra; 00367 else 00368 shift = 0; 00369 if (shift) 00370 rasteropHipLow(data, h, d, wpl, 0, h, shift); 00371 00372 databpl = (w + 7) / 8; 00373 for (i = 0; i < h; i++) { 00374 line = data + i * wpl; 00375 memcpy(buffer, line, bpl); 00376 for (j = 0; j < databpl; j++) { 00377 val = GET_DATA_BYTE(buffer, bpl - 1 - j); 00378 SET_DATA_BYTE(line, j, tab[val]); 00379 } 00380 } 00381 break; 00382 default: 00383 L_ERROR("depth not permitted for LR rot", procName); 00384 return; 00385 } 00386 00387 return; 00388 } 00389 00390 00391 /*------------------------------------------------------------------* 00392 * Top/bottom flip * 00393 *------------------------------------------------------------------*/ 00394 /*! 00395 * flipTBLow() 00396 * 00397 * Notes: 00398 * (1) This is simple and fast. We use the memcpy function 00399 * to do all the work on aligned data, regardless of pixel 00400 * depth. 00401 * (2) This operation is in-place. 00402 */ 00403 void 00404 flipTBLow(l_uint32 *data, 00405 l_int32 h, 00406 l_int32 wpl, 00407 l_uint32 *buffer) 00408 { 00409 l_int32 i, k, h2, bpl; 00410 l_uint32 *linet, *lineb; 00411 00412 h2 = h / 2; 00413 bpl = 4 * wpl; 00414 for (i = 0, k = h - 1; i < h2; i++, k--) { 00415 linet = data + i * wpl; 00416 lineb = data + k * wpl; 00417 memcpy(buffer, linet, bpl); 00418 memcpy(linet, lineb, bpl); 00419 memcpy(lineb, buffer, bpl); 00420 } 00421 00422 return; 00423 } 00424 00425 00426 /*------------------------------------------------------------------* 00427 * Byte reverse tables * 00428 *------------------------------------------------------------------*/ 00429 /*! 00430 * makeReverseByteTab1() 00431 * 00432 * Notes: 00433 * (1) This generates an 8 bit lookup table for reversing 00434 * the order of eight 1-bit pixels. 00435 */ 00436 l_uint8 * 00437 makeReverseByteTab1(void) 00438 { 00439 l_int32 i; 00440 l_uint8 *tab; 00441 00442 PROCNAME("makeReverseByteTab1"); 00443 00444 if ((tab = (l_uint8 *)CALLOC(256, sizeof(l_uint8))) == NULL) 00445 return (l_uint8 *)ERROR_PTR("calloc fail for tab", procName, NULL); 00446 00447 for (i = 0; i < 256; i++) 00448 tab[i] = ((0x80 & i) >> 7) | 00449 ((0x40 & i) >> 5) | 00450 ((0x20 & i) >> 3) | 00451 ((0x10 & i) >> 1) | 00452 ((0x08 & i) << 1) | 00453 ((0x04 & i) << 3) | 00454 ((0x02 & i) << 5) | 00455 ((0x01 & i) << 7); 00456 00457 return tab; 00458 } 00459 00460 00461 /*! 00462 * makeReverseByteTab2() 00463 * 00464 * Notes: 00465 * (1) This generates an 8 bit lookup table for reversing 00466 * the order of four 2-bit pixels. 00467 */ 00468 l_uint8 * 00469 makeReverseByteTab2(void) 00470 { 00471 l_int32 i; 00472 l_uint8 *tab; 00473 00474 PROCNAME("makeReverseByteTab2"); 00475 00476 if ((tab = (l_uint8 *)CALLOC(256, sizeof(l_uint8))) == NULL) 00477 return (l_uint8 *)ERROR_PTR("calloc fail for tab", procName, NULL); 00478 00479 for (i = 0; i < 256; i++) 00480 tab[i] = ((0xc0 & i) >> 6) | 00481 ((0x30 & i) >> 2) | 00482 ((0x0c & i) << 2) | 00483 ((0x03 & i) << 6); 00484 return tab; 00485 } 00486 00487 00488 /*! 00489 * makeReverseByteTab4() 00490 * 00491 * Notes: 00492 * (1) This generates an 8 bit lookup table for reversing 00493 * the order of two 4-bit pixels. 00494 */ 00495 l_uint8 * 00496 makeReverseByteTab4(void) 00497 { 00498 l_int32 i; 00499 l_uint8 *tab; 00500 00501 PROCNAME("makeReverseByteTab4"); 00502 00503 if ((tab = (l_uint8 *)CALLOC(256, sizeof(l_uint8))) == NULL) 00504 return (l_uint8 *)ERROR_PTR("calloc fail for tab", procName, NULL); 00505 00506 for (i = 0; i < 256; i++) 00507 tab[i] = ((0xf0 & i) >> 4) | ((0x0f & i) << 4); 00508 return tab; 00509 } 00510