Esempio n. 1
0
/*!
 * \brief   pixWriteMemBmp()
 *
 * \param[out]   pfdata   data of bmp formatted image
 * \param[out]   pfsize    size of returned data
 * \param[in]    pixs      1, 2, 4, 8, 16, 32 bpp
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) 2 bpp bmp files are not valid in the spec, and are
 *          written as 8 bpp.
 *      (2) pix with depth <= 8 bpp are written with a colormap.
 *          16 bpp gray and 32 bpp rgb pix are written without a colormap.
 *      (3) The transparency component in an rgb pix is ignored.
 *          All 32 bpp pix have the bmp alpha component set to 255 (opaque).
 *      (4) The bmp colormap entries, RGBA_QUAD, are the same as
 *          the ones used for colormaps in leptonica.  This allows
 *          a simple memcpy for bmp output.
 * </pre>
 */
l_int32
pixWriteMemBmp(l_uint8  **pfdata,
               size_t    *pfsize,
               PIX       *pixs)
{
l_uint8     pel[4];
l_uint8    *cta = NULL;     /* address of the bmp color table array */
l_uint8    *fdata, *data, *fmdata;
l_int32     cmaplen;      /* number of bytes in the bmp colormap */
l_int32     ncolors, val, stepsize;
l_int32     w, h, d, fdepth, xres, yres;
l_int32     pixWpl, pixBpl, extrabytes, fBpl, fWpl, i, j, k;
l_int32     heapcm;  /* extra copy of cta on the heap ? 1 : 0 */
l_uint32    offbytes, fimagebytes;
l_uint32   *line, *pword;
size_t      fsize;
BMP_FH     *bmpfh;
BMP_IH     *bmpih;
PIX        *pix;
PIXCMAP    *cmap;
RGBA_QUAD  *pquad;

    PROCNAME("pixWriteMemBmp");

    if (pfdata) *pfdata = NULL;
    if (pfsize) *pfsize = 0;
    if (!pfdata)
        return ERROR_INT("&fdata not defined", procName, 1 );
    if (!pfsize)
        return ERROR_INT("&fsize not defined", procName, 1 );
    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);

    pixGetDimensions(pixs, &w, &h, &d);
    if (d == 2) {
        L_WARNING("2 bpp files can't be read; converting to 8 bpp\n", procName);
        pix = pixConvert2To8(pixs, 0, 85, 170, 255, 1);
        d = 8;
    } else {
        pix = pixCopy(NULL, pixs);
    }
    fdepth = (d == 32) ? 24 : d;

        /* Resolution is given in pixels/meter */
    xres = (l_int32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
    yres = (l_int32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);

    pixWpl = pixGetWpl(pix);
    pixBpl = 4 * pixWpl;
    fWpl = (w * fdepth + 31) / 32;
    fBpl = 4 * fWpl;
    fimagebytes = h * fBpl;
    if (fimagebytes > 4LL * L_MAX_ALLOWED_PIXELS) {
        pixDestroy(&pix);
        return ERROR_INT("image data is too large", procName, 1);
    }

        /* If not rgb or 16 bpp, the bmp data is required to have a colormap */
    heapcm = 0;
    if (d == 32 || d == 16) {   /* 24 bpp rgb or 16 bpp: no colormap */
        ncolors = 0;
        cmaplen = 0;
    } else if ((cmap = pixGetColormap(pix))) {   /* existing colormap */
        ncolors = pixcmapGetCount(cmap);
        cmaplen = ncolors * sizeof(RGBA_QUAD);
        cta = (l_uint8 *)cmap->array;
    } else {   /* no existing colormap; d <= 8; make a binary or gray one */
        if (d == 1) {
            cmaplen  = sizeof(bwmap);
            ncolors = 2;
            cta = (l_uint8 *)bwmap;
        } else {   /* d = 2,4,8; use a grayscale output colormap */
            ncolors = 1 << fdepth;
            cmaplen = ncolors * sizeof(RGBA_QUAD);
            heapcm = 1;
            cta = (l_uint8 *)LEPT_CALLOC(cmaplen, 1);
            stepsize = 255 / (ncolors - 1);
            for (i = 0, val = 0, pquad = (RGBA_QUAD *)cta;
                 i < ncolors;
                 i++, val += stepsize, pquad++) {
                pquad->blue = pquad->green = pquad->red = val;
                pquad->alpha = 255;  /* opaque */
            }
        }
    }

#if DEBUG
    {l_uint8  *pcmptr;
        pcmptr = (l_uint8 *)pixGetColormap(pix)->array;
        fprintf(stderr, "Pix colormap[0] = %c%c%c%d\n",
            pcmptr[0], pcmptr[1], pcmptr[2], pcmptr[3]);
        fprintf(stderr, "Pix colormap[1] = %c%c%c%d\n",
            pcmptr[4], pcmptr[5], pcmptr[6], pcmptr[7]);
    }
#endif  /* DEBUG */

    offbytes = BMP_FHBYTES + BMP_IHBYTES + cmaplen;
    fsize = offbytes + fimagebytes;
    fdata = (l_uint8 *)LEPT_CALLOC(fsize, 1);
    *pfdata = fdata;
    *pfsize = fsize;

        /* Convert to little-endian and write the file header data */
    bmpfh = (BMP_FH *)fdata;
    bmpfh->bfType = convertOnBigEnd16(BMP_ID);
    bmpfh->bfSize = convertOnBigEnd16(fsize & 0x0000ffff);
    bmpfh->bfFill1 = convertOnBigEnd16((fsize >> 16) & 0x0000ffff);
    bmpfh->bfOffBits = convertOnBigEnd16(offbytes & 0x0000ffff);
    bmpfh->bfFill2 = convertOnBigEnd16((offbytes >> 16) & 0x0000ffff);

        /* Convert to little-endian and write the info header data */
    bmpih = (BMP_IH *)(fdata + BMP_FHBYTES);
    bmpih->biSize = convertOnBigEnd32(BMP_IHBYTES);
    bmpih->biWidth = convertOnBigEnd32(w);
    bmpih->biHeight = convertOnBigEnd32(h);
    bmpih->biPlanes = convertOnBigEnd16(1);
    bmpih->biBitCount = convertOnBigEnd16(fdepth);
    bmpih->biSizeImage = convertOnBigEnd32(fimagebytes);
    bmpih->biXPelsPerMeter = convertOnBigEnd32(xres);
    bmpih->biYPelsPerMeter = convertOnBigEnd32(yres);
    bmpih->biClrUsed = convertOnBigEnd32(ncolors);
    bmpih->biClrImportant = convertOnBigEnd32(ncolors);

        /* Copy the colormap data and free the cta if necessary */
    if (ncolors > 0) {
        memcpy(fdata + BMP_FHBYTES + BMP_IHBYTES, cta, cmaplen);
        if (heapcm) LEPT_FREE(cta);
    }

        /* When you write a binary image with a colormap
         * that sets BLACK to 0, you must invert the data */
    if (fdepth == 1 && cmap && ((l_uint8 *)(cmap->array))[0] == 0x0) {
        pixInvert(pix, pix);
    }

        /* An endian byte swap is also required */
    pixEndianByteSwap(pix);

        /* Transfer the image data.  Image origin for bmp is at lower right. */
    fmdata = fdata + offbytes;
    if (fdepth != 24) {   /* typ 1 or 8 bpp */
        data = (l_uint8 *)pixGetData(pix) + pixBpl * (h - 1);
        for (i = 0; i < h; i++) {
            memcpy(fmdata, data, fBpl);
            data -= pixBpl;
            fmdata += fBpl;
        }
    } else {  /* 32 bpp pix; 24 bpp file
             * See the comments in pixReadStreamBmp() to
             * understand the logic behind the pixel ordering below.
             * Note that we have again done an endian swap on
             * little endian machines before arriving here, so that
             * the bytes are ordered on both platforms as:
                        Red         Green        Blue         --
                    |-----------|------------|-----------|-----------|
             */
        extrabytes = fBpl - 3 * w;
        line = pixGetData(pix) + pixWpl * (h - 1);
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                pword = line + j;
                pel[2] = *((l_uint8 *)pword + COLOR_RED);
                pel[1] = *((l_uint8 *)pword + COLOR_GREEN);
                pel[0] = *((l_uint8 *)pword + COLOR_BLUE);
                memcpy(fmdata, &pel, 3);
                fmdata += 3;
            }
            if (extrabytes) {
                for (k = 0; k < extrabytes; k++) {
                    memcpy(fmdata, &pel, 1);
                    fmdata++;
                }
            }
            line -= pixWpl;
        }
    }

    pixDestroy(&pix);
    return 0;
}
Esempio n. 2
0
main(int    argc,
     char **argv)
{
char         *filein, *fileout;
l_int32       d, same;
PIX          *pixs, *pixd, *pixt0, *pixt1, *pixt2, *pixt3, *pixt4, *pixt5;
static char   mainName[] = "converttogray";

    if (argc != 2 && argc != 3)
	exit(ERROR_INT(" Syntax:  converttogray filein [fileout]",
	               mainName, 1));

    filein = argv[1];
    fileout = argv[2];

    if ((pixs = pixRead(filein)) == NULL)
	exit(ERROR_INT("pixs not made", mainName, 1));

#if 0
    pixd = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33);
    pixWrite(fileout, pixd, IFF_PNG);
    pixDestroy(&pixd);
#endif

#if 1
    d = pixGetDepth(pixs);
    if (d == 2) {
	pixt1 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, TRUE);
	pixt2 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, FALSE);
	pixEqual(pixt1, pixt2, &same);
	if (same)
	    fprintf(stderr, "images are the same\n");
	else
	    fprintf(stderr, "images are different!\n");
	pixWrite("/tmp/junkpixt1", pixt1, IFF_PNG);
	pixWrite("/tmp/junkpixt2", pixt2, IFF_PNG);
	pixDestroy(&pixt1);
	pixDestroy(&pixt2);
	pixSetColormap(pixs, NULL);
	pixt3 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, TRUE);
	pixt4 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, FALSE);
	pixEqual(pixt3, pixt4, &same);
	if (same)
	    fprintf(stderr, "images are the same\n");
	else
	    fprintf(stderr, "images are different!\n");
	pixWrite("/tmp/junkpixt3", pixt3, IFF_PNG);
	pixWrite("/tmp/junkpixt4", pixt4, IFF_PNG);
	pixDestroy(&pixt3);
	pixDestroy(&pixt4);
    }
    else if (d == 4) {
	pixt1 = pixConvert4To8(pixs, TRUE);
	pixt2 = pixConvert4To8(pixs, FALSE);
	pixEqual(pixt1, pixt2, &same);
	if (same)
	    fprintf(stderr, "images are the same\n");
	else
	    fprintf(stderr, "images are different!\n");
	pixWrite("/tmp/junkpixt1", pixt1, IFF_PNG);
	pixWrite("/tmp/junkpixt2", pixt2, IFF_PNG);
	pixDestroy(&pixt1);
	pixDestroy(&pixt2);
	pixSetColormap(pixs, NULL);
	pixt3 = pixConvert4To8(pixs, TRUE);
	pixt4 = pixConvert4To8(pixs, FALSE);
	pixEqual(pixt3, pixt4, &same);
	if (same)
	    fprintf(stderr, "images are the same\n");
	else
	    fprintf(stderr, "images are different!\n");
	pixWrite("/tmp/junkpixt3", pixt3, IFF_PNG);
	pixWrite("/tmp/junkpixt4", pixt4, IFF_PNG);
	pixDestroy(&pixt3);
	pixDestroy(&pixt4);
    }
#endif

    pixDestroy(&pixs);
    return 0;
}
Esempio n. 3
0
int main(int    argc,
          char **argv)
{
char         *filein;
char         *fileout = NULL;
l_int32       d, same;
PIX          *pixs, *pixd, *pix1, *pix2, *pix3, *pix4;
static char   mainName[] = "converttogray";

    if (argc != 2 && argc != 3)
        return ERROR_INT(" Syntax:  converttogray filein [fileout]",
                         mainName, 1);

    filein = argv[1];
    if (argc == 3) fileout = argv[2];
    if ((pixs = pixRead(filein)) == NULL)
        return ERROR_INT("pixs not made", mainName, 1);

    if (fileout) {
        pixd = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33);
        pixWrite(fileout, pixd, IFF_PNG);
        pixDestroy(&pixs);
        pixDestroy(&pixd);
        return 0;
    }

    d = pixGetDepth(pixs);
    if (d == 2) {
        pix1 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, TRUE);
        pix2 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, FALSE);
        pixEqual(pix1, pix2, &same);
        if (same)
            fprintf(stderr, "images are the same\n");
        else
            fprintf(stderr, "images are different!\n");
        pixWrite("/tmp/pix1.png", pix1, IFF_PNG);
        pixWrite("/tmp/pix2.png", pix2, IFF_PNG);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixSetColormap(pixs, NULL);
        pix3 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, TRUE);
        pix4 = pixConvert2To8(pixs, 0x00, 0x55, 0xaa, 0xff, FALSE);
        pixEqual(pix3, pix4, &same);
        if (same)
            fprintf(stderr, "images are the same\n");
        else
            fprintf(stderr, "images are different!\n");
        pixWrite("/tmp/pix3.png", pix3, IFF_PNG);
        pixWrite("/tmp/pix4.png", pix4, IFF_PNG);
        pixDestroy(&pix3);
        pixDestroy(&pix4);
    } else if (d == 4) {
        pix1 = pixConvert4To8(pixs, TRUE);
        pix2 = pixConvert4To8(pixs, FALSE);
        pixEqual(pix1, pix2, &same);
        if (same)
            fprintf(stderr, "images are the same\n");
        else
            fprintf(stderr, "images are different!\n");
        pixWrite("/tmp/pix1.png", pix1, IFF_PNG);
        pixWrite("/tmp/pix2.png", pix2, IFF_PNG);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
        pixSetColormap(pixs, NULL);
        pix3 = pixConvert4To8(pixs, TRUE);
        pix4 = pixConvert4To8(pixs, FALSE);
        pixEqual(pix3, pix4, &same);
        if (same)
            fprintf(stderr, "images are the same\n");
        else
            fprintf(stderr, "images are different!\n");
        pixWrite("/tmp/pix3.png", pix3, IFF_PNG);
        pixWrite("/tmp/pix4.png", pix4, IFF_PNG);
        pixDestroy(&pix3);
        pixDestroy(&pix4);
    } else {
        L_INFO("only converts 2 and 4 bpp; d = %d\n", mainName, d);
    }

    pixDestroy(&pixs);
    return 0;
}
Esempio n. 4
0
/*!
 *  pixGetWindowsHBITMAP()
 *
 *      Input:  pix
 *      Return: Windows hBitmap, or null on error
 *
 *  Notes:
 *      (1) It's the responsibility of the caller to destroy the
 *          returned hBitmap with a call to DeleteObject (or with
 *          something that eventually calls DeleteObject).
 */
HBITMAP
pixGetWindowsHBITMAP(PIX  *pix)
{
l_int32    width, height, depth;
l_uint32  *data;
HBITMAP    hBitmap = NULL;
BITMAP     bm;
DWORD      imageBitsSize;
PIX       *pixt = NULL;
PIXCMAP   *cmap;

    PROCNAME("pixGetWindowsHBITMAP");
    if (!pix)
        return (HBITMAP)ERROR_PTR("pix not defined", procName, NULL);

    pixGetDimensions(pix, &width, &height, &depth);
    cmap = pixGetColormap(pix);

    if (depth == 24) depth = 32;
    if (depth == 2) {
        pixt = pixConvert2To8(pix, 0, 85, 170, 255, TRUE);
        if (!pixt)
            return (HBITMAP)ERROR_PTR("unable to convert pix from 2bpp to 8bpp",
                    procName, NULL);
        depth = pixGetDepth(pixt);
        cmap = pixGetColormap(pixt);
    }

    if (depth < 16) {
        if (!cmap)
            cmap = pixcmapCreateLinear(depth, 1<<depth);
    }

    hBitmap = DSCreateDIBSection(width, height, depth, cmap);
    if (!hBitmap)
        return (HBITMAP)ERROR_PTR("Unable to create HBITMAP", procName, NULL);

        /* By default, Windows assumes bottom up images */
    if (pixt)
        pixt = pixFlipTB(pixt, pixt);
    else
        pixt = pixFlipTB(NULL, pix);

        /* "standard" color table assumes bit off=black */
    if (depth == 1) {
        pixInvert(pixt, pixt);
    }

        /* Don't byte swap until done manipulating pix! */
    if (depth <= 16)
        pixEndianByteSwap(pixt);

    GetObject (hBitmap, sizeof(BITMAP), &bm);
    imageBitsSize = ImageBitsSize(hBitmap);
    data = pixGetData(pixt);
    if (data) {
        memcpy (bm.bmBits, data, imageBitsSize);
    } else {
        DeleteObject (hBitmap);
        hBitmap = NULL;
    }
    pixDestroy(&pixt);

    return hBitmap;
}