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; }
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; }