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 * ropiplow.c 00018 * 00019 * Low level in-place full height vertical block transfer 00020 * 00021 * void rasteropVipLow() 00022 * 00023 * Low level in-place full width horizontal block transfer 00024 * 00025 * void rasteropHipLow() 00026 * void shiftDataHorizontalLow() 00027 */ 00028 00029 00030 #include <string.h> 00031 #include "allheaders.h" 00032 00033 #define COMBINE_PARTIAL(d, s, m) ( ((d) & ~(m)) | ((s) & (m)) ) 00034 00035 static const l_uint32 lmask32[] = {0x0, 00036 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 00037 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, 00038 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 00039 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 00040 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 00041 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, 00042 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 00043 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff}; 00044 00045 static const l_uint32 rmask32[] = {0x0, 00046 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 00047 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 00048 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 00049 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, 00050 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 00051 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, 00052 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 00053 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff}; 00054 00055 00056 /*--------------------------------------------------------------------* 00057 * Low-level Vertical In-place Rasterop * 00058 *--------------------------------------------------------------------*/ 00059 /*! 00060 * rasteropVipLow() 00061 * 00062 * Input: data (ptr to image data) 00063 * pixw (width) 00064 * pixh (height) 00065 * depth (depth) 00066 * wpl (wpl) 00067 * x (x val of UL corner of rectangle) 00068 * w (width of rectangle) 00069 * shift (+ shifts data downward in vertical column) 00070 * Return: 0 if OK; 1 on error. 00071 * 00072 * Notes: 00073 * (1) This clears the pixels that are left exposed after the 00074 * translation. You can consider them as pixels that are 00075 * shifted in from outside the image. This can be later 00076 * overridden by the incolor parameter in higher-level functions 00077 * that call this. For example, for images with depth > 1, 00078 * these pixels are cleared to black; to be white they 00079 * must later be SET to white. See, e.g., pixRasteropVip(). 00080 * (2) This function scales the width to accommodate any depth, 00081 * performs clipping, and then does the in-place rasterop. 00082 */ 00083 void 00084 rasteropVipLow(l_uint32 *data, 00085 l_int32 pixw, 00086 l_int32 pixh, 00087 l_int32 depth, 00088 l_int32 wpl, 00089 l_int32 x, 00090 l_int32 w, 00091 l_int32 shift) 00092 { 00093 l_int32 fwpartb; /* boolean (1, 0) if first word is partial */ 00094 l_int32 fwpart2b; /* boolean (1, 0) if first word is doubly partial */ 00095 l_uint32 fwmask; /* mask for first partial word */ 00096 l_int32 fwbits; /* first word bits in ovrhang */ 00097 l_uint32 *pdfwpart; /* ptr to first partial dest word */ 00098 l_uint32 *psfwpart; /* ptr to first partial src word */ 00099 l_int32 fwfullb; /* boolean (1, 0) if there exists a full word */ 00100 l_int32 nfullw; /* number of full words */ 00101 l_uint32 *pdfwfull; /* ptr to first full dest word */ 00102 l_uint32 *psfwfull; /* ptr to first full src word */ 00103 l_int32 lwpartb; /* boolean (1, 0) if last word is partial */ 00104 l_uint32 lwmask; /* mask for last partial word */ 00105 l_int32 lwbits; /* last word bits in ovrhang */ 00106 l_uint32 *pdlwpart; /* ptr to last partial dest word */ 00107 l_uint32 *pslwpart; /* ptr to last partial src word */ 00108 l_int32 dirwpl; /* directed wpl (-wpl * sign(shift)) */ 00109 l_int32 absshift; /* absolute value of shift; for use in iterator */ 00110 l_int32 vlimit; /* vertical limit value for iterations */ 00111 l_int32 i, j; 00112 00113 00114 /*--------------------------------------------------------* 00115 * Scale horizontal dimensions by depth * 00116 *--------------------------------------------------------*/ 00117 if (depth != 1) { 00118 pixw *= depth; 00119 x *= depth; 00120 w *= depth; 00121 } 00122 00123 00124 /*--------------------------------------------------------* 00125 * Clip horizontally * 00126 *--------------------------------------------------------*/ 00127 if (x < 0) { 00128 w += x; /* reduce w */ 00129 x = 0; /* clip to x = 0 */ 00130 } 00131 if (x >= pixw || w <= 0) /* no part of vertical slice is in the image */ 00132 return; 00133 00134 if (x + w > pixw) 00135 w = pixw - x; /* clip to x + w = pixw */ 00136 00137 /*--------------------------------------------------------* 00138 * Preliminary calculations * 00139 *--------------------------------------------------------*/ 00140 /* is the first word partial? */ 00141 if ((x & 31) == 0) { /* if not */ 00142 fwpartb = 0; 00143 fwbits = 0; 00144 } 00145 else { /* if so */ 00146 fwpartb = 1; 00147 fwbits = 32 - (x & 31); 00148 fwmask = rmask32[fwbits]; 00149 if (shift >= 0) { /* go up from bottom */ 00150 pdfwpart = data + wpl * (pixh - 1) + (x >> 5); 00151 psfwpart = data + wpl * (pixh - 1 - shift) + (x >> 5); 00152 } 00153 else { /* go down from top */ 00154 pdfwpart = data + (x >> 5); 00155 psfwpart = data - wpl * shift + (x >> 5); 00156 } 00157 } 00158 00159 /* is the first word doubly partial? */ 00160 if (w >= fwbits) /* if not */ 00161 fwpart2b = 0; 00162 else { /* if so */ 00163 fwpart2b = 1; 00164 fwmask &= lmask32[32 - fwbits + w]; 00165 } 00166 00167 /* is there a full dest word? */ 00168 if (fwpart2b == 1) { /* not */ 00169 fwfullb = 0; 00170 nfullw = 0; 00171 } 00172 else { 00173 nfullw = (w - fwbits) >> 5; 00174 if (nfullw == 0) /* if not */ 00175 fwfullb = 0; 00176 else { /* if so */ 00177 fwfullb = 1; 00178 if (fwpartb) { 00179 pdfwfull = pdfwpart + 1; 00180 psfwfull = psfwpart + 1; 00181 } 00182 else { 00183 if (shift >= 0) { /* go up from bottom */ 00184 pdfwfull = data + wpl * (pixh - 1) + (x >> 5); 00185 psfwfull = data + wpl * (pixh - 1 - shift) + (x >> 5); 00186 } 00187 else { /* go down from top */ 00188 pdfwfull = data + (x >> 5); 00189 psfwfull = data - wpl * shift + (x >> 5); 00190 } 00191 } 00192 } 00193 } 00194 00195 /* is the last word partial? */ 00196 lwbits = (x + w) & 31; 00197 if (fwpart2b == 1 || lwbits == 0) /* if not */ 00198 lwpartb = 0; 00199 else { 00200 lwpartb = 1; 00201 lwmask = lmask32[lwbits]; 00202 if (fwpartb) { 00203 pdlwpart = pdfwpart + 1 + nfullw; 00204 pslwpart = psfwpart + 1 + nfullw; 00205 } 00206 else { 00207 if (shift >= 0) { /* go up from bottom */ 00208 pdlwpart = data + wpl * (pixh - 1) + (x >> 5) + nfullw; 00209 pslwpart = data + wpl * (pixh - 1 - shift) + (x >> 5) + nfullw; 00210 } 00211 else { /* go down from top */ 00212 pdlwpart = data + (x >> 5) + nfullw; 00213 pslwpart = data - wpl * shift + (x >> 5) + nfullw; 00214 } 00215 } 00216 } 00217 00218 /* determine the direction of flow from the shift 00219 * If the shift >= 0, data flows downard from src 00220 * to dest, starting at the bottom and working up. 00221 * If shift < 0, data flows upward from src to 00222 * dest, starting at the top and working down. */ 00223 dirwpl = (shift >= 0) ? -wpl : wpl; 00224 absshift = L_ABS(shift); 00225 vlimit = L_MAX(0, pixh - absshift); 00226 00227 00228 /*--------------------------------------------------------* 00229 * Now we're ready to do the ops * 00230 *--------------------------------------------------------*/ 00231 00232 /* Do the first partial word */ 00233 if (fwpartb) { 00234 for (i = 0; i < vlimit; i++) { 00235 *pdfwpart = COMBINE_PARTIAL(*pdfwpart, *psfwpart, fwmask); 00236 pdfwpart += dirwpl; 00237 psfwpart += dirwpl; 00238 } 00239 00240 /* Clear the incoming pixels */ 00241 for (i = vlimit; i < pixh; i++) { 00242 *pdfwpart = COMBINE_PARTIAL(*pdfwpart, 0x0, fwmask); 00243 pdfwpart += dirwpl; 00244 } 00245 } 00246 00247 /* Do the full words */ 00248 if (fwfullb) { 00249 for (i = 0; i < vlimit; i++) { 00250 for (j = 0; j < nfullw; j++) 00251 *(pdfwfull + j) = *(psfwfull + j); 00252 pdfwfull += dirwpl; 00253 psfwfull += dirwpl; 00254 } 00255 00256 /* Clear the incoming pixels */ 00257 for (i = vlimit; i < pixh; i++) { 00258 for (j = 0; j < nfullw; j++) 00259 *(pdfwfull + j) = 0x0; 00260 pdfwfull += dirwpl; 00261 } 00262 } 00263 00264 /* Do the last partial word */ 00265 if (lwpartb) { 00266 for (i = 0; i < vlimit; i++) { 00267 *pdlwpart = COMBINE_PARTIAL(*pdlwpart, *pslwpart, lwmask); 00268 pdlwpart += dirwpl; 00269 pslwpart += dirwpl; 00270 } 00271 00272 /* Clear the incoming pixels */ 00273 for (i = vlimit; i < pixh; i++) { 00274 *pdlwpart = COMBINE_PARTIAL(*pdlwpart, 0x0, lwmask); 00275 pdlwpart += dirwpl; 00276 } 00277 } 00278 00279 return; 00280 } 00281 00282 00283 00284 /*--------------------------------------------------------------------* 00285 * Low-level Horizontal In-place Rasterop * 00286 *--------------------------------------------------------------------*/ 00287 /*! 00288 * rasteropHipLow() 00289 * 00290 * Input: data (ptr to image data) 00291 * pixh (height) 00292 * depth (depth) 00293 * wpl (wpl) 00294 * y (y val of UL corner of rectangle) 00295 * h (height of rectangle) 00296 * shift (+ shifts data to the left in a horizontal column) 00297 * Return: 0 if OK; 1 on error. 00298 * 00299 * Notes: 00300 * (1) This clears the pixels that are left exposed after the rasterop. 00301 * Therefore, for Pix with depth > 1, these pixels become black, 00302 * and must be subsequently SET if they are to be white. 00303 * For example, see pixRasteropHip(). 00304 * (2) This function performs clipping and calls shiftDataHorizontalLine() 00305 * to do the in-place rasterop on each line. 00306 */ 00307 void 00308 rasteropHipLow(l_uint32 *data, 00309 l_int32 pixh, 00310 l_int32 depth, 00311 l_int32 wpl, 00312 l_int32 y, 00313 l_int32 h, 00314 l_int32 shift) 00315 { 00316 l_int32 i; 00317 l_uint32 *line; 00318 00319 /* clip band if necessary */ 00320 if (y < 0) { 00321 h += y; /* reduce h */ 00322 y = 0; /* clip to y = 0 */ 00323 } 00324 if (h <= 0 || y > pixh) /* no part of horizontal slice is in the image */ 00325 return; 00326 00327 if (y + h > pixh) 00328 h = pixh - y; /* clip to y + h = pixh */ 00329 00330 for (i = y; i < y + h; i++) { 00331 line = data + i * wpl; 00332 shiftDataHorizontalLow(line, wpl, line, wpl, shift * depth); 00333 } 00334 } 00335 00336 00337 /*! 00338 * shiftDataHorizontalLow() 00339 * 00340 * Input: datad (ptr to beginning of dest line) 00341 * wpld (wpl of dest) 00342 * datas (ptr to beginning of src line) 00343 * wpls (wpl of src) 00344 * shift (horizontal shift of block; >0 is to right) 00345 * Return: void 00346 * 00347 * Notes: 00348 * (1) This can also be used for in-place operation; see, e.g., 00349 * rasteropHipLow(). 00350 * (2) We are clearing the pixels that are shifted in from 00351 * outside the image. This can be overridden by the 00352 * incolor parameter in higher-level functions that call this. 00353 */ 00354 void 00355 shiftDataHorizontalLow(l_uint32 *datad, 00356 l_int32 wpld, 00357 l_uint32 *datas, 00358 l_int32 wpls, 00359 l_int32 shift) 00360 { 00361 l_int32 j, firstdw, wpl, rshift, lshift; 00362 l_uint32 *lined, *lines; 00363 00364 lined = datad; 00365 lines = datas; 00366 00367 if (shift >= 0) { /* src shift to right; data flows to 00368 * right, starting at right edge and 00369 * progressing leftward. */ 00370 firstdw = shift / 32; 00371 wpl = L_MIN(wpls, wpld - firstdw); 00372 lined += firstdw + wpl - 1; 00373 lines += wpl - 1; 00374 rshift = shift & 31; 00375 if (rshift == 0) { 00376 for (j = 0; j < wpl; j++) 00377 *lined-- = *lines--; 00378 00379 /* clear out the rest to the left edge */ 00380 for (j = 0; j < firstdw; j++) 00381 *lined-- = 0; 00382 } 00383 else { 00384 lshift = 32 - rshift; 00385 for (j = 1; j < wpl; j++) { 00386 *lined-- = *(lines - 1) << lshift | *lines >> rshift; 00387 lines--; 00388 } 00389 *lined = *lines >> rshift; /* partial first */ 00390 00391 /* clear out the rest to the left edge */ 00392 *lined &= ~lmask32[rshift]; 00393 lined--; 00394 for (j = 0; j < firstdw; j++) 00395 *lined-- = 0; 00396 } 00397 } 00398 else { /* src shift to left; data flows to left, starting 00399 * at left edge and progressing rightward. */ 00400 firstdw = (-shift) / 32; 00401 wpl = L_MIN(wpls - firstdw, wpld); 00402 lines += firstdw; 00403 lshift = (-shift) & 31; 00404 if (lshift == 0) { 00405 for (j = 0; j < wpl; j++) 00406 *lined++ = *lines++; 00407 00408 /* clear out the rest to the right edge */ 00409 for (j = 0; j < firstdw; j++) 00410 *lined++ = 0; 00411 } 00412 else { 00413 rshift = 32 - lshift; 00414 for (j = 1; j < wpl; j++) { 00415 *lined++ = *lines << lshift | *(lines + 1) >> rshift; 00416 lines++; 00417 } 00418 *lined = *lines << lshift; /* partial last */ 00419 00420 /* clear out the rest to the right edge */ 00421 /* first clear the lshift pixels of this partial word */ 00422 *lined &= ~rmask32[lshift]; 00423 lined++; 00424 /* then the remaining words to the right edge */ 00425 for (j = 0; j < firstdw; j++) 00426 *lined++ = 0; 00427 } 00428 } 00429 00430 return; 00431 } 00432