Leptonica 1.68
C Image Processing Library

pix2.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  *  pix2.c
00018  *
00019  *    This file has these basic operations:
00020  *
00021  *      (1) Get and set: individual pixels, full image, rectangular region,
00022  *          pad pixels, border pixels, and color components for RGB
00023  *      (2) Add and remove border pixels
00024  *      (3) Endian byte swaps
00025  *      (4) Simple method for byte-processing images (instead of words)
00026  *
00027  *      Pixel poking
00028  *           l_int32     pixGetPixel()
00029  *           l_int32     pixSetPixel()
00030  *           l_int32     pixGetRGBPixel()
00031  *           l_int32     pixSetRGBPixel()
00032  *           l_int32     pixGetRandomPixel()
00033  *           l_int32     pixClearPixel()
00034  *           l_int32     pixFlipPixel()
00035  *           void        setPixelLow()
00036  *
00037  *      Full image clear/set/set-to-arbitrary-value
00038  *           l_int32     pixClearAll()
00039  *           l_int32     pixSetAll()
00040  *           l_int32     pixSetAllArbitrary()
00041  *           l_int32     pixSetBlackOrWhite()
00042  *
00043  *      Rectangular region clear/set/set-to-arbitrary-value/blend
00044  *           l_int32     pixClearInRect()
00045  *           l_int32     pixSetInRect()
00046  *           l_int32     pixSetInRectArbitrary()
00047  *           l_int32     pixBlendInRect()
00048  *
00049  *      Set pad bits
00050  *           l_int32     pixSetPadBits()
00051  *           l_int32     pixSetPadBitsBand()
00052  *
00053  *      Assign border pixels
00054  *           l_int32     pixSetOrClearBorder()
00055  *           l_int32     pixSetBorderVal()
00056  *           l_int32     pixSetBorderRingVal()
00057  *           l_int32     pixSetMirroredBorder()
00058  *           PIX        *pixCopyBorder()
00059  *
00060  *      Add and remove border
00061  *           PIX        *pixAddBorder()
00062  *           PIX        *pixAddBlackBorder()
00063  *           PIX        *pixAddBorderGeneral()
00064  *           PIX        *pixRemoveBorder()
00065  *           PIX        *pixRemoveBorderGeneral()
00066  *           PIX        *pixAddMirroredBorder()
00067  *           PIX        *pixAddRepeatedBorder()
00068  *           PIX        *pixAddMixedBorder()
00069  *
00070  *      Color sample setting and extraction
00071  *           PIX        *pixCreateRGBImage()
00072  *           PIX        *pixGetRGBComponent()
00073  *           l_int32     pixSetRGBComponent()
00074  *           PIX        *pixGetRGBComponentCmap()
00075  *           l_int32     composeRGBPixel()
00076  *           void        extractRGBValues()
00077  *           l_int32     extractMinMaxComponent()
00078  *           l_int32     pixGetRGBLine()
00079  *
00080  *      Conversion between big and little endians
00081  *           PIX        *pixEndianByteSwapNew()
00082  *           l_int32     pixEndianByteSwap()
00083  *           l_int32     lineEndianByteSwap()
00084  *           PIX        *pixEndianTwoByteSwapNew()
00085  *           l_int32     pixEndianTwoByteSwap()
00086  *
00087  *      Extract raster data as binary string
00088  *           l_int32     pixGetRasterData()
00089  *
00090  *      Setup helpers for 8 bpp byte processing
00091  *           l_uint8   **pixSetupByteProcessing()
00092  *           l_int32     pixCleanupByteProcessing()
00093  *
00094  *      Setting parameters for antialias masking with alpha transforms
00095  *           void        l_setAlphaMaskBorder()
00096  *
00097  *      *** indicates implicit assumption about RGB component ordering
00098  */
00099 
00100 
00101 #include <string.h>
00102 #include "allheaders.h"
00103 
00104 static const l_uint32 rmask32[] = {0x0,
00105     0x00000001, 0x00000003, 0x00000007, 0x0000000f,
00106     0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
00107     0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
00108     0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
00109     0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
00110     0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
00111     0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
00112     0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};
00113 
00114     /* This is a global that determines the default 8 bpp alpha mask values
00115      * for rings at distance 1 and 2 from the border.  Declare extern
00116      * to use.  To change the values, use l_setAlphaMaskBorder(). */
00117 LEPT_DLL l_float32  AlphaMaskBorderVals[2] = {0.0, 0.5};
00118 
00119 
00120 #ifndef  NO_CONSOLE_IO
00121 #define  DEBUG_SERIALIZE        0
00122 #endif  /* ~NO_CONSOLE_IO */
00123 
00124 
00125 /*-------------------------------------------------------------*
00126  *                         Pixel poking                        *
00127  *-------------------------------------------------------------*/
00128 /*!
00129  *  pixGetPixel()
00130  *
00131  *      Input:  pix
00132  *              (x,y) pixel coords
00133  *              &val (<return> pixel value)
00134  *      Return: 0 if OK; 1 on error
00135  *
00136  *  Notes:
00137  *      (1) This returns the value in the data array.  If the pix is
00138  *          colormapped, it returns the colormap index, not the rgb value.
00139  *      (2) Because of the function overhead and the parameter checking,
00140  *          this is much slower than using the GET_DATA_*() macros directly.
00141  *          Speed on a 1 Mpixel RGB image, using a 3 GHz machine:
00142  *            * pixGet/pixSet: ~25 Mpix/sec
00143  *            * GET_DATA/SET_DATA: ~350 MPix/sec
00144  *          If speed is important and you're doing random access into
00145  *          the pix, use pixGetLinePtrs() and the array access macros.
00146  */
00147 l_int32
00148 pixGetPixel(PIX       *pix,
00149             l_int32    x,
00150             l_int32    y,
00151             l_uint32  *pval)
00152 {
00153 l_int32    w, h, d, wpl, val;
00154 l_uint32  *line, *data;
00155 
00156     PROCNAME("pixGetPixel");
00157 
00158     if (!pval)
00159         return ERROR_INT("pval not defined", procName, 1);
00160     *pval = 0;
00161     if (!pix)
00162         return ERROR_INT("pix not defined", procName, 1);
00163 
00164     pixGetDimensions(pix, &w, &h, &d);
00165     if (x < 0 || x >= w)
00166         return ERROR_INT("x out of bounds", procName, 1);
00167     if (y < 0 || y >= h)
00168         return ERROR_INT("y out of bounds", procName, 1);
00169 
00170     wpl = pixGetWpl(pix);
00171     data = pixGetData(pix);
00172     line = data + y * wpl;
00173     switch (d)
00174     {
00175     case 1:
00176         val = GET_DATA_BIT(line, x);
00177         break;
00178     case 2:
00179         val = GET_DATA_DIBIT(line, x);
00180         break;
00181     case 4:
00182         val = GET_DATA_QBIT(line, x);
00183         break;
00184     case 8:
00185         val = GET_DATA_BYTE(line, x);
00186         break;
00187     case 16:
00188         val = GET_DATA_TWO_BYTES(line, x);
00189         break;
00190     case 32:
00191         val = line[x];
00192         break;
00193     default:
00194         return ERROR_INT("depth must be in {1,2,4,8,16,32} bpp", procName, 1);
00195     }
00196 
00197     *pval = val;
00198     return 0;
00199 }
00200 
00201 
00202 /*!
00203  *  pixSetPixel()
00204  *
00205  *      Input:  pix
00206  *              (x,y) pixel coords
00207  *              val (value to be inserted)
00208  *      Return: 0 if OK; 1 on error
00209  *
00210  *  Notes:
00211  *      (1) Warning: the input value is not checked for overflow with respect
00212  *          the the depth of @pix, and the sign bit (if any) is ignored.
00213  *          * For d == 1, @val > 0 sets the bit on.
00214  *          * For d == 2, 4, 8 and 16, @val is masked to the maximum allowable
00215  *            pixel value, and any (invalid) higher order bits are discarded.
00216  *      (2) See pixGetPixel() for information on performance.
00217  */
00218 l_int32
00219 pixSetPixel(PIX      *pix,
00220             l_int32   x,
00221             l_int32   y,
00222             l_uint32  val)
00223 {
00224 l_int32    w, h, d, wpl;
00225 l_uint32  *line, *data;
00226 
00227     PROCNAME("pixSetPixel");
00228 
00229     if (!pix)
00230         return ERROR_INT("pix not defined", procName, 1);
00231 
00232     pixGetDimensions(pix, &w, &h, &d);
00233     if (x < 0 || x >= w)
00234         return ERROR_INT("x out of bounds", procName, 1);
00235     if (y < 0 || y >= h)
00236         return ERROR_INT("y out of bounds", procName, 1);
00237 
00238     data = pixGetData(pix);
00239     wpl = pixGetWpl(pix);
00240     line = data + y * wpl;
00241     switch (d)
00242     {
00243     case 1:
00244         if (val)
00245             SET_DATA_BIT(line, x);
00246         else
00247             CLEAR_DATA_BIT(line, x);
00248         break;
00249     case 2:
00250         SET_DATA_DIBIT(line, x, val);
00251         break;
00252     case 4:
00253         SET_DATA_QBIT(line, x, val);
00254         break;
00255     case 8:
00256         SET_DATA_BYTE(line, x, val);
00257         break;
00258     case 16:
00259         SET_DATA_TWO_BYTES(line, x, val);
00260         break;
00261     case 32:
00262         line[x] = val;
00263         break;
00264     default:
00265         return ERROR_INT("depth must be in {1,2,4,8,16,32} bpp", procName, 1);
00266     }
00267 
00268     return 0;
00269 }
00270 
00271 
00272 /*!
00273  *  pixGetRGBPixel()
00274  *
00275  *      Input:  pix (32 bpp rgb, not colormapped)
00276  *              (x,y) pixel coords
00277  *              &rval (<optional return> red component)
00278  *              &gval (<optional return> green component)
00279  *              &bval (<optional return> blue component)
00280  *      Return: 0 if OK; 1 on error
00281  */
00282 l_int32
00283 pixGetRGBPixel(PIX      *pix,
00284                l_int32   x,
00285                l_int32   y,
00286                l_int32  *prval,
00287                l_int32  *pgval,
00288                l_int32  *pbval)
00289 {
00290 l_int32    w, h, d, wpl;
00291 l_uint32  *data, *ppixel;
00292 
00293     PROCNAME("pixGetRGBPixel");
00294 
00295     if (!pix)
00296         return ERROR_INT("pix not defined", procName, 1);
00297     pixGetDimensions(pix, &w, &h, &d);
00298     if (d != 32)
00299         return ERROR_INT("pix not 32 bpp", procName, 1);
00300     if (x < 0 || x >= w)
00301         return ERROR_INT("x out of bounds", procName, 1);
00302     if (y < 0 || y >= h)
00303         return ERROR_INT("y out of bounds", procName, 1);
00304 
00305     wpl = pixGetWpl(pix);
00306     data = pixGetData(pix);
00307     ppixel = data + y * wpl + x;
00308     if (prval) *prval = GET_DATA_BYTE(ppixel, COLOR_RED);
00309     if (pgval) *pgval = GET_DATA_BYTE(ppixel, COLOR_GREEN);
00310     if (pbval) *pbval = GET_DATA_BYTE(ppixel, COLOR_BLUE);
00311     return 0;
00312 }
00313 
00314 
00315 /*!
00316  *  pixSetRGBPixel()
00317  *
00318  *      Input:  pix (32 bpp rgb)
00319  *              (x,y) pixel coords
00320  *              rval (red component)
00321  *              gval (green component)
00322  *              bval (blue component)
00323  *      Return: 0 if OK; 1 on error
00324  */
00325 l_int32
00326 pixSetRGBPixel(PIX     *pix,
00327                l_int32  x,
00328                l_int32  y,
00329                l_int32  rval,
00330                l_int32  gval,
00331                l_int32  bval)
00332 {
00333 l_int32    w, h, d, wpl;
00334 l_uint32   pixel;
00335 l_uint32  *data, *line;
00336 
00337     PROCNAME("pixSetRGBPixel");
00338 
00339     if (!pix)
00340         return ERROR_INT("pix not defined", procName, 1);
00341     pixGetDimensions(pix, &w, &h, &d);
00342     if (d != 32)
00343         return ERROR_INT("pix not 32 bpp", procName, 1);
00344     if (x < 0 || x >= w)
00345         return ERROR_INT("x out of bounds", procName, 1);
00346     if (y < 0 || y >= h)
00347         return ERROR_INT("y out of bounds", procName, 1);
00348 
00349     wpl = pixGetWpl(pix);
00350     data = pixGetData(pix);
00351     line = data + y * wpl;
00352     composeRGBPixel(rval, gval, bval, &pixel);
00353     *(line + x) = pixel;
00354     return 0;
00355 }
00356 
00357 
00358 /*!
00359  *  pixGetRandomPixel()
00360  *
00361  *      Input:  pix (any depth; can be colormapped)
00362  *              &val (<return> pixel value)
00363  *              &x (<optional return> x coordinate chosen; can be null)
00364  *              &y (<optional return> y coordinate chosen; can be null)
00365  *      Return: 0 if OK; 1 on error
00366  *
00367  *  Notes:
00368  *      (1) If the pix is colormapped, it returns the rgb value.
00369  */
00370 l_int32
00371 pixGetRandomPixel(PIX       *pix,
00372                   l_uint32  *pval,
00373                   l_int32   *px,
00374                   l_int32   *py)
00375 {
00376 l_int32   w, h, x, y, rval, gval, bval;
00377 l_uint32  val;
00378 PIXCMAP  *cmap;
00379 
00380     PROCNAME("pixGetRandomPixel");
00381 
00382     if (!pval)
00383         return ERROR_INT("pval not defined", procName, 1);
00384     *pval = 0;
00385     if (!pix)
00386         return ERROR_INT("pix not defined", procName, 1);
00387 
00388     pixGetDimensions(pix, &w, &h, NULL);
00389     x = rand() % w;
00390     y = rand() % h;
00391     if (px) *px = x;
00392     if (py) *py = y;
00393     pixGetPixel(pix, x, y, &val);
00394     if ((cmap = pixGetColormap(pix)) != NULL) {
00395         pixcmapGetColor(cmap, val, &rval, &gval, &bval);
00396         composeRGBPixel(rval, gval, bval, pval);
00397     }
00398     else
00399         *pval = val;
00400 
00401     return 0;
00402 }
00403 
00404 
00405 /*!
00406  *  pixClearPixel()
00407  *
00408  *      Input:  pix
00409  *              (x,y) pixel coords
00410  *      Return: 0 if OK; 1 on error.
00411  */
00412 l_int32
00413 pixClearPixel(PIX     *pix,
00414               l_int32  x,
00415               l_int32  y)
00416 {
00417 l_int32    w, h, d, wpl;
00418 l_uint32  *line, *data;
00419 
00420     PROCNAME("pixClearPixel");
00421 
00422     if (!pix)
00423         return ERROR_INT("pix not defined", procName, 1);
00424 
00425     pixGetDimensions(pix, &w, &h, &d);
00426     if (x < 0 || x >= w)
00427         return ERROR_INT("x out of bounds", procName, 1);
00428     if (y < 0 || y >= h)
00429         return ERROR_INT("y out of bounds", procName, 1);
00430 
00431     wpl = pixGetWpl(pix);
00432     data = pixGetData(pix);
00433     line = data + y * wpl;
00434     switch (d)
00435     {
00436     case 1:
00437         CLEAR_DATA_BIT(line, x);
00438         break;
00439     case 2:
00440         CLEAR_DATA_DIBIT(line, x);
00441         break;
00442     case 4:
00443         CLEAR_DATA_QBIT(line, x);
00444         break;
00445     case 8:
00446         SET_DATA_BYTE(line, x, 0);
00447         break;
00448     case 16:
00449         SET_DATA_TWO_BYTES(line, x, 0);
00450         break;
00451     case 32:
00452         line[x] = 0;
00453         break;
00454     default:
00455         return ERROR_INT("depth must be in {1,2,4,8,16,32} bpp", procName, 1);
00456     }
00457 
00458     return 0;
00459 }
00460 
00461 
00462 /*!
00463  *  pixFlipPixel()
00464  *
00465  *      Input:  pix
00466  *              (x,y) pixel coords
00467  *      Return: 0 if OK; 1 on error
00468  */
00469 l_int32
00470 pixFlipPixel(PIX     *pix,
00471              l_int32  x,
00472              l_int32  y)
00473 {
00474 l_int32    w, h, d, wpl;
00475 l_uint32   val;
00476 l_uint32  *line, *data;
00477 
00478     PROCNAME("pixFlipPixel");
00479 
00480     if (!pix)
00481         return ERROR_INT("pix not defined", procName, 1);
00482 
00483     pixGetDimensions(pix, &w, &h, &d);
00484     if (x < 0 || x >= w)
00485         return ERROR_INT("x out of bounds", procName, 1);
00486     if (y < 0 || y >= h)
00487         return ERROR_INT("y out of bounds", procName, 1);
00488 
00489     data = pixGetData(pix);
00490     wpl = pixGetWpl(pix);
00491     line = data + y * wpl;
00492     switch (d)
00493     {
00494     case 1:
00495         val = GET_DATA_BIT(line, x);
00496         if (val)
00497             CLEAR_DATA_BIT(line, x);
00498         else
00499             SET_DATA_BIT(line, x);
00500         break;
00501     case 2:
00502         val = GET_DATA_DIBIT(line, x);
00503         val ^= 0x3;
00504         SET_DATA_DIBIT(line, x, val);
00505         break;
00506     case 4:
00507         val = GET_DATA_QBIT(line, x);
00508         val ^= 0xf;
00509         SET_DATA_QBIT(line, x, val);
00510         break;
00511     case 8:
00512         val = GET_DATA_BYTE(line, x);
00513         val ^= 0xff;
00514         SET_DATA_BYTE(line, x, val);
00515         break;
00516     case 16:
00517         val = GET_DATA_TWO_BYTES(line, x);
00518         val ^= 0xffff;
00519         SET_DATA_TWO_BYTES(line, x, val);
00520         break;
00521     case 32:
00522         val = line[x] ^ 0xffffffff;
00523         line[x] = val;
00524         break;
00525     default:
00526         return ERROR_INT("depth must be in {1,2,4,8,16,32} bpp", procName, 1);
00527     }
00528 
00529     return 0;
00530 }
00531 
00532 
00533 /*!
00534  *  setPixelLow()
00535  *
00536  *      Input:  line (ptr to beginning of line),
00537  *              x (pixel location in line)
00538  *              depth (bpp)
00539  *              val (to be inserted)
00540  *      Return: void
00541  *
00542  *  Notes:
00543  *      (1) Caution: input variables are not checked!
00544  */
00545 void
00546 setPixelLow(l_uint32  *line,
00547             l_int32    x,
00548             l_int32    depth,
00549             l_uint32   val)
00550 {
00551     switch (depth)
00552     {
00553     case 1:
00554         if (val)
00555             SET_DATA_BIT(line, x);
00556         else
00557             CLEAR_DATA_BIT(line, x);
00558         break;
00559     case 2:
00560         SET_DATA_DIBIT(line, x, val);
00561         break;
00562     case 4:
00563         SET_DATA_QBIT(line, x, val);
00564         break;
00565     case 8:
00566         SET_DATA_BYTE(line, x, val);
00567         break;
00568     case 16:
00569         SET_DATA_TWO_BYTES(line, x, val);
00570         break;
00571     case 32:
00572         line[x] = val;
00573         break;
00574     default:
00575         fprintf(stderr, "illegal depth in setPixelLow()\n");
00576     }
00577 
00578     return;
00579 }
00580 
00581 
00582 /*-------------------------------------------------------------*
00583  *     Full image clear/set/set-to-arbitrary-value/invert      *
00584  *-------------------------------------------------------------*/
00585 /*!
00586  *  pixClearAll()
00587  *
00588  *      Input:  pix (all depths; use cmapped with caution)
00589  *      Return: 0 if OK, 1 on error
00590  *
00591  *  Notes:
00592  *      (1) Clears all data to 0.  For 1 bpp, this is white; for grayscale
00593  *          or color, this is black.
00594  *      (2) Caution: for colormapped pix, this sets the color to the first
00595  *          one in the colormap.  Be sure that this is the intended color!
00596  */
00597 l_int32
00598 pixClearAll(PIX  *pix)
00599 {
00600     PROCNAME("pixClearAll");
00601 
00602     if (!pix)
00603         return ERROR_INT("pix not defined", procName, 1);
00604         
00605     pixRasterop(pix, 0, 0, pixGetWidth(pix), pixGetHeight(pix),
00606                 PIX_CLR, NULL, 0, 0);
00607     return 0;
00608 }
00609 
00610 
00611 /*!
00612  *  pixSetAll()
00613  *
00614  *      Input:  pix (all depths; use cmapped with caution)
00615  *      Return: 0 if OK, 1 on error
00616  *
00617  *  Notes:
00618  *      (1) Sets all data to 1.  For 1 bpp, this is black; for grayscale
00619  *          or color, this is white.
00620  *      (2) Caution: for colormapped pix, this sets the pixel value to the
00621  *          maximum value supported by the colormap: 2^d - 1.  However, this
00622  *          color may not be defined, because the colormap may not be full.
00623  */
00624 l_int32
00625 pixSetAll(PIX  *pix)
00626 {
00627 l_int32   n;
00628 PIXCMAP  *cmap;
00629 
00630     PROCNAME("pixSetAll");
00631 
00632     if (!pix)
00633         return ERROR_INT("pix not defined", procName, 1);
00634     if ((cmap = pixGetColormap(pix)) != NULL) {
00635         n = pixcmapGetCount(cmap);
00636         if (n < cmap->nalloc)  /* cmap is not full */
00637             return ERROR_INT("cmap entry does not exist", procName, 1);
00638     }
00639 
00640     pixRasterop(pix, 0, 0, pixGetWidth(pix), pixGetHeight(pix),
00641                 PIX_SET, NULL, 0, 0);
00642     return 0;
00643 }
00644 
00645 
00646 /*!
00647  *  pixSetAllArbitrary()
00648  *
00649  *      Input:  pix (all depths; use cmapped with caution)
00650  *              val  (value to set all pixels)
00651  *      Return: 0 if OK; 1 on error
00652  *
00653  *  Notes:
00654  *      (1) For colormapped pix, be sure the value is the intended
00655  *          one in the colormap.
00656  *      (2) Caution: for colormapped pix, this sets each pixel to the
00657  *          color at the index equal to val.  Be sure that this index
00658  *          exists in the colormap and that it is the intended one!
00659  */
00660 l_int32
00661 pixSetAllArbitrary(PIX      *pix,
00662                    l_uint32  val)
00663 {
00664 l_int32    n, i, j, w, h, d, wpl, npix;
00665 l_uint32   maxval, wordval;
00666 l_uint32  *data, *line;
00667 PIXCMAP   *cmap;
00668 
00669     PROCNAME("pixSetAllArbitrary");
00670 
00671     if (!pix)
00672         return ERROR_INT("pix not defined", procName, 1);
00673     if ((cmap = pixGetColormap(pix)) != NULL) {
00674         n = pixcmapGetCount(cmap);
00675         if (val < 0) {
00676             L_WARNING("index not in colormap; using first color", procName);
00677             val = 0;
00678         }
00679         else if (val >= n) {
00680             L_WARNING("index not in colormap; using last color", procName);
00681             val = n - 1;
00682         }
00683     }
00684 
00685     pixGetDimensions(pix, &w, &h, &d);
00686     if (d == 32)
00687         maxval = 0xffffffff;
00688     else
00689         maxval = (1 << d) - 1;
00690     if (val < 0) {
00691         L_WARNING("invalid pixel value; set to 0", procName);
00692         val = 0;
00693     }
00694     if (val > maxval) {
00695         L_WARNING_INT("invalid pixel val; set to maxval = %d",
00696                       procName, maxval);
00697         val = maxval;
00698     }
00699 
00700         /* Set up word to tile with */
00701     wordval = 0;
00702     npix = 32 / d;    /* number of pixels per 32 bit word */
00703     for (j = 0; j < npix; j++)
00704         wordval |= (val << (j * d));
00705 
00706     wpl = pixGetWpl(pix);
00707     data = pixGetData(pix);
00708     for (i = 0; i < h; i++) {
00709         line = data + i * wpl;
00710         for (j = 0; j < wpl; j++) {
00711             *(line + j) = wordval;
00712         }
00713     }
00714 
00715     return 0;
00716 }
00717 
00718 
00719 /*!
00720  *  pixSetBlackOrWhite()
00721  *
00722  *      Input:  pixs (all depths; cmap ok)
00723  *              op (L_SET_BLACK, L_SET_WHITE)
00724  *      Return: 0 if OK; 1 on error
00725  *
00726  *  Notes:
00727  *      (1) Function for setting all pixels in an image to either black
00728  *          or white.
00729  *      (2) If pixs is colormapped, it adds black or white to the
00730  *          colormap if it's not there and there is room.  If the colormap
00731  *          is full, it finds the closest color in intensity.
00732  *          This index is written to all pixels.
00733  */
00734 l_int32
00735 pixSetBlackOrWhite(PIX     *pixs,
00736                    l_int32  op)
00737 {
00738 l_int32   d, index;
00739 PIXCMAP  *cmap;
00740 
00741     PROCNAME("pixSetBlackOrWhite");
00742 
00743     if (!pixs)
00744         return ERROR_INT("pix not defined", procName, 1);
00745     if (op != L_SET_BLACK && op != L_SET_WHITE)
00746         return ERROR_INT("invalid op", procName, 1);
00747 
00748     cmap = pixGetColormap(pixs);
00749     d = pixGetDepth(pixs);
00750     if (!cmap) {
00751         if ((d == 1 && op == L_SET_BLACK) ||
00752             (d > 1 && op == L_SET_WHITE))
00753             pixSetAll(pixs);
00754         else 
00755             pixClearAll(pixs);
00756     }
00757     else {  /* handle colormap */
00758         if (op == L_SET_BLACK)
00759             pixcmapAddBlackOrWhite(cmap, 0, &index);
00760         else  /* L_SET_WHITE */
00761             pixcmapAddBlackOrWhite(cmap, 1, &index);
00762         pixSetAllArbitrary(pixs, index);
00763     }
00764 
00765     return 0;
00766 }
00767 
00768 
00769 /*-------------------------------------------------------------*
00770  *     Rectangular region clear/set/set-to-arbitrary-value     *
00771  *-------------------------------------------------------------*/
00772 /*!
00773  *  pixClearInRect()
00774  *
00775  *      Input:  pix (all depths; can be cmapped)
00776  *              box (in which all pixels will be cleared)
00777  *      Return: 0 if OK, 1 on error
00778  *
00779  *  Notes:
00780  *      (1) Clears all data in rect to 0.  For 1 bpp, this is white;
00781  *          for grayscale or color, this is black.
00782  *      (2) Caution: for colormapped pix, this sets the color to the first
00783  *          one in the colormap.  Be sure that this is the intended color!
00784  */
00785 l_int32
00786 pixClearInRect(PIX  *pix,
00787                BOX  *box)
00788 {
00789 l_int32  x, y, w, h;
00790 
00791     PROCNAME("pixClearInRect");
00792 
00793     if (!pix)
00794         return ERROR_INT("pix not defined", procName, 1);
00795     if (!box)
00796         return ERROR_INT("box not defined", procName, 1);
00797 
00798     boxGetGeometry(box, &x, &y, &w, &h);
00799     pixRasterop(pix, x, y, w, h, PIX_CLR, NULL, 0, 0);
00800     return 0;
00801 }
00802 
00803 
00804 /*!
00805  *  pixSetInRect()
00806  *
00807  *      Input:  pix (all depths, can be cmapped)
00808  *              box (in which all pixels will be set)
00809  *      Return: 0 if OK, 1 on error
00810  *
00811  *  Notes:
00812  *      (1) Sets all data in rect to 1.  For 1 bpp, this is black;
00813  *          for grayscale or color, this is white.
00814  *      (2) Caution: for colormapped pix, this sets the pixel value to the
00815  *          maximum value supported by the colormap: 2^d - 1.  However, this
00816  *          color may not be defined, because the colormap may not be full.
00817  */
00818 l_int32
00819 pixSetInRect(PIX  *pix,
00820              BOX  *box)
00821 {
00822 l_int32   n, x, y, w, h;
00823 PIXCMAP  *cmap;
00824 
00825     PROCNAME("pixSetInRect");
00826 
00827     if (!pix)
00828         return ERROR_INT("pix not defined", procName, 1);
00829     if (!box)
00830         return ERROR_INT("box not defined", procName, 1);
00831     if ((cmap = pixGetColormap(pix)) != NULL) {
00832         n = pixcmapGetCount(cmap);
00833         if (n < cmap->nalloc)  /* cmap is not full */
00834             return ERROR_INT("cmap entry does not exist", procName, 1);
00835     }
00836 
00837     boxGetGeometry(box, &x, &y, &w, &h);
00838     pixRasterop(pix, x, y, w, h, PIX_SET, NULL, 0, 0);
00839     return 0;
00840 }
00841 
00842 
00843 /*!
00844  *  pixSetInRectArbitrary()
00845  *
00846  *      Input:  pix (all depths; can be cmapped)
00847  *              box (in which all pixels will be set to val)
00848  *              val  (value to set all pixels)
00849  *      Return: 0 if OK; 1 on error
00850  *
00851  *  Notes:
00852  *      (1) For colormapped pix, be sure the value is the intended
00853  *          one in the colormap.
00854  *      (2) Caution: for colormapped pix, this sets each pixel in the
00855  *          rect to the color at the index equal to val.  Be sure that
00856  *          this index exists in the colormap and that it is the intended one!
00857  */
00858 l_int32
00859 pixSetInRectArbitrary(PIX      *pix,
00860                       BOX      *box,
00861                       l_uint32  val)
00862 {
00863 l_int32    n, x, y, xstart, xend, ystart, yend, bw, bh, w, h, d, wpl, maxval;
00864 l_uint32  *data, *line;
00865 BOX       *boxc;
00866 PIXCMAP   *cmap;
00867 
00868     PROCNAME("pixSetInRectArbitrary");
00869 
00870     if (!pix)
00871         return ERROR_INT("pix not defined", procName, 1);
00872     if (!box)
00873         return ERROR_INT("box not defined", procName, 1);
00874     pixGetDimensions(pix, &w, &h, &d);
00875     if (d != 1 && d != 2 && d != 4 && d !=8 && d != 16 && d != 32)
00876         return ERROR_INT("depth must be in {1,2,4,8,16,32} bpp", procName, 1);
00877     if ((cmap = pixGetColormap(pix)) != NULL) {
00878         n = pixcmapGetCount(cmap);
00879         if (val < 0) {
00880             L_WARNING("index not in colormap; using first color", procName);
00881             val = 0;
00882         }
00883         else if (val >= n) {
00884             L_WARNING("index not in colormap; using last color", procName);
00885             val = n - 1;
00886         }
00887     }
00888 
00889     if (d == 32)
00890         maxval = 0xffffffff;
00891     else
00892         maxval = (1 << d) - 1;
00893     if (val < 0) {
00894         L_WARNING("invalid pixel value; set to 0", procName);
00895         val = 0;
00896     }
00897     if (val > maxval) {
00898         L_WARNING_INT("invalid pixel val; set to maxval = %d",
00899                       procName, maxval);
00900         val = maxval;
00901     }
00902 
00903         /* Handle the simple cases: the min and max values */
00904     if (val == 0) {
00905         pixClearInRect(pix, box);
00906         return 0;
00907     }
00908     if (d == 1 ||
00909         (d == 2 && val == 3) ||
00910         (d == 4 && val == 0xf) ||
00911         (d == 8 && val == 0xff) ||
00912         (d == 16 && val == 0xffff) ||
00913         (d == 32 && ((val ^ 0xffffff00) >> 8 == 0))) {
00914         pixSetInRect(pix, box);
00915         return 0;
00916     }
00917 
00918         /* Find the overlap of box with the input pix */
00919     if ((boxc = boxClipToRectangle(box, w, h)) == NULL)
00920         return ERROR_INT("no overlap of box with image", procName, 1);
00921     boxGetGeometry(boxc, &xstart, &ystart, &bw, &bh);
00922     xend = xstart + bw - 1;
00923     yend = ystart + bh - 1;
00924     boxDestroy(&boxc);
00925 
00926     wpl = pixGetWpl(pix);
00927     data = pixGetData(pix);
00928     for (y = ystart; y <= yend; y++) {
00929         line = data + y * wpl;
00930         for (x = xstart; x <= xend; x++) {
00931             switch(d)
00932             {
00933             case 2:
00934                 SET_DATA_DIBIT(line, x, val);
00935                 break;
00936             case 4:
00937                 SET_DATA_QBIT(line, x, val);
00938                 break;
00939             case 8:
00940                 SET_DATA_BYTE(line, x, val);
00941                 break;
00942             case 16:
00943                 SET_DATA_TWO_BYTES(line, x, val);
00944                 break;
00945             case 32:
00946                 line[x] = val;
00947                 break;
00948             default:
00949                 return ERROR_INT("depth not 2|4|8|16|32 bpp", procName, 1);
00950             }
00951         }
00952     }
00953 
00954     return 0;
00955 }
00956 
00957 
00958 /*!
00959  *  pixBlendInRect()
00960  *
00961  *      Input:  pixs (32 bpp rgb)
00962  *              box (in which all pixels will be blended)
00963  *              val  (blend value; 0xrrggbb00)
00964  *              fract (fraction of color to be blended with each pixel in pixs)
00965  *      Return: 0 if OK; 1 on error
00966  *
00967  *  Notes:
00968  *      (1) This is an in-place function.  It blends the input color @val
00969  *          with the pixels in pixs in the specified rectangle.
00970  */
00971 l_int32
00972 pixBlendInRect(PIX       *pixs,
00973                BOX       *box,
00974                l_uint32   val,
00975                l_float32  fract)
00976 {
00977 l_int32    i, j, bx, by, bw, bh, w, h, wpls;
00978 l_int32    prval, pgval, pbval, rval, gval, bval;
00979 l_uint32   val32;
00980 l_uint32  *datas, *lines;
00981 
00982     PROCNAME("pixBlendInRect");
00983 
00984     if (!pixs || pixGetDepth(pixs) != 32)
00985         return ERROR_INT("pixs not defined or not 32 bpp", procName, 1);
00986     if (!box)
00987         return ERROR_INT("box not defined", procName, 1);
00988 
00989     boxGetGeometry(box, &bx, &by, &bw, &bh);
00990     pixGetDimensions(pixs, &w, &h, NULL);
00991     datas = pixGetData(pixs);
00992     wpls = pixGetWpl(pixs);
00993     extractRGBValues(val, &rval, &gval, &bval);
00994     for (i = 0; i < bh; i++) {   /* scan over box */
00995         if (by + i < 0 || by + i >= h) continue;
00996         lines = datas + (by + i) * wpls;
00997         for (j = 0; j < bw; j++) {
00998             if (bx + j < 0 || bx + j >= w) continue;
00999             val32 = *(lines + bx + j);
01000             extractRGBValues(val32, &prval, &pgval, &pbval);
01001             prval = (l_int32)((1. - fract) * prval + fract * rval);
01002             pgval = (l_int32)((1. - fract) * pgval + fract * gval);
01003             pbval = (l_int32)((1. - fract) * pbval + fract * bval);
01004             composeRGBPixel(prval, pgval, pbval, &val32);
01005             *(lines + bx + j) = val32;
01006         }
01007     }
01008 
01009     return 0;
01010 }
01011 
01012 
01013 /*-------------------------------------------------------------*
01014  *                         Set pad bits                        *
01015  *-------------------------------------------------------------*/
01016 /*!
01017  *  pixSetPadBits()
01018  *
01019  *      Input:  pix (1, 2, 4, 8, 16, 32 bpp)
01020  *              val  (0 or 1)
01021  *      Return: 0 if OK; 1 on error
01022  *
01023  *  Notes:
01024  *      (1) The pad bits are the bits that expand each scanline to a
01025  *          multiple of 32 bits.  They are usually not used in
01026  *          image processing operations.  When boundary conditions
01027  *          are important, as in seedfill, they must be set properly.
01028  *      (2) This sets the value of the pad bits (if any) in the last
01029  *          32-bit word in each scanline.
01030  *      (3) For 32 bpp pix, there are no pad bits, so this is a no-op.
01031  */
01032 l_int32
01033 pixSetPadBits(PIX     *pix,
01034               l_int32  val)
01035 {
01036 l_int32    i, w, h, d, wpl, endbits, fullwords;
01037 l_uint32   mask;
01038 l_uint32  *data, *pword;
01039 
01040     PROCNAME("pixSetPadBits");
01041 
01042     if (!pix)
01043         return ERROR_INT("pix not defined", procName, 1);
01044 
01045     pixGetDimensions(pix, &w, &h, &d);
01046     if (d == 32)  /* no padding exists for 32 bpp */
01047         return 0;  
01048 
01049     data = pixGetData(pix);
01050     wpl = pixGetWpl(pix);
01051     endbits = 32 - ((w * d) % 32);
01052     if (endbits == 32)  /* no partial word */
01053         return 0;
01054     fullwords = w * d / 32;
01055 
01056     mask = rmask32[endbits];
01057     if (val == 0)
01058         mask = ~mask;
01059 
01060     for (i = 0; i < h; i++) {
01061         pword = data + i * wpl + fullwords;
01062         if (val == 0) /* clear */
01063             *pword = *pword & mask;
01064         else  /* set */
01065             *pword = *pword | mask;
01066     }
01067 
01068     return 0;
01069 }
01070 
01071 
01072 /*!
01073  *  pixSetPadBitsBand()
01074  *
01075  *      Input:  pix (1, 2, 4, 8, 16, 32 bpp)
01076  *              by  (starting y value of band)
01077  *              bh  (height of band)
01078  *              val  (0 or 1)
01079  *      Return: 0 if OK; 1 on error
01080  *
01081  *  Notes:
01082  *      (1) The pad bits are the bits that expand each scanline to a
01083  *          multiple of 32 bits.  They are usually not used in
01084  *          image processing operations.  When boundary conditions
01085  *          are important, as in seedfill, they must be set properly.
01086  *      (2) This sets the value of the pad bits (if any) in the last
01087  *          32-bit word in each scanline, within the specified
01088  *          band of raster lines.
01089  *      (3) For 32 bpp pix, there are no pad bits, so this is a no-op.
01090  */
01091 l_int32
01092 pixSetPadBitsBand(PIX     *pix,
01093                   l_int32  by,
01094                   l_int32  bh,
01095                   l_int32  val)
01096 {
01097 l_int32    i, w, h, d, wpl, endbits, fullwords;
01098 l_uint32   mask;
01099 l_uint32  *data, *pword;
01100 
01101     PROCNAME("pixSetPadBitsBand");
01102 
01103     if (!pix)
01104         return ERROR_INT("pix not defined", procName, 1);
01105 
01106     pixGetDimensions(pix, &w, &h, &d);
01107     if (d == 32)  /* no padding exists for 32 bpp */
01108         return 0;  
01109 
01110     if (by < 0)
01111         by = 0;
01112     if (by >= h)
01113         return ERROR_INT("start y not in image", procName, 1);
01114     if (by + bh > h)
01115         bh = h - by;
01116 
01117     data = pixGetData(pix);
01118     wpl = pixGetWpl(pix);
01119     endbits = 32 - ((w * d) % 32);
01120     if (endbits == 32)  /* no partial word */
01121         return 0;
01122     fullwords = w * d / 32;
01123 
01124     mask = rmask32[endbits];
01125     if (val == 0)
01126         mask = ~mask;
01127 
01128     for (i = by; i < by + bh; i++) {
01129         pword = data + i * wpl + fullwords;
01130         if (val == 0) /* clear */
01131             *pword = *pword & mask;
01132         else  /* set */
01133             *pword = *pword | mask;
01134     }
01135 
01136     return 0;
01137 }
01138 
01139 
01140 /*-------------------------------------------------------------*
01141  *                       Set border pixels                     *
01142  *-------------------------------------------------------------*/
01143 /*!
01144  *  pixSetOrClearBorder()
01145  *
01146  *      Input:  pixs (all depths)
01147  *              left, right, top, bot (amount to set or clear)
01148  *              operation (PIX_SET or PIX_CLR)
01149  *      Return: 0 if OK; 1 on error
01150  *
01151  *  Notes:
01152  *      (1) The border region is defined to be the region in the
01153  *          image within a specific distance of each edge.  Here, we
01154  *          allow the pixels within a specified distance of each
01155  *          edge to be set independently.  This either sets or
01156  *          clears all pixels in the border region.
01157  *      (2) For binary images, use PIX_SET for black and PIX_CLR for white.
01158  *      (3) For grayscale or color images, use PIX_SET for white
01159  *          and PIX_CLR for black.
01160  */
01161 l_int32
01162 pixSetOrClearBorder(PIX     *pixs,
01163                     l_int32  left,
01164                     l_int32  right,
01165                     l_int32  top,
01166                     l_int32  bot,
01167                     l_int32  op)
01168 {
01169 l_int32  w, h;
01170 
01171     PROCNAME("pixSetOrClearBorder");
01172 
01173     if (!pixs)
01174         return ERROR_INT("pixs not defined", procName, 1);
01175     if (op != PIX_SET && op != PIX_CLR)
01176         return ERROR_INT("op must be PIX_SET or PIX_CLR", procName, 1);
01177 
01178     pixGetDimensions(pixs, &w, &h, NULL);
01179     pixRasterop(pixs, 0, 0, left, h, op, NULL, 0, 0);
01180     pixRasterop(pixs, w - right, 0, right, h, op, NULL, 0, 0);
01181     pixRasterop(pixs, 0, 0, w, top, op, NULL, 0, 0);
01182     pixRasterop(pixs, 0, h - bot, w, bot, op, NULL, 0, 0);
01183 
01184     return 0;
01185 }
01186 
01187 
01188 /*!
01189  *  pixSetBorderVal()
01190  *
01191  *      Input:  pixs (8, 16 or 32 bpp)
01192  *              left, right, top, bot (amount to set)
01193  *              val (value to set at each border pixel)
01194  *      Return: 0 if OK; 1 on error
01195  *
01196  *  Notes:
01197  *      (1) The border region is defined to be the region in the
01198  *          image within a specific distance of each edge.  Here, we
01199  *          allow the pixels within a specified distance of each
01200  *          edge to be set independently.  This sets the pixels
01201  *          in the border region to the given input value.
01202  *      (2) For efficiency, use pixSetOrClearBorder() if
01203  *          you're setting the border to either black or white.
01204  *      (3) If d != 32, the input value should be masked off
01205  *          to the appropriate number of least significant bits.
01206  *      (4) The code is easily generalized for 2 or 4 bpp.
01207  */
01208 l_int32
01209 pixSetBorderVal(PIX      *pixs,
01210                 l_int32   left,
01211                 l_int32   right,
01212                 l_int32   top,
01213                 l_int32   bot,
01214                 l_uint32  val)
01215 {
01216 l_int32    w, h, d, wpls, i, j, bstart, rstart;
01217 l_uint32  *datas, *lines;
01218 
01219     PROCNAME("pixSetBorderVal");
01220 
01221     if (!pixs)
01222         return ERROR_INT("pixs not defined", procName, 1);
01223     pixGetDimensions(pixs, &w, &h, &d);
01224     if (d != 8 && d != 16 && d != 32)
01225         return ERROR_INT("depth must be 8, 16 or 32 bpp", procName, 1);
01226 
01227     datas = pixGetData(pixs);
01228     wpls = pixGetWpl(pixs);
01229     if (d == 8) {
01230         val &= 0xff;
01231         for (i = 0; i < top; i++) {
01232             lines = datas + i * wpls;
01233             for (j = 0; j < w; j++)
01234                 SET_DATA_BYTE(lines, j, val);
01235         }
01236         rstart = w - right;
01237         bstart = h - bot;
01238         for (i = top; i < bstart; i++) {
01239             lines = datas + i * wpls;
01240             for (j = 0; j < left; j++)
01241                 SET_DATA_BYTE(lines, j, val);
01242             for (j = rstart; j < w; j++)
01243                 SET_DATA_BYTE(lines, j, val);
01244         }
01245         for (i = bstart; i < h; i++) {
01246             lines = datas + i * wpls;
01247             for (j = 0; j < w; j++)
01248                 SET_DATA_BYTE(lines, j, val);
01249         }
01250     }
01251     else if (d == 16) {
01252         val &= 0xffff;
01253         for (i = 0; i < top; i++) {
01254             lines = datas + i * wpls;
01255             for (j = 0; j < w; j++)
01256                 SET_DATA_TWO_BYTES(lines, j, val);
01257         }
01258         rstart = w - right;
01259         bstart = h - bot;
01260         for (i = top; i < bstart; i++) {
01261             lines = datas + i * wpls;
01262             for (j = 0; j < left; j++)
01263                 SET_DATA_TWO_BYTES(lines, j, val);
01264             for (j = rstart; j < w; j++)
01265                 SET_DATA_TWO_BYTES(lines, j, val);
01266         }
01267         for (i = bstart; i < h; i++) {
01268             lines = datas + i * wpls;
01269             for (j = 0; j < w; j++)
01270                 SET_DATA_TWO_BYTES(lines, j, val);
01271         }
01272     }
01273     else {   /* d == 32 */
01274         for (i = 0; i < top; i++) {
01275             lines = datas + i * wpls;
01276             for (j = 0; j < w; j++)
01277                 *(lines + j) = val;
01278         }
01279         rstart = w - right;
01280         bstart = h - bot;
01281         for (i = top; i < bstart; i++) {
01282             lines = datas + i * wpls;
01283             for (j = 0; j < left; j++)
01284                 *(lines + j) = val;
01285             for (j = rstart; j < w; j++)
01286                 *(lines + j) = val;
01287         }
01288         for (i = bstart; i < h; i++) {
01289             lines = datas + i * wpls;
01290             for (j = 0; j < w; j++)
01291                 *(lines + j) = val;
01292         }
01293     }
01294 
01295     return 0;
01296 }
01297 
01298 
01299 /*!
01300  *  pixSetBorderRingVal()
01301  *
01302  *      Input:  pixs (any depth; cmap OK)
01303  *              dist (distance from outside; must be > 0; first ring is 1)
01304  *              val (value to set at each border pixel)
01305  *      Return: 0 if OK; 1 on error
01306  *
01307  *  Notes:
01308  *      (1) The rings are single-pixel-wide rectangular sets of
01309  *          pixels at a given distance from the edge of the pix.
01310  *          This sets all pixels in a given ring to a value.
01311  */
01312 l_int32
01313 pixSetBorderRingVal(PIX      *pixs,
01314                     l_int32   dist,
01315                     l_uint32  val)
01316 {
01317 l_int32  w, h, d, i, j, xend, yend;
01318 
01319     PROCNAME("pixSetBorderRingVal");
01320 
01321     if (!pixs)
01322         return ERROR_INT("pixs not defined", procName, 1);
01323     if (dist < 1)
01324         return ERROR_INT("dist must be > 0", procName, 1);
01325     pixGetDimensions(pixs, &w, &h, &d);
01326     if (w < 2 * dist + 1 || h < 2 * dist + 1)
01327         return ERROR_INT("ring doesn't exist", procName, 1);
01328     if (d < 32 && (val >= (1 << d)))
01329         return ERROR_INT("invalid pixel value", procName, 1);
01330 
01331     xend = w - dist;
01332     yend = h - dist;
01333     for (j = dist - 1; j <= xend; j++)
01334         pixSetPixel(pixs, j, dist - 1, val);
01335     for (j = dist - 1; j <= xend; j++)
01336         pixSetPixel(pixs, j, yend, val);
01337     for (i = dist - 1; i <= yend; i++)
01338         pixSetPixel(pixs, dist - 1, i, val);
01339     for (i = dist - 1; i <= yend; i++)
01340         pixSetPixel(pixs, xend, i, val);
01341 
01342     return 0;
01343 }
01344 
01345 
01346 /*!
01347  *  pixSetMirroredBorder()
01348  *
01349  *      Input:  pixs (all depths; colormap ok)
01350  *              left, right, top, bot (number of pixels to set)
01351  *      Return: 0 if OK, 1 on error
01352  *
01353  *  Notes:
01354  *      (1) This applies what is effectively mirror boundary conditions
01355  *          to a border region in the image.  It is in-place.
01356  *      (2) This is useful for setting pixels near the border to a
01357  *          value representative of the near pixels to the interior.
01358  *      (3) The general pixRasterop() is used for an in-place operation here
01359  *          because there is no overlap between the src and dest rectangles.
01360  */
01361 l_int32
01362 pixSetMirroredBorder(PIX     *pixs,
01363                      l_int32  left,
01364                      l_int32  right,
01365                      l_int32  top,
01366                      l_int32  bot)
01367 {
01368 l_int32  i, j, w, h;
01369 
01370     PROCNAME("pixSetMirroredBorder");
01371 
01372     if (!pixs)
01373         return ERROR_INT("pixs not defined", procName, 1);
01374 
01375     pixGetDimensions(pixs, &w, &h, NULL);
01376     for (j = 0; j < left; j++)
01377         pixRasterop(pixs, left - 1 - j, top, 1, h - top - bot, PIX_SRC,
01378                     pixs, left + j, top);
01379     for (j = 0; j < right; j++)
01380         pixRasterop(pixs, w - right + j, top, 1, h - top - bot, PIX_SRC,
01381                     pixs, w - right - 1 - j, top);
01382     for (i = 0; i < top; i++)
01383         pixRasterop(pixs, 0, top - 1 - i, w, 1, PIX_SRC,
01384                     pixs, 0, top + i);
01385     for (i = 0; i < bot; i++)
01386         pixRasterop(pixs, 0, h - bot + i, w, 1, PIX_SRC,
01387                     pixs, 0, h - bot - 1 - i);
01388 
01389     return 0;
01390 }
01391      
01392 
01393 /*!
01394  *  pixCopyBorder()
01395  *
01396  *      Input:  pixd (all depths; colormap ok; can be NULL)
01397  *              pixs (same depth and size as pixd)
01398  *              left, right, top, bot (number of pixels to copy)
01399  *      Return: pixd, or null on error if pixd is not defined
01400  *
01401  *  Notes:
01402  *      (1) pixd can be null, but otherwise it must be the same size
01403  *          and depth as pixs.  Always returns pixd.
01404  *      (1) This is useful in situations where by setting a few border
01405  *          pixels we can avoid having to copy all pixels in pixs into
01406  *          pixd as an initialization step for some operation.
01407  */
01408 PIX *
01409 pixCopyBorder(PIX     *pixd,
01410               PIX     *pixs,
01411               l_int32  left,
01412               l_int32  right,
01413               l_int32  top,
01414               l_int32  bot)
01415 {
01416 l_int32  w, h;
01417 
01418     PROCNAME("pixCopyBorder");
01419 
01420     if (!pixs)
01421         return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
01422 
01423     if (pixd) {
01424         if (pixd == pixs) {
01425             L_WARNING("same: nothing to do", procName);
01426             return pixd;
01427         }
01428         else if (!pixSizesEqual(pixs, pixd))
01429             return (PIX *)ERROR_PTR("pixs and pixd sizes differ",
01430                                     procName, pixd);
01431     }
01432     else {
01433         if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL)
01434             return (PIX *)ERROR_PTR("pixd not made", procName, pixd);
01435     }
01436 
01437     pixGetDimensions(pixs, &w, &h, NULL);
01438     pixRasterop(pixd, 0, 0, left, h, PIX_SRC, pixs, 0, 0);
01439     pixRasterop(pixd, w - right, 0, right, h, PIX_SRC, pixs, w - right, 0);
01440     pixRasterop(pixd, 0, 0, w, top, PIX_SRC, pixs, 0, 0);
01441     pixRasterop(pixd, 0, h - bot, w, bot, PIX_SRC, pixs, 0, h - bot);
01442 
01443     return pixd;
01444 }
01445 
01446 
01447 
01448 /*-------------------------------------------------------------*
01449  *                     Add and remove border                   *
01450  *-------------------------------------------------------------*/
01451 /*!
01452  *  pixAddBorder()
01453  *
01454  *      Input:  pixs (all depths; colormap ok)
01455  *              npix (number of pixels to be added to each side)
01456  *              val  (value of added border pixels)
01457  *      Return: pixd (with the added exterior pixels), or null on error
01458  *
01459  *  Notes:
01460  *      (1) See pixAddBorderGeneral() for values of white & black pixels.
01461  */
01462 PIX *
01463 pixAddBorder(PIX      *pixs,
01464              l_int32   npix,
01465              l_uint32  val)
01466 {
01467     PROCNAME("pixAddBorder");
01468 
01469     if (!pixs)
01470         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
01471     if (npix == 0)
01472         return pixClone(pixs);
01473     return pixAddBorderGeneral(pixs, npix, npix, npix, npix, val);
01474 }
01475 
01476 
01477 /*!
01478  *  pixAddBlackBorder()
01479  *
01480  *      Input:  pixs (all depths; colormap ok)
01481  *              npix (number of pixels to be added to each side)
01482  *      Return: pixd (with the added exterior pixels), or null on error
01483  */
01484 PIX *
01485 pixAddBlackBorder(PIX      *pixs,
01486                   l_int32   npix)
01487 {
01488 l_int32   d, val;
01489 PIXCMAP  *cmap;
01490 
01491     PROCNAME("pixAddBlackBorder");
01492 
01493     if (!pixs)
01494         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
01495     if (npix == 0)
01496         return pixClone(pixs);
01497 
01498     if ((cmap = pixGetColormap(pixs)) != NULL)
01499         pixcmapGetRankIntensity(cmap, 0.0, &val);
01500     else {
01501         d = pixGetDepth(pixs);
01502         val = (d == 1) ? 1 : 0;
01503     }
01504     return pixAddBorderGeneral(pixs, npix, npix, npix, npix, val);
01505 }
01506 
01507 
01508 /*!
01509  *  pixAddBorderGeneral()
01510  *
01511  *      Input:  pixs (all depths; colormap ok)
01512  *              left, right, top, bot  (number of pixels added)
01513  *              val   (value of added border pixels)
01514  *      Return: pixd (with the added exterior pixels), or null on error
01515  *
01516  *  Notes:
01517  *      (1) For binary images:
01518  *             white:  val = 0
01519  *             black:  val = 1
01520  *          For grayscale images:
01521  *             white:  val = 2 ** d - 1
01522  *             black:  val = 0
01523  *          For rgb color images:
01524  *             white:  val = 0xffffff00
01525  *             black:  val = 0
01526  *          For colormapped images, use 'index' found this way:
01527  *             white: pixcmapGetRankIntensity(cmap, 1.0, &index);
01528  *             black: pixcmapGetRankIntensity(cmap, 0.0, &index);
01529  */
01530 PIX *
01531 pixAddBorderGeneral(PIX      *pixs,
01532                     l_int32   left,
01533                     l_int32   right,
01534                     l_int32   top,
01535                     l_int32   bot,
01536                     l_uint32  val)
01537 {
01538 l_int32  ws, hs, wd, hd, d, op;
01539 PIX     *pixd;
01540 
01541     PROCNAME("pixAddBorderGeneral");
01542 
01543     if (!pixs)
01544         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
01545     if (left < 0 || right < 0 || top < 0 || bot < 0)
01546         return (PIX *)ERROR_PTR("negative border added!", procName, NULL);
01547 
01548     pixGetDimensions(pixs, &ws, &hs, &d);
01549     wd = ws + left + right;
01550     hd = hs + top + bot;
01551     if ((pixd = pixCreateNoInit(wd, hd, d)) == NULL)
01552         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
01553     pixCopyResolution(pixd, pixs);
01554     pixCopyColormap(pixd, pixs);
01555 
01556         /* Set the new border pixels */
01557     op = UNDEF;
01558     if (val == 0)
01559         op = PIX_CLR;
01560     else if ((d == 1 && val == 1) || (d == 2 && val == 3) ||
01561              (d == 4 && val == 0xf) || (d == 8 && val == 0xff) || 
01562              (d == 16 && val == 0xffff) || (d == 32 && (val >> 8) == 0xffffff))
01563         op = PIX_SET;
01564     if (op == UNDEF)
01565         pixSetAllArbitrary(pixd, val);   /* a little extra writing ! */
01566     else {
01567         pixRasterop(pixd, 0, 0, left, hd, op, NULL, 0, 0); 
01568         pixRasterop(pixd, wd - right, 0, right, hd, op, NULL, 0, 0); 
01569         pixRasterop(pixd, 0, 0, wd, top, op, NULL, 0, 0); 
01570         pixRasterop(pixd, 0, hd - bot, wd, bot, op, NULL, 0, 0); 
01571     }
01572 
01573         /* Copy pixs into the interior */
01574     pixRasterop(pixd, left, top, ws, hs, PIX_SRC, pixs, 0, 0);
01575     return pixd;
01576 }
01577 
01578 
01579 /*!
01580  *  pixRemoveBorder()
01581  *
01582  *      Input:  pixs (all depths; colormap ok)
01583  *              npix (number to be removed from each of the 4 sides)
01584  *      Return: pixd (with pixels removed around border), or null on error
01585  */
01586 PIX *
01587 pixRemoveBorder(PIX     *pixs,
01588                 l_int32  npix)
01589 {
01590     PROCNAME("pixRemoveBorder");
01591 
01592     if (!pixs)
01593         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
01594     if (npix == 0)
01595         return pixClone(pixs);
01596     return pixRemoveBorderGeneral(pixs, npix, npix, npix, npix);
01597 }
01598 
01599 
01600 /*!
01601  *  pixRemoveBorderGeneral()
01602  *
01603  *      Input:  pixs (all depths; colormap ok)
01604  *              left, right, top, bot  (number of pixels added)
01605  *      Return: pixd (with pixels removed around border), or null on error
01606  */
01607 PIX *
01608 pixRemoveBorderGeneral(PIX     *pixs,
01609                        l_int32  left,
01610                        l_int32  right,
01611                        l_int32  top,
01612                        l_int32  bot)
01613 {
01614 l_int32  ws, hs, wd, hd, d;
01615 PIX     *pixd;
01616 
01617     PROCNAME("pixRemoveBorderGeneral");
01618 
01619     if (!pixs)
01620         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
01621     if (left < 0 || right < 0 || top < 0 || bot < 0)
01622         return (PIX *)ERROR_PTR("negative border removed!", procName, NULL);
01623 
01624     pixGetDimensions(pixs, &ws, &hs, &d);
01625     wd = ws - left - right;
01626     hd = hs - top - bot;
01627     if (wd <= 0)
01628         return (PIX *)ERROR_PTR("width must be > 0", procName, NULL);
01629     if (hd <= 0)
01630         return (PIX *)ERROR_PTR("height must be > 0", procName, NULL);
01631     if ((pixd = pixCreateNoInit(wd, hd, d)) == NULL)
01632         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
01633     pixCopyResolution(pixd, pixs);
01634     pixCopyColormap(pixd, pixs);
01635 
01636     pixRasterop(pixd, 0, 0, wd, hd, PIX_SRC, pixs, left, top);
01637     return pixd;
01638 }
01639 
01640 
01641 /*!
01642  *  pixAddMirroredBorder()
01643  *
01644  *      Input:  pixs (all depths; colormap ok)
01645  *              left, right, top, bot (number of pixels added)
01646  *      Return: pixd, or null on error
01647  *
01648  *  Notes:
01649  *      (1) This applies what is effectively mirror boundary conditions.
01650  *          For the added border pixels in pixd, the pixels in pixs
01651  *          near the border are mirror-copied into the border region.
01652  *      (2) This is useful for avoiding special operations near
01653  *          boundaries when doing image processing operations
01654  *          such as rank filters and convolution.  In use, one first
01655  *          adds mirrored pixels to each side of the image.  The number
01656  *          of pixels added on each side is half the filter dimension.
01657  *          Then the image processing operations proceed over a
01658  *          region equal to the size of the original image, and
01659  *          write directly into a dest pix of the same size as pixs.
01660  *      (3) The general pixRasterop() is used for an in-place operation here
01661  *          because there is no overlap between the src and dest rectangles.
01662  */
01663 PIX  *
01664 pixAddMirroredBorder(PIX      *pixs,
01665                       l_int32  left,
01666                       l_int32  right,
01667                       l_int32  top,
01668                       l_int32  bot)
01669 {
01670 l_int32  i, j, w, h;
01671 PIX     *pixd;
01672 
01673     PROCNAME("pixAddMirroredBorder");
01674 
01675     if (!pixs)
01676         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
01677     pixGetDimensions(pixs, &w, &h, NULL);
01678     if (left > w || right > w || top > h || bot > h)
01679         return (PIX *)ERROR_PTR("border too large", procName, NULL);
01680 
01681         /* Set pixels on left, right, top and bottom, in that order */
01682     pixd = pixAddBorderGeneral(pixs, left, right, top, bot, 0);
01683     for (j = 0; j < left; j++)
01684         pixRasterop(pixd, left - 1 - j, top, 1, h, PIX_SRC,
01685                     pixd, left + j, top);
01686     for (j = 0; j < right; j++)
01687         pixRasterop(pixd, left + w + j, top, 1, h, PIX_SRC,
01688                     pixd, left + w - 1 - j, top);
01689     for (i = 0; i < top; i++)
01690         pixRasterop(pixd, 0, top - 1 - i, left + w + right, 1, PIX_SRC,
01691                     pixd, 0, top + i);
01692     for (i = 0; i < bot; i++)
01693         pixRasterop(pixd, 0, top + h + i, left + w + right, 1, PIX_SRC,
01694                     pixd, 0, top + h - 1 - i);
01695 
01696     return pixd;
01697 }
01698      
01699 /*!
01700  *  pixAddRepeatedBorder()
01701  *
01702  *      Input:  pixs (all depths; colormap ok)
01703  *              left, right, top, bot (number of pixels added)
01704  *      Return: pixd, or null on error
01705  *
01706  *  Notes:
01707  *      (1) This applies a repeated border, as if the central part of
01708  *          the image is tiled over the plane.  So, for example, the
01709  *          pixels in the left border come from the right side of the image.
01710  *      (2) The general pixRasterop() is used for an in-place operation here
01711  *          because there is no overlap between the src and dest rectangles.
01712  */
01713 PIX  *
01714 pixAddRepeatedBorder(PIX      *pixs,
01715                      l_int32  left,
01716                      l_int32  right,
01717                      l_int32  top,
01718                      l_int32  bot)
01719 {
01720 l_int32  w, h;
01721 PIX     *pixd;
01722 
01723     PROCNAME("pixAddRepeatedBorder");
01724 
01725     if (!pixs)
01726         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
01727     pixGetDimensions(pixs, &w, &h, NULL);
01728     if (left > w || right > w || top > h || bot > h)
01729         return (PIX *)ERROR_PTR("border too large", procName, NULL);
01730 
01731     pixd = pixAddBorderGeneral(pixs, left, right, top, bot, 0);
01732 
01733         /* Set pixels on left, right, top and bottom, in that order */
01734     pixRasterop(pixd, 0, top, left, h, PIX_SRC, pixd, w, top);
01735     pixRasterop(pixd, left + w, top, right, h, PIX_SRC, pixd, left, top);
01736     pixRasterop(pixd, 0, 0, left + w + right, top, PIX_SRC, pixd, 0, h);
01737     pixRasterop(pixd, 0, top + h, left + w + right, bot, PIX_SRC, pixd, 0, top);
01738 
01739     return pixd;
01740 }
01741      
01742 
01743 /*!
01744  *  pixAddMixedBorder()
01745  *
01746  *      Input:  pixs (all depths; colormap ok)
01747  *              left, right, top, bot (number of pixels added)
01748  *      Return: pixd, or null on error
01749  *
01750  *  Notes:
01751  *      (1) This applies mirrored boundary conditions horizontally
01752  *          and repeated b.c. vertically.
01753  *      (2) It is specifically used for avoiding special operations
01754  *          near boundaries when convolving a hue-saturation histogram
01755  *          with a given window size.  The repeated b.c. are used
01756  *          vertically for hue, and the mirrored b.c. are used
01757  *          horizontally for saturation.  The number of pixels added
01758  *          on each side is approximately (but not quite) half the
01759  *          filter dimension.  The image processing operations can
01760  *          then proceed over a region equal to the size of the original
01761  *          image, and write directly into a dest pix of the same
01762  *          size as pixs.
01763  *      (3) The general pixRasterop() can be used for an in-place
01764  *          operation here because there is no overlap between the
01765  *          src and dest rectangles.
01766  */
01767 PIX  *
01768 pixAddMixedBorder(PIX      *pixs,
01769                   l_int32  left,
01770                   l_int32  right,
01771                   l_int32  top,
01772                   l_int32  bot)
01773 {
01774 l_int32  j, w, h;
01775 PIX     *pixd;
01776 
01777     PROCNAME("pixAddMixedBorder");
01778 
01779     if (!pixs)
01780         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
01781     pixGetDimensions(pixs, &w, &h, NULL);
01782     if (left > w || right > w || top > h || bot > h)
01783         return (PIX *)ERROR_PTR("border too large", procName, NULL);
01784 
01785         /* Set mirrored pixels on left and right;
01786          * then set repeated pixels on top and bottom. */
01787     pixd = pixAddBorderGeneral(pixs, left, right, top, bot, 0);
01788     for (j = 0; j < left; j++)
01789         pixRasterop(pixd, left - 1 - j, top, 1, h, PIX_SRC,
01790                     pixd, left + j, top);
01791     for (j = 0; j < right; j++)
01792         pixRasterop(pixd, left + w + j, top, 1, h, PIX_SRC,
01793                     pixd, left + w - 1 - j, top);
01794     pixRasterop(pixd, 0, 0, left + w + right, top, PIX_SRC, pixd, 0, h);
01795     pixRasterop(pixd, 0, top + h, left + w + right, bot, PIX_SRC, pixd, 0, top);
01796 
01797     return pixd;
01798 }
01799      
01800 
01801 
01802 /*-------------------------------------------------------------*
01803  *                Color sample setting and extraction          *
01804  *-------------------------------------------------------------*/
01805 /*!
01806  *  pixCreateRGBImage()
01807  *
01808  *      Input:  8 bpp red pix
01809  *              8 bpp green pix
01810  *              8 bpp blue pix
01811  *      Return: 32 bpp pix, interleaved with 4 samples/pixel,
01812  *              or null on error
01813  *
01814  *  Notes:
01815  *      (1) the 4th byte, sometimes called the "alpha channel",
01816  *          and which is often used for blending between different
01817  *          images, is left with 0 value.
01818  *      (2) see Note (4) in pix.h for details on storage of
01819  *          8-bit samples within each 32-bit word.
01820  *      (3) This implementation, setting the r, g and b components
01821  *          sequentially, is much faster than setting them in parallel
01822  *          by constructing an RGB dest pixel and writing it to dest.
01823  *          The reason is there are many more cache misses when reading
01824  *          from 3 input images simultaneously.
01825  */
01826 PIX *
01827 pixCreateRGBImage(PIX  *pixr,
01828                   PIX  *pixg,
01829                   PIX  *pixb)
01830 {
01831 l_int32  wr, wg, wb, hr, hg, hb, dr, dg, db;
01832 PIX     *pixd;
01833 
01834     PROCNAME("pixCreateRGBImage");
01835 
01836     if (!pixr)
01837         return (PIX *)ERROR_PTR("pixr not defined", procName, NULL);
01838     if (!pixg)
01839         return (PIX *)ERROR_PTR("pixg not defined", procName, NULL);
01840     if (!pixb)
01841         return (PIX *)ERROR_PTR("pixb not defined", procName, NULL);
01842     pixGetDimensions(pixr, &wr, &hr, &dr);
01843     pixGetDimensions(pixg, &wg, &hg, &dg);
01844     pixGetDimensions(pixb, &wb, &hb, &db);
01845     if (dr != 8 || dg != 8 || db != 8)
01846         return (PIX *)ERROR_PTR("input pix not all 8 bpp", procName, NULL);
01847     if (wr != wg || wr != wb)
01848         return (PIX *)ERROR_PTR("widths not the same", procName, NULL);
01849     if (hr != hg || hr != hb)
01850         return (PIX *)ERROR_PTR("heights not the same", procName, NULL);
01851 
01852     if ((pixd = pixCreate(wr, hr, 32)) == NULL)
01853         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
01854     pixCopyResolution(pixd, pixr);
01855     pixSetRGBComponent(pixd, pixr, COLOR_RED);
01856     pixSetRGBComponent(pixd, pixg, COLOR_GREEN);
01857     pixSetRGBComponent(pixd, pixb, COLOR_BLUE);
01858 
01859     return pixd;
01860 }
01861 
01862 
01863 /*!
01864  *  pixGetRGBComponent()
01865  *
01866  *      Input:  pixs  (32 bpp)
01867  *              color  (one of {COLOR_RED, COLOR_GREEN, COLOR_BLUE,
01868  *                      L_ALPHA_CHANNEL})
01869  *      Return: pixd, the selected 8 bpp component image of the
01870  *              input 32 bpp image, or null on error
01871  *
01872  *  Notes:
01873  *      (1) The alpha channel (in the 4th byte of each RGB pixel)
01874  *          is mostly ignored in leptonica.
01875  *      (2) Three calls to this function generate the three 8 bpp component
01876  *          images.  This is much faster than generating the three
01877  *          images in parallel, by extracting a src pixel and setting
01878  *          the pixels of each component image from it.  The reason is
01879  *          there are many more cache misses when writing to three
01880  *          output images simultaneously.
01881  */
01882 PIX *
01883 pixGetRGBComponent(PIX     *pixs,
01884                    l_int32  color)
01885 {
01886 l_uint8    srcbyte;
01887 l_uint32  *lines, *lined;
01888 l_uint32  *datas, *datad;
01889 l_int32    i, j, w, h;
01890 l_int32    wpls, wpld;
01891 PIX           *pixd;
01892 
01893     PROCNAME("pixGetRGBComponent");
01894 
01895     if (!pixs)
01896         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
01897     if (pixGetDepth(pixs) != 32)
01898         return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
01899     if (color != COLOR_RED && color != COLOR_GREEN &&
01900         color != COLOR_BLUE && color != L_ALPHA_CHANNEL)
01901         return (PIX *)ERROR_PTR("invalid color", procName, NULL);
01902 
01903     pixGetDimensions(pixs, &w, &h, NULL);
01904     if ((pixd = pixCreate(w, h, 8)) == NULL)
01905         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
01906     pixCopyResolution(pixd, pixs);
01907     wpls = pixGetWpl(pixs);
01908     wpld = pixGetWpl(pixd);
01909     datas = pixGetData(pixs);
01910     datad = pixGetData(pixd);
01911 
01912     for (i = 0; i < h; i++) {
01913         lines = datas + i * wpls;
01914         lined = datad + i * wpld;
01915         for (j = 0; j < w; j++) {
01916             srcbyte = GET_DATA_BYTE(lines + j, color);
01917             SET_DATA_BYTE(lined, j, srcbyte);
01918         }
01919     }
01920 
01921     return pixd;
01922 }
01923 
01924 
01925 /*!
01926  *  pixSetRGBComponent()
01927  *
01928  *      Input:  pixd  (32 bpp)
01929  *              pixs  (8 bpp)
01930  *              color  (one of {COLOR_RED, COLOR_GREEN, COLOR_BLUE,
01931  *                      L_ALPHA_CHANNEL})
01932  *      Return: 0 if OK; 1 on error
01933  *
01934  *  Notes:
01935  *      (1) This places the 8 bpp pixel in pixs into the
01936  *          specified color component (properly interleaved) in pixd.
01937  *      (2) The alpha channel component mostly ignored in leptonica.
01938  */
01939 l_int32
01940 pixSetRGBComponent(PIX     *pixd,
01941                    PIX     *pixs,
01942                    l_int32  color)
01943 {
01944 l_uint8    srcbyte;
01945 l_int32    i, j, w, h;
01946 l_int32    wpls, wpld;
01947 l_uint32  *lines, *lined;
01948 l_uint32  *datas, *datad;
01949 
01950     PROCNAME("pixSetRGBComponent");
01951 
01952     if (!pixd)
01953         return ERROR_INT("pixd not defined", procName, 1);
01954     if (!pixs)
01955         return ERROR_INT("pixs not defined", procName, 1);
01956 
01957     if (pixGetDepth(pixd) != 32)
01958         return ERROR_INT("pixd not 32 bpp", procName, 1);
01959     if (pixGetDepth(pixs) != 8)
01960         return ERROR_INT("pixs not 8 bpp", procName, 1);
01961     if (color != COLOR_RED && color != COLOR_GREEN &&
01962         color != COLOR_BLUE && color != L_ALPHA_CHANNEL)
01963         return ERROR_INT("invalid color", procName, 1);
01964     pixGetDimensions(pixs, &w, &h, NULL);
01965     if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
01966         return ERROR_INT("sizes not commensurate", procName, 1);
01967 
01968     datas = pixGetData(pixs);
01969     datad = pixGetData(pixd);
01970     wpls = pixGetWpl(pixs);
01971     wpld = pixGetWpl(pixd);
01972     for (i = 0; i < h; i++) {
01973         lines = datas + i * wpls;
01974         lined = datad + i * wpld;
01975         for (j = 0; j < w; j++) {
01976             srcbyte = GET_DATA_BYTE(lines, j);
01977             SET_DATA_BYTE(lined + j, color, srcbyte);
01978         }
01979     }
01980 
01981     return 0;
01982 }
01983 
01984 
01985 /*!
01986  *  pixGetRGBComponentCmap()
01987  *
01988  *      Input:  pixs  (colormapped)
01989  *              color  (one of {COLOR_RED, COLOR_GREEN, COLOR_BLUE})
01990  *      Return: pixd  (the selected 8 bpp component image of the
01991  *                     input cmapped image), or null on error
01992  */
01993 PIX *
01994 pixGetRGBComponentCmap(PIX     *pixs,
01995                        l_int32  color)
01996 {
01997 l_int32     i, j, w, h, val, index;
01998 l_int32     wplc, wpld;
01999 l_uint32   *linec, *lined;
02000 l_uint32   *datac, *datad;
02001 PIX        *pixc, *pixd;
02002 PIXCMAP    *cmap;
02003 RGBA_QUAD  *cta;
02004 
02005     PROCNAME("pixGetRGBComponentCmap");
02006 
02007     if (!pixs)
02008         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
02009     if ((cmap = pixGetColormap(pixs)) == NULL)
02010         return (PIX *)ERROR_PTR("pixs not cmapped", procName, NULL);
02011     if (color != COLOR_RED && color != COLOR_GREEN &&
02012         color != COLOR_BLUE)
02013         return (PIX *)ERROR_PTR("invalid color", procName, NULL);
02014 
02015         /* If not 8 bpp, make a cmapped 8 bpp pix */
02016     if (pixGetDepth(pixs) == 8)
02017         pixc = pixClone(pixs);
02018     else
02019         pixc = pixConvertTo8(pixs, TRUE);
02020 
02021     pixGetDimensions(pixs, &w, &h, NULL);
02022     if ((pixd = pixCreateNoInit(w, h, 8)) == NULL)
02023         return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
02024     pixCopyResolution(pixd, pixs);
02025     wplc = pixGetWpl(pixc);
02026     wpld = pixGetWpl(pixd);
02027     datac = pixGetData(pixc);
02028     datad = pixGetData(pixd);
02029     cta = (RGBA_QUAD *)cmap->array;
02030 
02031     for (i = 0; i < h; i++) {
02032         linec = datac + i * wplc;
02033         lined = datad + i * wpld;
02034         if (color == COLOR_RED) {
02035             for (j = 0; j < w; j++) {
02036                 index = GET_DATA_BYTE(linec, j);
02037                 val = cta[index].red;
02038                 SET_DATA_BYTE(lined, j, val);
02039             }
02040         }
02041         else if (color == COLOR_GREEN) {
02042             for (j = 0; j < w; j++) {
02043                 index = GET_DATA_BYTE(linec, j);
02044                 val = cta[index].green;
02045                 SET_DATA_BYTE(lined, j, val);
02046             }
02047         }
02048         else if (color == COLOR_BLUE) {
02049             for (j = 0; j < w; j++) {
02050                 index = GET_DATA_BYTE(linec, j);
02051                 val = cta[index].green;
02052                 SET_DATA_BYTE(lined, j, val);
02053             }
02054         }
02055     }
02056 
02057     pixDestroy(&pixc);
02058     return pixd;
02059 }
02060 
02061 
02062 /*!
02063  *  composeRGBPixel()
02064  *
02065  *      Input:  rval, gval, bval
02066  *              &rgbpixel  (<return> 32-bit pixel)
02067  *      Return: 0 if OK; 1 on error
02068  *
02069  *  Notes:
02070  *      (1) A slower implementation uses macros:
02071  *            SET_DATA_BYTE(ppixel, COLOR_RED, rval);
02072  *            SET_DATA_BYTE(ppixel, COLOR_GREEN, gval);
02073  *            SET_DATA_BYTE(ppixel, COLOR_BLUE, bval);
02074  */
02075 l_int32
02076 composeRGBPixel(l_int32    rval,
02077                 l_int32    gval,
02078                 l_int32    bval,
02079                 l_uint32  *ppixel)
02080 {
02081     PROCNAME("composeRGBPixel");
02082 
02083     if (!ppixel)
02084         return ERROR_INT("&pixel not defined", procName, 1);
02085 
02086     *ppixel = (rval << L_RED_SHIFT) | (gval << L_GREEN_SHIFT) |
02087               (bval << L_BLUE_SHIFT);
02088     return 0;
02089 }
02090 
02091 
02092 /*!
02093  *  extractRGBValues()
02094  *
02095  *      Input:  pixel (32 bit)
02096  *              &rval (<optional return> red component)
02097  *              &gval (<optional return> green component)
02098  *              &bval (<optional return> blue component)
02099  *      Return: void
02100  *
02101  *  Notes:
02102  *      (1) A slower implementation uses macros:
02103  *             *prval = GET_DATA_BYTE(&pixel, COLOR_RED);
02104  *             *pgval = GET_DATA_BYTE(&pixel, COLOR_GREEN);
02105  *             *pbval = GET_DATA_BYTE(&pixel, COLOR_BLUE);
02106  */
02107 void
02108 extractRGBValues(l_uint32  pixel,
02109                  l_int32  *prval,
02110                  l_int32  *pgval,
02111                  l_int32  *pbval)
02112 {
02113     if (prval) *prval = (pixel >> L_RED_SHIFT) & 0xff;
02114     if (pgval) *pgval = (pixel >> L_GREEN_SHIFT) & 0xff;
02115     if (pbval) *pbval = (pixel >> L_BLUE_SHIFT) & 0xff;
02116     return;
02117 }
02118 
02119 
02120 /*!
02121  *  extractMinMaxComponent()
02122  *
02123  *      Input:  pixel (32 bpp RGB)
02124  *              type (L_CHOOSE_MIN or L_CHOOSE_MAX)
02125  *      Return: componet (in range [0 ... 255], or null on error
02126  */
02127 l_int32
02128 extractMinMaxComponent(l_uint32  pixel,
02129                        l_int32   type)
02130 {
02131 l_int32  rval, gval, bval, val;
02132 
02133     extractRGBValues(pixel, &rval, &gval, &bval);
02134     if (type == L_CHOOSE_MIN) {
02135         val = L_MIN(rval, gval);
02136         val = L_MIN(val, bval);
02137     }
02138     else {  /* type == L_CHOOSE_MAX */
02139         val = L_MAX(rval, gval);
02140         val = L_MAX(val, bval);
02141     }
02142     return val;
02143 }
02144 
02145 
02146 /*!
02147  *  pixGetRGBLine()
02148  *
02149  *      Input:  pixs  (32 bpp)
02150  *              row
02151  *              bufr  (array of red samples; size w bytes)
02152  *              bufg  (array of green samples; size w bytes)
02153  *              bufb  (array of blue samples; size w bytes)
02154  *      Return: 0 if OK; 1 on error
02155  *
02156  *  Notes:
02157  *      (1) This puts rgb components from the input line in pixs
02158  *          into the given buffers.
02159  */
02160 l_int32
02161 pixGetRGBLine(PIX      *pixs,
02162               l_int32   row,
02163               l_uint8  *bufr,
02164               l_uint8  *bufg,
02165               l_uint8  *bufb)
02166 {
02167 l_uint32  *lines;
02168 l_int32    j, w, h;
02169 l_int32    wpls;
02170 
02171     PROCNAME("pixGetRGBLine");
02172 
02173     if (!pixs)
02174         return ERROR_INT("pixs not defined", procName, 1);
02175     if (pixGetDepth(pixs) != 32)
02176         return ERROR_INT("pixs not 32 bpp", procName, 1);
02177     if (!bufr || !bufg || !bufb)
02178         return ERROR_INT("buffer not defined", procName, 1);
02179 
02180     pixGetDimensions(pixs, &w, &h, NULL);
02181     if (row < 0 || row >= h)
02182         return ERROR_INT("row out of bounds", procName, 1);
02183     wpls = pixGetWpl(pixs);
02184     lines = pixGetData(pixs) + row * wpls;
02185 
02186     for (j = 0; j < w; j++) {
02187         bufr[j] = GET_DATA_BYTE(lines + j, COLOR_RED);
02188         bufg[j] = GET_DATA_BYTE(lines + j, COLOR_GREEN);
02189         bufb[j] = GET_DATA_BYTE(lines + j, COLOR_BLUE);
02190     }
02191 
02192     return 0;
02193 }
02194 
02195 
02196 /*-------------------------------------------------------------*
02197  *                    Pixel endian conversion                  *
02198  *-------------------------------------------------------------*/
02199 /*!
02200  *  pixEndianByteSwapNew()
02201  *
02202  *      Input:  pixs
02203  *      Return: pixd, or null on error
02204  *
02205  *  Notes:
02206  *      (1) This is used to convert the data in a pix to a
02207  *          serialized byte buffer in raster order, and, for RGB,
02208  *          in order RGBA.  This requires flipping bytes within
02209  *          each 32-bit word for little-endian platforms, because the
02210  *          words have a MSB-to-the-left rule, whereas byte raster-order
02211  *          requires the left-most byte in each word to be byte 0.
02212  *          For big-endians, no swap is necessary, so this returns a clone.
02213  *      (2) Unlike pixEndianByteSwap(), which swaps the bytes in-place,
02214  *          this returns a new pix (or a clone).  We provide this
02215  *          because often when serialization is done, the source
02216  *          pix needs to be restored to canonical little-endian order,
02217  *          and this requires a second byte swap.  In such a situation,
02218  *          it is twice as fast to make a new pix in big-endian order,
02219  *          use it, and destroy it.
02220  */
02221 PIX *
02222 pixEndianByteSwapNew(PIX  *pixs)
02223 {
02224 l_uint32  *datas, *datad;
02225 l_int32    i, j, h, wpl;
02226 l_uint32   word;
02227 PIX       *pixd;
02228 
02229     PROCNAME("pixEndianByteSwapNew");
02230         
02231 #ifdef L_BIG_ENDIAN
02232 
02233     return pixClone(pixs);
02234 
02235 #else   /* L_LITTLE_ENDIAN */
02236 
02237     if (!pixs)
02238         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
02239 
02240     datas = pixGetData(pixs);
02241     wpl = pixGetWpl(pixs);
02242     h = pixGetHeight(pixs);
02243     pixd = pixCreateTemplate(pixs);
02244     datad = pixGetData(pixd);
02245     for (i = 0; i < h; i++) {
02246         for (j = 0; j < wpl; j++, datas++, datad++) {
02247             word = *datas;
02248             *datad = (word >> 24) |
02249                     ((word >> 8) & 0x0000ff00) |
02250                     ((word << 8) & 0x00ff0000) |
02251                     (word << 24);
02252         }
02253     }
02254 
02255     return pixd;
02256 
02257 #endif   /* L_BIG_ENDIAN */
02258 
02259 }
02260 
02261 
02262 /*!
02263  *  pixEndianByteSwap()
02264  *
02265  *      Input:  pixs
02266  *      Return: 0 if OK, 1 on error
02267  *
02268  *  Notes:
02269  *      (1) This is used on little-endian platforms to swap
02270  *          the bytes within a word; bytes 0 and 3 are swapped,
02271  *          and bytes 1 and 2 are swapped.
02272  *      (2) This is required for little-endians in situations
02273  *          where we convert from a serialized byte order that is
02274  *          in raster order, as one typically has in file formats,
02275  *          to one with MSB-to-the-left in each 32-bit word, or v.v.
02276  *          See pix.h for a description of the canonical format
02277  *          (MSB-to-the left) that is used for both little-endian
02278  *          and big-endian platforms.   For big-endians, the
02279  *          MSB-to-the-left word order has the bytes in raster
02280  *          order when serialized, so no byte flipping is required.
02281  */
02282 l_int32
02283 pixEndianByteSwap(PIX  *pixs)
02284 {
02285 l_uint32  *data;
02286 l_int32    i, j, h, wpl;
02287 l_uint32   word;
02288 
02289     PROCNAME("pixEndianByteSwap");
02290         
02291 #ifdef L_BIG_ENDIAN
02292 
02293     return 0;
02294 
02295 #else   /* L_LITTLE_ENDIAN */
02296 
02297     if (!pixs)
02298         return ERROR_INT("pixs not defined", procName, 1);
02299 
02300     data = pixGetData(pixs);
02301     wpl = pixGetWpl(pixs);
02302     h = pixGetHeight(pixs);
02303     for (i = 0; i < h; i++) {
02304         for (j = 0; j < wpl; j++, data++) {
02305             word = *data;
02306             *data = (word >> 24) |
02307                     ((word >> 8) & 0x0000ff00) |
02308                     ((word << 8) & 0x00ff0000) |
02309                     (word << 24);
02310         }
02311     }
02312 
02313     return 0;
02314 
02315 #endif   /* L_BIG_ENDIAN */
02316 
02317 }
02318 
02319 
02320 /*!
02321  *  lineEndianByteSwap()
02322  *
02323  *      Input   datad (dest byte array data, reordered on little-endians)
02324  *              datas (a src line of pix data)
02325  *              wpl (number of 32 bit words in the line)
02326  *      Return: 0 if OK, 1 on error
02327  *
02328  *  Notes:
02329  *      (1) This is used on little-endian platforms to swap
02330  *          the bytes within each word in the line of image data.
02331  *          Bytes 0 <==> 3 and 1 <==> 2 are swapped in the dest
02332  *          byte array data8d, relative to the pix data in datas.
02333  *      (2) The bytes represent 8 bit pixel values.  They are swapped
02334  *          for little endians so that when the dest array (char *)datad
02335  *          is addressed by bytes, the pixels are chosen sequentially
02336  *          from left to right in the image.
02337  */
02338 l_int32
02339 lineEndianByteSwap(l_uint32  *datad,
02340                    l_uint32  *datas,
02341                    l_int32    wpl)
02342 {
02343 l_int32   j;
02344 l_uint32  word;
02345 
02346     PROCNAME("lineEndianByteSwap");
02347 
02348     if (!datad || !datas)
02349         return ERROR_INT("datad and datas not both defined", procName, 1);
02350 
02351 #ifdef L_BIG_ENDIAN
02352 
02353     memcpy((char *)datad, (char *)datas, 4 * wpl);
02354     return 0;
02355 
02356 #else   /* L_LITTLE_ENDIAN */
02357 
02358     for (j = 0; j < wpl; j++, datas++, datad++) {
02359         word = *datas;
02360         *datad = (word >> 24) |
02361                  ((word >> 8) & 0x0000ff00) |
02362                  ((word << 8) & 0x00ff0000) |
02363                  (word << 24);
02364     }
02365     return 0;
02366 
02367 #endif   /* L_BIG_ENDIAN */
02368 
02369 }
02370 
02371 
02372 /*!
02373  *  pixEndianTwoByteSwapNew()
02374  *
02375  *      Input:  pixs
02376  *      Return: 0 if OK, 1 on error
02377  *
02378  *  Notes:
02379  *      (1) This is used on little-endian platforms to swap the
02380  *          2-byte entities within a 32-bit word.
02381  *      (2) This is equivalent to a full byte swap, as performed
02382  *          by pixEndianByteSwap(), followed by byte swaps in
02383  *          each of the 16-bit entities separately.
02384  *      (3) Unlike pixEndianTwoByteSwap(), which swaps the shorts in-place,
02385  *          this returns a new pix (or a clone).  We provide this
02386  *          to avoid having to swap twice in situations where the input
02387  *          pix must be restored to canonical little-endian order.
02388  */
02389 PIX *
02390 pixEndianTwoByteSwapNew(PIX  *pixs)
02391 {
02392 l_uint32  *datas, *datad;
02393 l_int32    i, j, h, wpl;
02394 l_uint32   word;
02395 PIX       *pixd;
02396 
02397     PROCNAME("pixEndianTwoByteSwapNew");
02398         
02399 #ifdef L_BIG_ENDIAN
02400 
02401     return pixClone(pixs);
02402 
02403 #else   /* L_LITTLE_ENDIAN */
02404 
02405     if (!pixs)
02406         return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
02407 
02408     datas = pixGetData(pixs);
02409     wpl = pixGetWpl(pixs);
02410     h = pixGetHeight(pixs);
02411     pixd = pixCreateTemplate(pixs);
02412     datad = pixGetData(pixd);
02413     for (i = 0; i < h; i++) {
02414         for (j = 0; j < wpl; j++, datas++, datad++) {
02415             word = *datas;
02416             *datad = (word << 16) | (word >> 16);
02417         }
02418     }
02419 
02420     return pixd;
02421 
02422 #endif   /* L_BIG_ENDIAN */
02423 
02424 }
02425 
02426 
02427 /*!
02428  *  pixEndianTwoByteSwap()
02429  *
02430  *      Input:  pixs
02431  *      Return: 0 if OK, 1 on error
02432  *
02433  *  Notes:
02434  *      (1) This is used on little-endian platforms to swap the
02435  *          2-byte entities within a 32-bit word.
02436  *      (2) This is equivalent to a full byte swap, as performed
02437  *          by pixEndianByteSwap(), followed by byte swaps in
02438  *          each of the 16-bit entities separately.
02439  */
02440 l_int32
02441 pixEndianTwoByteSwap(PIX  *pixs)
02442 {
02443 l_uint32  *data;
02444 l_int32    i, j, h, wpl;
02445 l_uint32   word;
02446 
02447     PROCNAME("pixEndianTwoByteSwap");
02448         
02449 #ifdef L_BIG_ENDIAN
02450 
02451     return 0;
02452 
02453 #else   /* L_LITTLE_ENDIAN */
02454 
02455     if (!pixs)
02456         return ERROR_INT("pixs not defined", procName, 1);
02457 
02458     data = pixGetData(pixs);
02459     wpl = pixGetWpl(pixs);
02460     h = pixGetHeight(pixs);
02461     for (i = 0; i < h; i++) {
02462         for (j = 0; j < wpl; j++, data++) {
02463             word = *data;
02464             *data = (word << 16) | (word >> 16);
02465         }
02466     }
02467 
02468     return 0;
02469 
02470 #endif   /* L_BIG_ENDIAN */
02471 
02472 }
02473 
02474 
02475 /*-------------------------------------------------------------*
02476  *             Extract raster data as binary string            *
02477  *-------------------------------------------------------------*/
02478 /*!
02479  *  pixGetRasterData()
02480  *
02481  *      Input:  pixs (1, 8, 32 bpp)
02482  *              &data (<return> raster data in memory)
02483  *              &nbytes (<return> number of bytes in data string)
02484  *      Return: 0 if OK, 1 on error
02485  *
02486  *  Notes:
02487  *      (1) This returns the raster data as a byte string, padded to the
02488  *          byte.  For 1 bpp, the first pixel is the MSbit in the first byte.
02489  *          For rgb, the bytes are in (rgb) order.  This is the format
02490  *          required for flate encoding of pixels in a PostScript file.
02491  */
02492 l_int32
02493 pixGetRasterData(PIX       *pixs,
02494                  l_uint8  **pdata,
02495                  size_t    *pnbytes)
02496 {
02497 l_int32    w, h, d, wpl, i, j, rval, gval, bval;
02498 l_int32    databpl;  /* bytes for each raster line in returned data */
02499 l_uint8   *line, *data;  /* packed data in returned array */
02500 l_uint32  *rline, *rdata;  /* data in pix raster */
02501 
02502     PROCNAME("pixGetRasterData");
02503 
02504     if (!pdata || !pnbytes)
02505         return ERROR_INT("&data and &nbytes not both defined", procName, 1);
02506     *pdata = NULL;
02507     *pnbytes = 0;
02508     if (!pixs)
02509         return ERROR_INT("pixs not defined", procName, 1);
02510     pixGetDimensions(pixs, &w, &h, &d);
02511     if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32)
02512         return ERROR_INT("depth not in {1,2,4,8,16,32}", procName, 1);
02513     rdata = pixGetData(pixs);
02514     wpl = pixGetWpl(pixs);
02515     if (d == 1)
02516         databpl = (w + 7) / 8;
02517     else if (d == 2)
02518         databpl = (w + 3) / 4;
02519     else if (d == 4)
02520         databpl = (w + 1) / 2;
02521     else if (d == 8 || d == 16)
02522         databpl = w * (d / 8);
02523     else  /* d == 32 bpp rgb */
02524         databpl = 3 * w;
02525     if ((data = (l_uint8 *)CALLOC(databpl * h, sizeof(l_uint8))) == NULL)
02526         return ERROR_INT("data not allocated", procName, 1);
02527     *pdata = data;
02528     *pnbytes = databpl * h;
02529 
02530     for (i = 0; i < h; i++) {
02531          rline = rdata + i * wpl;
02532          line = data + i * databpl;
02533          if (d <= 8) {
02534              for (j = 0; j < databpl; j++)
02535                   line[j] = GET_DATA_BYTE(rline, j);
02536          }
02537          else if (d == 16) {
02538              for (j = 0; j < w; j++)
02539                   line[2 * j] = GET_DATA_TWO_BYTES(rline, j);
02540          }
02541          else {  /* d == 32 bpp rgb */
02542              for (j = 0; j < w; j++) {
02543                   extractRGBValues(rline[j], &rval, &gval, &bval);
02544                   *(line + 3 * j) = rval;
02545                   *(line + 3 * j + 1) = gval;
02546                   *(line + 3 * j + 2) = bval;
02547              }
02548          }
02549     }
02550 
02551     return 0;
02552 }
02553 
02554 
02555 /*-------------------------------------------------------------*
02556  *             Setup helpers for 8 bpp byte processing         *
02557  *-------------------------------------------------------------*/
02558 /*!
02559  *  pixSetupByteProcessing()
02560  *
02561  *      Input:  pix (8 bpp, no colormap)
02562  *              &w (<optional return> width)
02563  *              &h (<optional return> height)
02564  *      Return: line ptr array, or null on error
02565  *
02566  *  Notes:
02567  *      (1) This is a simple helper for processing 8 bpp images with
02568  *          direct byte access.  It can swap byte order within each word.
02569  *      (2) After processing, you must call pixCleanupByteProcessing(),
02570  *          which frees the lineptr array and restores byte order.
02571  *      (3) Usage:
02572  *              l_uint8 **lineptrs = pixSetupByteProcessing(pix, &w, &h);
02573  *              for (i = 0; i < h; i++) {
02574  *                  l_uint8 *line = lineptrs[i];
02575  *                  for (j = 0; j < w; j++) {
02576  *                      val = line[j];
02577  *                      ...
02578  *                  }
02579  *              }
02580  *              pixCleanupByteProcessing(pix, lineptrs);
02581  */
02582 l_uint8 **
02583 pixSetupByteProcessing(PIX      *pix,
02584                        l_int32  *pw,
02585                        l_int32  *ph)
02586 {
02587 l_int32  w, h;
02588 
02589     PROCNAME("pixSetupByteProcessing");
02590 
02591     if (pw) *pw = 0;
02592     if (ph) *ph = 0;
02593     if (!pix || pixGetDepth(pix) != 8)
02594         return (l_uint8 **)ERROR_PTR("pix not defined or not 8 bpp",
02595                                      procName, NULL);
02596     if (pixGetColormap(pix))
02597         return (l_uint8 **)ERROR_PTR("pix has colormap", procName, NULL);
02598 
02599     pixGetDimensions(pix, &w, &h, NULL);
02600     if (pw) *pw = w;
02601     if (ph) *ph = h;
02602     pixEndianByteSwap(pix);
02603     return (l_uint8 **)pixGetLinePtrs(pix, NULL);
02604 }
02605 
02606 
02607 /*!
02608  *  pixCleanupByteProcessing()
02609  *
02610  *      Input:  pix (8 bpp, no colormap)
02611  *              lineptrs (ptrs to the beginning of each raster line of data)
02612  *      Return: 0 if OK, 1 on error
02613  *
02614  *  Notes:
02615  *      (1) This must be called after processing that was initiated
02616  *          by pixSetupByteProcessing() has finished.
02617  */
02618 l_int32
02619 pixCleanupByteProcessing(PIX      *pix,
02620                          l_uint8 **lineptrs)
02621 {
02622     PROCNAME("pixCleanupByteProcessing");
02623 
02624     if (!pix)
02625         return ERROR_INT("pix not defined", procName, 1);
02626     if (!lineptrs)
02627         return ERROR_INT("lineptrs not defined", procName, 1);
02628 
02629     pixEndianByteSwap(pix);
02630     FREE(lineptrs);
02631     return 0;
02632 }
02633 
02634 
02635 /*------------------------------------------------------------------------*
02636  *      Setting parameters for antialias masking with alpha transforms    *
02637  *------------------------------------------------------------------------*/
02638 /*!
02639  *  l_setAlphaMaskBorder()
02640  *
02641  *      Input:  val1, val2 (in [0.0 ... 1.0])
02642  *      Return: void
02643  *
02644  *  Notes:
02645  *      (1) This sets the opacity values used to generate the two outer
02646  *          boundary rings in the alpha mask associated with geometric
02647  *          transforms such as pixRotateWithAlpha().
02648  *      (2) The default values are val1 = 0.0 (completely transparent
02649  *          in the outermost ring) and val2 = 0.5 (half transparent
02650  *          in the second ring).  When the image is blended, this
02651  *          completely removes the outer ring (shrinking the image by
02652  *          2 in each direction), and alpha-blends with 0.5 the second ring.
02653  *      (3) The actual mask values are found by multiplying these
02654  *          normalized opacity values by 255.
02655  */
02656 void
02657 l_setAlphaMaskBorder(l_float32  val1,
02658                      l_float32  val2)
02659 {
02660     val1 = L_MAX(0.0, L_MIN(1.0, val1));
02661     val2 = L_MAX(0.0, L_MIN(1.0, val2));
02662     AlphaMaskBorderVals[0] = val1;
02663     AlphaMaskBorderVals[1] = val2;
02664 }
02665 
02666 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines