Leptonica 1.68
C Image Processing Library

ropiplow.c

Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines