src/writefile.c
l_int32
pixSaveTiledOutline(PIX     *pixs,
                    PIXA    *pixa,
                    l_int32  reduction,
                    l_int32  newrow,
                    l_int32  space,
                    l_int32  linewidth,
                    l_int32  dp)
{
l_int32         n, top, left, bx, by, bw, w, h, depth, bottom;
l_float32       scale;
BOX            *box;
PIX            *pix, *pixt1, *pixt2, *pixt3;

    PROCNAME("pixSaveTiledOutline");

    if (reduction == 0) return 0;

    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if (!pixa)
        return ERROR_INT("pixa not defined", procName, 1);

    n = pixaGetCount(pixa);
    if (n == 0) {
        bottom = 0;
        if (dp != 8 && dp != 32) {
            L_WARNING("dp not 8 or 32 bpp; using 32", procName);
            depth = 32;
        } else
            depth = dp;
    }
    else {  /* extract the depth and bottom params from the first pix */
        pix = pixaGetPix(pixa, 0, L_CLONE);
        depth = pixGetDepth(pix);
        bottom = pixGetInputFormat(pix);  /* not typical usage! */
        pixDestroy(&pix);
    }

        /* Scale and convert to output depth */
    if (reduction == 1)
        pixt1 = pixClone(pixs);
    else {
        scale = 1. / (l_float32)reduction;
        if (pixGetDepth(pixs) == 1)
            pixt1 = pixScaleToGray(pixs, scale);
        else
            pixt1 = pixScale(pixs, scale, scale);
    }
    if (depth == 8)
        pixt2 = pixConvertTo8(pixt1, 0);
    else
        pixt2 = pixConvertTo32(pixt1);
    pixDestroy(&pixt1);

        /* Add black outline */
    if (linewidth > 0)
        pixt3 = pixAddBorder(pixt2, linewidth, 0);
    else
        pixt3 = pixClone(pixt2);
    pixDestroy(&pixt2);

        /* Find position of current pix (UL corner plus size) */
    if (n == 0) {
        top = 0;
        left = 0;
    }
    else if (newrow == 1) {
        top = bottom + space;
        left = 0;
    }
    else if (n > 0) {
        pixaGetBoxGeometry(pixa, n - 1, &bx, &by, &bw, NULL);
        top = by;
        left = bx + bw + space;
    }

    pixGetDimensions(pixt3, &w, &h, NULL);
    bottom = L_MAX(bottom, top + h);
    box = boxCreate(left, top, w, h);
    pixaAddPix(pixa, pixt3, L_INSERT);
    pixaAddBox(pixa, box, L_INSERT);

        /* Save the new bottom value */
    pix = pixaGetPix(pixa, 0, L_CLONE);
    pixSetInputFormat(pix, bottom);  /* not typical usage! */
    pixDestroy(&pix);

    return 0;
}
/*!
 *  pixSaveTiledOutline()
 *
 *      Input:  pixs (1, 2, 4, 8, 32 bpp)
 *              pixa (the pix are accumulated here)
 *              reduction (0 to disable; otherwise this is a reduction factor)
 *              newrow (0 if placed on the same row as previous; 1 otherwise)
 *              space (horizontal and vertical spacing, in pixels)
 *              linewidth (width of added outline for image; 0 for no outline)
 *              dp (depth of pixa; 8 or 32 bpp; only used on first call)
 *      Return: 0 if OK, 1 on error.
 *
 *  Notes:
 *      (1) Before calling this function for the first time, use
 *          pixaCreate() to make the @pixa that will accumulate the pix.
 *          This is passed in each time pixSaveTiled() is called.
 *      (2) @reduction is the integer reduction factor for the input
 *          image.  After reduction and possible depth conversion,
 *          the image is saved in the input pixa, along with a box
 *          that specifies the location to place it when tiled later.
 *          Disable saving the pix by setting reduction == 0.
 *      (3) @newrow and @space specify the location of the new pix
 *          with respect to the last one(s) that were entered.
 *      (4) @dp specifies the depth at which all pix are saved.  It can
 *          be only 8 or 32 bpp.  Any colormap is removed.  This is only
 *          used at the first invocation.
 *      (5) This function uses two variables from call to call.
 *          If they were static, the function would not be .so or thread
 *          safe, and furthermore, there would be interference with two or
 *          more pixa accumulating images at a time.  Consequently,
 *          we use the first pix in the pixa to store and obtain both
 *          the depth and the current position of the bottom (one pixel
 *          below the lowest image raster line when laid out using
 *          the boxa).  The bottom variable is stored in the input format
 *          field, which is the only field available for storing an int.
 */


(1) Before calling this function for the first time, use
pixaCreate() to make the @pixa that will accumulate the pix.
This is passed in each time pixSaveTiled() is called.
(2) @reduction is the integer reduction factor for the input
image.  After reduction and possible depth conversion,
the image is saved in the input pixa, along with a box
that specifies the location to place it when tiled later.
Disable saving the pix by setting reduction == 0.
(3) @newrow and @space specify the location of the new pix
with respect to the last one(s) that were entered.
(4) @dp specifies the depth at which all pix are saved.  It can
be only 8 or 32 bpp.  Any colormap is removed.  This is only
used at the first invocation.
(5) This function uses two variables from call to call.
If they were static, the function would not be .so or thread
safe, and furthermore, there would be interference with two or
more pixa accumulating images at a time.  Consequently,
we use the first pix in the pixa to store and obtain both
the depth and the current position of the bottom (one pixel
below the lowest image raster line when laid out using
the boxa).  The bottom variable is stored in the input format
field, which is the only field available for storing an int.
( 1 ) Before calling this function for the first time use pixaCreate () to make the @pixa that will accumulate the pix . This is passed in each time pixSaveTiled () is called . ( 2 ) @reduction is the integer reduction factor for the input image . After reduction and possible depth conversion the image is saved in the input pixa along with a box that specifies the location to place it when tiled later . Disable saving the pix by setting reduction == 0 . ( 3 ) @newrow and @space specify the location of the new pix with respect to the last one ( s ) that were entered . ( 4 ) @dp specifies the depth at which all pix are saved . It can be only 8 or 32 bpp . Any colormap is removed . This is only used at the first invocation . ( 5 ) This function uses two variables from call to call . If they were static the function would not be . so or thread safe and furthermore there would be interference with two or more pixa accumulating images at a time . Consequently we use the first pix in the pixa to store and obtain both the depth and the current position of the bottom ( one pixel below the lowest image raster line when laid out using the boxa ) . The bottom variable is stored in the input format field which is the only field available for storing an int .
l_int32
pixSaveTiledOutline(PIX     *pixs,
                    PIXA    *pixa,
                    l_int32  reduction,
                    l_int32  newrow,
                    l_int32  space,
                    l_int32  linewidth,
                    l_int32  dp)
{
l_int32         n, top, left, bx, by, bw, w, h, depth, bottom;
l_float32       scale;
BOX            *box;
PIX            *pix, *pixt1, *pixt2, *pixt3;
    PROCNAME("pixSaveTiledOutline");
    if (reduction == 0) return 0;
    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if (!pixa)
        return ERROR_INT("pixa not defined", procName, 1);
    n = pixaGetCount(pixa);
    if (n == 0) {
        bottom = 0;
        if (dp != 8 && dp != 32) {
            L_WARNING("dp not 8 or 32 bpp; using 32", procName);
            depth = 32;
        } else
            depth = dp;
    }
    else {  
        pix = pixaGetPix(pixa, 0, L_CLONE);
        depth = pixGetDepth(pix);
        bottom = pixGetInputFormat(pix);  
        pixDestroy(&pix);
    }
    if (reduction == 1)
        pixt1 = pixClone(pixs);
    else {
        scale = 1. / (l_float32)reduction;
        if (pixGetDepth(pixs) == 1)
            pixt1 = pixScaleToGray(pixs, scale);
        else
            pixt1 = pixScale(pixs, scale, scale);
    }
    if (depth == 8)
        pixt2 = pixConvertTo8(pixt1, 0);
    else
        pixt2 = pixConvertTo32(pixt1);
    pixDestroy(&pixt1);
    if (linewidth > 0)
        pixt3 = pixAddBorder(pixt2, linewidth, 0);
    else
        pixt3 = pixClone(pixt2);
    pixDestroy(&pixt2);
    if (n == 0) {
        top = 0;
        left = 0;
    }
    else if (newrow == 1) {
        top = bottom + space;
        left = 0;
    }
    else if (n > 0) {
        pixaGetBoxGeometry(pixa, n - 1, &bx, &by, &bw, NULL);
        top = by;
        left = bx + bw + space;
    }
    pixGetDimensions(pixt3, &w, &h, NULL);
    bottom = L_MAX(bottom, top + h);
    box = boxCreate(left, top, w, h);
    pixaAddPix(pixa, pixt3, L_INSERT);
    pixaAddBox(pixa, box, L_INSERT);
    pix = pixaGetPix(pixa, 0, L_CLONE);
    pixSetInputFormat(pix, bottom);  
    pixDestroy(&pix);
    return 0;
}
l_int32 pixSaveTiledOutline ( PIX * pixs , PIXA * pixa , l_int32 reduction , l_int32 newrow , l_int32 space , l_int32 linewidth , l_int32 dp ) { l_int32 n , top , left , bx , by , bw , w , h , depth , bottom ; l_float32 scale ; BOX * box ; PIX * pix , * pixt1 , * pixt2 , * pixt3 ; PROCNAME ( " " ) ; if ( reduction == 0 ) return 0 ; if ( ! pixs ) return ERROR_INT ( " " , procName , 1 ) ; if ( ! pixa ) return ERROR_INT ( " " , procName , 1 ) ; n = pixaGetCount ( pixa ) ; if ( n == 0 ) { bottom = 0 ; if ( dp != 8 && dp != 32 ) { L_WARNING ( " " , procName ) ; depth = 32 ; } else depth = dp ; } else { pix = pixaGetPix ( pixa , 0 , L_CLONE ) ; depth = pixGetDepth ( pix ) ; bottom = pixGetInputFormat ( pix ) ; pixDestroy ( & pix ) ; } if ( reduction == 1 ) pixt1 = pixClone ( pixs ) ; else { scale = 1. / ( l_float32 ) reduction ; if ( pixGetDepth ( pixs ) == 1 ) pixt1 = pixScaleToGray ( pixs , scale ) ; else pixt1 = pixScale ( pixs , scale , scale ) ; } if ( depth == 8 ) pixt2 = pixConvertTo8 ( pixt1 , 0 ) ; else pixt2 = pixConvertTo32 ( pixt1 ) ; pixDestroy ( & pixt1 ) ; if ( linewidth > 0 ) pixt3 = pixAddBorder ( pixt2 , linewidth , 0 ) ; else pixt3 = pixClone ( pixt2 ) ; pixDestroy ( & pixt2 ) ; if ( n == 0 ) { top = 0 ; left = 0 ; } else if ( newrow == 1 ) { top = bottom + space ; left = 0 ; } else if ( n > 0 ) { pixaGetBoxGeometry ( pixa , n - 1 , & bx , & by , & bw , NULL ) ; top = by ; left = bx + bw + space ; } pixGetDimensions ( pixt3 , & w , & h , NULL ) ; bottom = L_MAX ( bottom , top + h ) ; box = boxCreate ( left , top , w , h ) ; pixaAddPix ( pixa , pixt3 , L_INSERT ) ; pixaAddBox ( pixa , box , L_INSERT ) ; pix = pixaGetPix ( pixa , 0 , L_CLONE ) ; pixSetInputFormat ( pix , bottom ) ; pixDestroy ( & pix ) ; return 0 ; }
pixSaveTiledOutline()
      Input:  pixs (1, 2, 4, 8, 32 bpp)
              pixa (the pix are accumulated here)
              reduction (0 to disable; otherwise this is a reduction factor)
              newrow (0 if placed on the same row as previous; 1 otherwise)
              space (horizontal and vertical spacing, in pixels)
              linewidth (width of added outline for image; 0 for no outline)
              dp (depth of pixa; 8 or 32 bpp; only used on first call)
      Return: 0 if OK, 1 on error.
pixSaveTiledOutline () Input : pixs ( 1 2 4 8 32 bpp ) pixa ( the pix are accumulated here ) reduction ( 0 to disable ; otherwise this is a reduction factor ) newrow ( 0 if placed on the same row as previous ; 1 otherwise ) space ( horizontal and vertical spacing in pixels ) linewidth ( width of added outline for image ; 0 for no outline ) dp ( depth of pixa ; 8 or 32 bpp ; only used on first call ) Return : 0 if OK 1 on error .
/* extract the depth and bottom params from the first pix */ /* not typical usage! */ /* Scale and convert to output depth */ /* Add black outline */ /* Find position of current pix (UL corner plus size) */ /* Save the new bottom value */ /* not typical usage! */