Example #1
0
unsigned char *
simage_tiff_load(std::istream& fin,
                 int& width_ret,
                 int& height_ret,
                 int& numComponents_ret,
                 uint16& bitspersample)
{
    TIFF *in;
    uint16 dataType;
    uint16 samplesperpixel;
    uint16 photometric;
    uint32 w, h;
    uint16 config;
    uint16* red;
    uint16* green;
    uint16* blue;
    unsigned char *inbuf = NULL;
    tsize_t rowsize;
    uint32 row;
    int format;
    unsigned char *buffer;
    int width;
    int height;
    unsigned char *currPtr;

    TIFFSetErrorHandler(tiff_error);
    TIFFSetWarningHandler(tiff_warn);

    in = TIFFClientOpen("inputstream", "r", (thandle_t)&fin,
            libtiffStreamReadProc, //Custom read function
            libtiffStreamWriteProc, //Custom write function
            libtiffStreamSeekProc, //Custom seek function
            libtiffStreamCloseProc, //Custom close function
            libtiffStreamSizeProc, //Custom size function
            libtiffStreamMapProc, //Custom map function
            libtiffStreamUnmapProc); //Custom unmap function

    if (in == NULL)
    {
        tifferror = ERR_OPEN;
        return NULL;
    }
    if (TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric) == 1)
    {
        if (photometric != PHOTOMETRIC_RGB && photometric != PHOTOMETRIC_PALETTE &&
            photometric != PHOTOMETRIC_MINISWHITE &&
            photometric != PHOTOMETRIC_MINISBLACK)
        {
            OSG_NOTICE << "Photometric type "<<photometric<<" not handled; can only handle Grayscale, RGB and Palette images" << std::endl;
            TIFFClose(in);
            tifferror = ERR_UNSUPPORTED;
            return NULL;
        }
    }
    else
    {
        tifferror = ERR_READ;
        TIFFClose(in);
        return NULL;
    }

    if (TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel) == 1)
    {
        if (samplesperpixel != 1 &&
            samplesperpixel != 2 &&
            samplesperpixel != 3 &&
            samplesperpixel != 4)
        {
            OSG_DEBUG << "Bad samples/pixel" << std::endl;
            tifferror = ERR_UNSUPPORTED;
            TIFFClose(in);
            return NULL;
        }
    }
    else
    {
        tifferror = ERR_READ;
        TIFFClose(in);
        return NULL;
    }

    if (TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample) == 1)
    {
         if (bitspersample != 8 && bitspersample != 16 && bitspersample != 32)
        {
            OSG_NOTICE << "can only handle 8, 16 and 32 bit samples" << std::endl;
            TIFFClose(in);
            tifferror = ERR_UNSUPPORTED;
            return NULL;
        }
    }
    else
    {
        tifferror = ERR_READ;
        TIFFClose(in);
        return NULL;
    }

    if (TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w) != 1 ||
        TIFFGetField(in, TIFFTAG_IMAGELENGTH, &h) != 1 ||
        TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config) != 1)
    {
        TIFFClose(in);
        tifferror = ERR_READ;
        return NULL;
    }


    TIFFGetField(in, TIFFTAG_DATATYPE, &dataType);
    OSG_INFO<<"TIFFTAG_DATATYPE="<<dataType<<std::endl;


    /*
    if (photometric == PHOTOMETRIC_MINISWHITE ||
        photometric == PHOTOMETRIC_MINISBLACK)
        format = 1;
    else
        format = 3;
    */
    // if it has a palette, data returned is 3 byte rgb
    // so set format to 3.
    if (photometric == PHOTOMETRIC_PALETTE)
        format = 3;
    else
        format = samplesperpixel * bitspersample / 8;


    int bytespersample = bitspersample / 8;
    int bytesperpixel = bytespersample * samplesperpixel;

    OSG_INFO<<"format="<<format<<std::endl;
    OSG_INFO<<"bytespersample="<<bytespersample<<std::endl;
    OSG_INFO<<"bytesperpixel="<<bytesperpixel<<std::endl;

    buffer = new unsigned char [w*h*format];

    if (!buffer)
    {
        tifferror = ERR_MEM;
        TIFFClose(in);
        return NULL;
    }

    // initialize memory
    for(unsigned char* ptr=buffer;ptr<buffer+w*h*format;++ptr) *ptr = 0;

    width = w;
    height = h;

    currPtr = buffer + (h-1)*w*format;

    tifferror = ERR_NO_ERROR;

    switch (pack(photometric, config))
    {
        case pack(PHOTOMETRIC_MINISWHITE, PLANARCONFIG_CONTIG):
        case pack(PHOTOMETRIC_MINISBLACK, PLANARCONFIG_CONTIG):
        case pack(PHOTOMETRIC_MINISWHITE, PLANARCONFIG_SEPARATE):
        case pack(PHOTOMETRIC_MINISBLACK, PLANARCONFIG_SEPARATE):
            inbuf = new unsigned char [TIFFScanlineSize(in)];
            for (row = 0; row < h; row++)
            {
                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
                {
                    tifferror = ERR_READ;
                    break;
                }
                invert_row(currPtr, inbuf, samplesperpixel*w, photometric == PHOTOMETRIC_MINISWHITE, bitspersample);
                currPtr -= format*w;
            }
            break;

        case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_CONTIG):
        case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_SEPARATE):
            if (TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue) != 1)
                tifferror = ERR_READ;
            /* */
            /* Convert 16-bit colormap to 8-bit (unless it looks */
            /* like an old-style 8-bit colormap). */
            /* */
            if (!tifferror && checkcmap(1<<bitspersample, red, green, blue) == 16)
            {
                int i;
                for (i = (1<<bitspersample)-1; i >= 0; i--)
                {
                    red[i] = CVT(red[i]);
                    green[i] = CVT(green[i]);
                    blue[i] = CVT(blue[i]);
                }
            }

            inbuf = new unsigned char [TIFFScanlineSize(in)];
            for (row = 0; row < h; row++)
            {
                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
                {
                    tifferror = ERR_READ;
                    break;
                }
                remap_row(currPtr, inbuf, w, red, green, blue);
                currPtr -= format*w;
            }
            break;

        case pack(PHOTOMETRIC_RGB, PLANARCONFIG_CONTIG):
            inbuf = new unsigned char [TIFFScanlineSize(in)];
            for (row = 0; row < h; row++)
            {
                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
                {
                    tifferror = ERR_READ;
                    break;
                }
                memcpy(currPtr, inbuf, format*w);
                currPtr -= format*w;
            }
            break;

        case pack(PHOTOMETRIC_RGB, PLANARCONFIG_SEPARATE):
            rowsize = TIFFScanlineSize(in);
            inbuf = new unsigned char [format*rowsize];
            for (row = 0; !tifferror && row < h; row++)
            {
                int s;
                for (s = 0; s < format; s++)
                {
                    if (TIFFReadScanline(in, (tdata_t)(inbuf+s*rowsize), (uint32)row, (tsample_t)s) < 0)
                    {
                        tifferror = ERR_READ; break;
                    }
                }
                if (!tifferror)
                {
                    if (format==3) interleave_row(currPtr, inbuf, inbuf+rowsize, inbuf+2*rowsize, w, format, bitspersample);
                    else if (format==4) interleave_row(currPtr, inbuf, inbuf+rowsize, inbuf+2*rowsize, inbuf+3*rowsize, w, format, bitspersample);
                    currPtr -= format*w;
                }
            }
            break;
        default:
            tifferror = ERR_UNSUPPORTED;
            break;
    }

    if (inbuf) delete [] inbuf;
    TIFFClose(in);

    if (tifferror)
    {
        if (buffer) delete [] buffer;
        return NULL;
    }
    width_ret = width;
    height_ret = height;
    if (photometric == PHOTOMETRIC_PALETTE)
        numComponents_ret = format;
    else
        numComponents_ret = samplesperpixel;

    return buffer;
}
Example #2
0
int opendcp_decode_bmp(odcp_image_t **image_ptr, const char *infile) {
    bmp_magic_num_t magic;
    bmp_image_t     bmp;
    FILE            *bmp_fp;
    odcp_image_t    *image = 00;
    int             pixels = 0;
    int             i,w,h;
    size_t          readsize;

    /* open bmp using filename or file descriptor */
    dcp_log(LOG_DEBUG,"%-15.15s: opening bmp file %s","read_bmp",infile);

    bmp_fp = fopen(infile, "rb");

    if (!bmp_fp) {
        dcp_log(LOG_ERROR,"%-15.15s: opening bmp file %s","read_bmp",infile);
        return OPENDCP_FATAL;
    }

    readsize = fread(&magic, 1, sizeof(bmp_magic_num_t), bmp_fp);
    if (readsize != sizeof(bmp_magic_num_t)) {
        dcp_log(LOG_ERROR,"%-15.15s: failed to read magic number expected %d read %d","read_bmp", sizeof(bmp_magic_num_t), readsize);
    }

    readsize = fread(&bmp, 1, sizeof(bmp_image_t), bmp_fp);
    if (readsize != sizeof(bmp_image_t)) {
        dcp_log(LOG_ERROR,"%-15.15s: failed to header expected %d read %d","read_bmp", sizeof(bmp_image_t), readsize);
    }

    if (magic.magic_num != MAGIC_NUMBER) {
         dcp_log(LOG_ERROR,"%s is not a valid BMP file", infile);
    }

    if (bmp.image.height < 0) {
        bmp.row_order = BMP_TOP;
    } else {
        bmp.row_order = BMP_BOTTOM;
    }

    w = bmp.image.width;
    h = abs(bmp.image.height);
    pixels = w * h;

    print_bmp_header(&bmp);

    switch (bmp.image.compression) {
        case BMP_RGB:
            break;
        case BMP_RLE8:
        case BMP_RLE4:
        case BMP_BITFIELDS:
        case BMP_JPEG:
        case BMP_PNG:
        default:
            dcp_log(LOG_ERROR, "Unsupported image compression: %d", bmp.image.compression);
            return OPENDCP_FATAL;
            break;
    }

    /* apparently, some applications don't fill in the image size */
    if (bmp.image.image_size == 0) {
        dcp_log(LOG_WARN, "BMP missing file size field, will attempt to calculate");
        bmp.image.image_size = bmp.file.size - sizeof(bmp_magic_num_t) - sizeof(bmp_image_t);
    }

    if (bmp.image.bpp < 24 || bmp.image.bpp > 32) {
        dcp_log(LOG_ERROR, "%d-bit depth is not supported.",bmp.image.bpp);
        return OPENDCP_FATAL;
    }

    /* create the image */
    dcp_log(LOG_DEBUG,"%-15.15s: allocating odcp image","read_bmp");
    image = odcp_image_create(3, w, h);
    dcp_log(LOG_DEBUG,"%-15.15s: image allocated","read_bmp");

    int row_size = ((bmp.image.bpp * w + 31) / 32) * 4;
    dcp_log(LOG_DEBUG, "%-15,15s: row size %d data size %d", "read_bmp", row_size, sizeof(uint8_t));

    fseek(bmp_fp, bmp.file.offset, SEEK_SET);

    /* RGB(A) */
    if (bmp.image.compression == BMP_RGB) {
        /* 16-bits per pixel */
        if (bmp.image.bpp == 16 ) {
            uint8_t data[2];
            for (i=0; i<pixels; i++) {
                fread(&data,sizeof(data),1,bmp_fp);
                int p = invert_row(bmp, i);
                image->component[BMP_B].data[p] = data[0] << 2;
                image->component[BMP_G].data[p] = data[0] << 4;
                image->component[BMP_R].data[p] = data[1] << 2;
            }
        /* 24-bits per pixel */
        } else if (bmp.image.bpp == 24 ) {
            uint8_t data[3];
            for (i=0; i<pixels; i++) {
                fread(&data, sizeof(uint8_t), sizeof(data), bmp_fp);
                int p = invert_row(bmp, i);
                image->component[BMP_B].data[p] = data[0] << 4;
                image->component[BMP_G].data[p] = data[1] << 4;
                image->component[BMP_R].data[p] = data[2] << 4;;
            }
        /* 32-bits per pixel */
        } else if (bmp.image.bpp == 32 ) {
            uint8_t data[4];
            for (i=0; i<pixels; i++) {
                fread(&data, sizeof(uint8_t), sizeof(data), bmp_fp);
                int p = invert_row(bmp, i);
                image->component[BMP_B].data[p] = data[0] << 4;
                image->component[BMP_G].data[p] = data[1] << 4;
                image->component[BMP_R].data[p] = data[2] << 4;
            }
        }
    }
    /* RGB(A) */

    fclose(bmp_fp);

    dcp_log(LOG_DEBUG,"%-15.15s: BMP read complete","read_bmp");
    *image_ptr = image;

    return OPENDCP_NO_ERROR;
}