Sayfayı Yazdır | Pencereyi Kapat

leptonica read bmp with use pixReadMem function

Nereden Yazdırıldığı: Datakent
Kategori: Diğer bölümler
Forum Adı: C, C++, Visual C++
Forum Tanımlaması: C, C++, Visual C++ Örnekleri
URL: http://forum.datakent.com/forum_posts.asp?TID=2465
Tarih: 28.Mart.2024 Saat 13:30


Konu: leptonica read bmp with use pixReadMem function
Mesajı Yazan: aziz.alkurt
Konu: leptonica read bmp with use pixReadMem function
Mesaj Tarihi: 09.Aralik.2012 Saat 12:35
leptonica - bmpio.c
//----------------------------------------------------------------------------------------------------------------------
PIX *
pixReadMemBmp(const l_uint8  *cdata,
              size_t          size)
{
    int hacked;
    l_uint16   sval;
    l_uint32   ival;
    l_int16    bfType, bfSize, bfFill1, bfReserved1, bfReserved2;
    l_int16    offset, bfFill2, biPlanes, depth, d;
    l_int32    biSize, width, height, xres, yres, compression, ignore;
    l_int32    imagebytes, biClrUsed, biClrImportant;
    l_uint8   *colormapBuf;
    l_int32    colormapEntries;
    l_int32    fileBpl, extrabytes, readerror;
    l_int32    pixWpl, pixBpl;
    l_int32    i, j, k;
    l_uint8    pel[4];
    l_uint8   *data;
    l_uint32  *line, *pword;
    PIX        *pix, *pixt;
    PIXCMAP   *cmap;
    PROCNAME("pixReadMemBmp");
   
        /* Read bitmap file header */
    memcpy((char *)&sval,(char *)cdata,2);
    bfType = convertOnBigEnd16(sval);
    if (bfType != BMP_ID)
        return (PIX *)ERROR_PTR("not bmf format", procName, NULL);

    memcpy((char *)&sval,(char *)cdata+2,2);
    bfSize = convertOnBigEnd16(sval);
    memcpy((char *)&sval,(char *)cdata+4,2);
    bfFill1 = convertOnBigEnd16(sval);
    memcpy((char *)&sval,(char *)cdata+6,2);
    bfReserved1 = convertOnBigEnd16(sval);
    memcpy((char *)&sval,(char *)cdata+8,2);
    bfReserved2 = convertOnBigEnd16(sval);
    memcpy((char *)&sval,(char *)cdata+10,2);
    offset = convertOnBigEnd16(sval);
    memcpy((char *)&sval,(char *)cdata+12,2);
    bfFill2 = convertOnBigEnd16(sval);

        /* Read bitmap info header */
    memcpy((char *)&ival,(char *)cdata+14,4);
    biSize = convertOnBigEnd32(ival);
    memcpy((char *)&ival,(char *)cdata+18,4);
    width = convertOnBigEnd32(ival);
    memcpy((char *)&ival,(char *)cdata+22,4);
    height = convertOnBigEnd32(ival);
    memcpy((char *)&sval,(char *)cdata+26,2);
    biPlanes = convertOnBigEnd16(sval);
    memcpy((char *)&sval,(char *)cdata+28,2);
    depth = convertOnBigEnd16(sval);
    memcpy((char *)&ival,(char *)cdata+30,4);
    compression = convertOnBigEnd32(ival);
    memcpy((char *)&ival,(char *)cdata+34,4);
    imagebytes = convertOnBigEnd32(ival);
    memcpy((char *)&ival,(char *)cdata+38,4);
    xres = convertOnBigEnd32(ival);
    memcpy((char *)&ival,(char *)cdata+42,4);
    yres = convertOnBigEnd32(ival);
    memcpy((char *)&ival,(char *)cdata+46,4);
    biClrUsed = convertOnBigEnd32(ival);
    memcpy((char *)&ival,(char *)cdata+50,4);
    biClrImportant = convertOnBigEnd32(ival);

    if (compression != 0)
        return (PIX *)ERROR_PTR("cannot read compressed BMP files",
                                procName,NULL);

        /* A little sanity checking.  It would be nice to check
            * if the number of bytes in the file equals the offset to
            * the data plus the imagedata, but this won't work when
            * reading from memory, because fmemopen() doesn't implement
            * ftell().  So we can't do that check.  The imagebytes for
            * uncompressed images is either 0 or the size of the file data.
            * (The fact that it can be 0 is perhaps some legacy glitch).  */
    if (width < 1)
        return (PIX *)ERROR_PTR("width < 1", procName,NULL);
    if (height < 1)
        return (PIX *)ERROR_PTR("height < 1", procName,NULL);
    if (depth < 1 || depth > 32)
        return (PIX *)ERROR_PTR("depth not in [1 ... 32]", procName,NULL);
    fileBpl = 4 * ((width * depth + 31)/32);
    if (imagebytes != 0 && imagebytes != fileBpl * height)
        return (PIX *)ERROR_PTR("invalid imagebytes", procName,NULL);
    if (offset < BMP_FHBYTES + BMP_IHBYTES)
        return (PIX *)ERROR_PTR("invalid offset: too small", procName,NULL);
    if (offset > BMP_FHBYTES + BMP_IHBYTES + 4 * 256)
        return (PIX *)ERROR_PTR("invalid offset: too large", procName,NULL);

        /* Handle the colormap */
    colormapEntries = (offset - BMP_FHBYTES - BMP_IHBYTES) / sizeof(RGBA_QUAD);
    if (colormapEntries > 0) {
        if ((colormapBuf = (l_uint8 *)CALLOC(colormapEntries,
                                                sizeof(RGBA_QUAD))) == NULL)
            return (PIX *)ERROR_PTR("colormapBuf alloc fail", procName, NULL );

            /* Read colormap */
        if (54+colormapEntries>size)
        {
            FREE(colormapBuf);
            return (PIX *)ERROR_PTR( "colormap read fail", procName, NULL);
        }
        memcpy(colormapBuf,(char *)cdata+54,colormapEntries);


    }

        /* Make a 32 bpp pix if depth is 24 bpp */
    d = depth;
    if (depth == 24)
        d = 32;
    if ((pix = pixCreate(width, height, d)) == NULL)
        return (PIX *)ERROR_PTR( "pix not made", procName, NULL);
    pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));  /* to ppi */
    pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));  /* to ppi */
    pixWpl = pixGetWpl(pix);
    pixBpl = 4 * pixWpl;

    cmap = NULL;
    if (colormapEntries > 256)
        L_WARNING("more than 256 colormap entries!", procName);
    if (colormapEntries > 0) {  /* import the colormap to the pix cmap */
        cmap = pixcmapCreate(L_MIN(d, 8));
        FREE(cmap->array);  /* remove generated cmap array */
        cmap->array  = (void *)colormapBuf;  /* and replace */
        cmap->n = L_MIN(colormapEntries, 256);
    }
    pixSetColormap(pix, cmap);

        /* Seek to the start of the bitmap in the file */
    /*fseek(fp, offset, 0);*/
    hacked=offset;
    if (depth != 24) {  /* typ. 1 or 8 bpp */
        data = (l_uint8 *)pixGetData(pix) + pixBpl * (height - 1);
        for (i = 0; i < height; i++)
        {
            if (hacked+fileBpl>size)
            {
                pixDestroy(&pix);
                return (PIX *)ERROR_PTR("BMP read fail", procName, NULL);
            }
            else
            {
                 //fread(data, 1, fileBpl, fp) != fileBpl
                memcpy(data,(char *)cdata+hacked,fileBpl);
                hacked+=fileBpl;
            }
            data -= pixBpl;
        }
    }
    else {  /*  24 bpp file; 32 bpp pix
                *  Note: for bmp files, pel[0] is blue, pel[1] is green,
                *  and pel[2] is red.  This is opposite to the storage
                *  in the pix, which puts the red pixel in the 0 byte,
                *  the green in the 1 byte and the blue in the 2 byte.
                *  Note also that all words are endian flipped after
                *  assignment on L_LITTLE_ENDIAN platforms.
                *
                *  We can then make these assignments for little endians:
                *      SET_DATA_BYTE(pword, 1, pel[0]);      blue
                *      SET_DATA_BYTE(pword, 2, pel[1]);      green
                *      SET_DATA_BYTE(pword, 3, pel[2]);      red
                *  This looks like:
                *          3  (R)     2  (G)        1  (B)        0
                *      |-----------|------------|-----------|-----------|
                *  and after byte flipping:
                *           3          2  (B)     1  (G)        0  (R)
                *      |-----------|------------|-----------|-----------|
                *
                *  For big endians we set:
                *      SET_DATA_BYTE(pword, 2, pel[0]);      blue
                *      SET_DATA_BYTE(pword, 1, pel[1]);      green
                *      SET_DATA_BYTE(pword, 0, pel[2]);      red
                *  This looks like:
                *          0  (R)     1  (G)        2  (B)        3
                *      |-----------|------------|-----------|-----------|
                *  so in both cases we get the correct assignment in the PIX.
                *
                *  Can we do a platform-independent assignment?
                *  Yes, set the bytes without using macros:
                *      *((l_uint8 *)pword) = pel[2];           red
                *      *((l_uint8 *)pword + 1) = pel[1];       green
                *      *((l_uint8 *)pword + 2) = pel[0];       blue
                *  For little endians, before flipping, this looks again like:
                *          3  (R)     2  (G)        1  (B)        0
                *      |-----------|------------|-----------|-----------|
                */
        readerror = 0;
        extrabytes = fileBpl - 3 * width;
        line = pixGetData(pix) + pixWpl * (height - 1);
        for (i = 0; i < height; i++)
        {
            for (j = 0; j < width; j++)
            {
                pword = line + j;
                /*if (fread(&pel, 1, 3, fp) != 3)
                    readerror = 1;*/
                if(hacked+3>size)
                    readerror=1;
                memcpy(&pel,(char *)cdata+hacked,3);
                hacked+=3;
                *((l_uint8 *)pword + COLOR_RED) = pel[2];
                *((l_uint8 *)pword + COLOR_GREEN) = pel[1];
                *((l_uint8 *)pword + COLOR_BLUE) = pel[0];
            }
            hacked+=extrabytes;
            line -= pixWpl;
        }
        if (readerror) {
            pixDestroy(&pix);
            return (PIX *)ERROR_PTR("BMP read fail", procName, NULL);
        }
    }

    pixEndianByteSwap(pix);

        /* ----------------------------------------------
            * The bmp colormap determines the values of black
            * and white pixels for binary in the following way:
            * if black = 1 (255), white = 0
            *      255, 255, 255, 0, 0, 0, 0, 0
            * if black = 0, white = 1 (255)
            *      0, 0, 0, 0, 255, 255, 255, 0
            * We have no need for a 1 bpp pix with a colormap!
            * ---------------------------------------------- */
    if (depth == 1 && cmap) {
/*        L_INFO("Removing colormap", procName); */
        pixt = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC);
        pixDestroy(&pix);
        pix = pixt;  /* rename */
    }

    return pix;
}
// --------------------------------------------------------------------------------------------------------------------

TEST
//----------------------------------------------------------------------------------------------------------------------
    unsigned char* dstTmp = NULL;
    FILE *file;
    file =fopen("d:/testx.bmp","rb");
    fseek (file , 0 , SEEK_END);
    size_t length=ftell (file);
    rewind (file);
    dstTmp = (unsigned char*) malloc (sizeof(unsigned char)*length);
    fread (dstTmp,1,length,file);
    fclose(file);

    Pix *pix = pixReadMem(dstTmp,length);
//----------------------------------------------------------------------------------------------------------------------





Sayfayı Yazdır | Pencereyi Kapat