bool CxImageTIF::Decode(CxFile * hFile) { //Comment this line if you need more information on errors // TIFFSetErrorHandler(NULL); //<Patrick Hoffmann> //Open file and fill the TIFF structure // m_tif = TIFFOpen(imageFileName,"rb"); TIFF* m_tif = _TIFFOpenEx(hFile, "rb"); uint32 height=0; uint32 width=0; uint16 bitspersample=1; uint16 samplesperpixel=1; uint32 rowsperstrip=(uint32_t)-1; uint16 photometric=0; uint16 compression=1; uint16 orientation=ORIENTATION_TOPLEFT; //<vho> uint16 res_unit; //<Trifon> uint32 x, y; float resolution, offset; bool isRGB; uint8_t *bits; //pointer to source data uint8_t *bits2; //pointer to destination data cx_try { //check if it's a tiff file if (!m_tif) cx_throw("Error encountered while opening TIFF file"); // <Robert Abram> - 12/2002 : get NumFrames directly, instead of looping // info.nNumFrames=0; // while(TIFFSetDirectory(m_tif,(uint16)info.nNumFrames)) info.nNumFrames++; info.nNumFrames = TIFFNumberOfDirectories(m_tif); if (!TIFFSetDirectory(m_tif, (uint16)info.nFrame)) cx_throw("Error: page not present in TIFF file"); //get image info TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height); TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &photometric); TIFFGetField(m_tif, TIFFTAG_ORIENTATION, &orientation); if (info.nEscape == -1) { // Return output dimensions only head.biWidth = width; head.biHeight = height; info.dwType = CXIMAGE_FORMAT_TIF; cx_throw("output dimensions returned"); } TIFFGetFieldDefaulted(m_tif, TIFFTAG_RESOLUTIONUNIT, &res_unit); if (TIFFGetField(m_tif, TIFFTAG_XRESOLUTION, &resolution)) { if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f); SetXDPI((int32_t)resolution); } if (TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &resolution)) { if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f); SetYDPI((int32_t)resolution); } if (TIFFGetField(m_tif, TIFFTAG_XPOSITION, &offset)) info.xOffset = (int32_t)offset; if (TIFFGetField(m_tif, TIFFTAG_YPOSITION, &offset)) info.yOffset = (int32_t)offset; head.biClrUsed=0; info.nBkgndIndex =-1; if (rowsperstrip>height){ rowsperstrip=height; TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); } isRGB = /*(bitspersample >= 8) && (VK: it is possible so for RGB to have < 8 bpp!)*/ (photometric == PHOTOMETRIC_RGB) || (photometric == PHOTOMETRIC_YCBCR) || (photometric == PHOTOMETRIC_SEPARATED) || (photometric == PHOTOMETRIC_LOGL) || (photometric == PHOTOMETRIC_LOGLUV); if (isRGB){ head.biBitCount=24; }else{ if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE)||(photometric==PHOTOMETRIC_PALETTE)){ if (bitspersample == 1){ head.biBitCount=1; //B&W image head.biClrUsed =2; } else if (bitspersample == 4) { head.biBitCount=4; //16 colors gray scale head.biClrUsed =16; } else { head.biBitCount=8; //gray scale head.biClrUsed =256; } } else if (bitspersample == 4) { head.biBitCount=4; // 16 colors head.biClrUsed=16; } else { head.biBitCount=8; //256 colors head.biClrUsed=256; } if ((bitspersample > 8) && (photometric==PHOTOMETRIC_PALETTE)) // + VK + (BIG palette! => convert to RGB) { head.biBitCount=24; head.biClrUsed =0; } } if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding Create(width,height,head.biBitCount,CXIMAGE_FORMAT_TIF); //image creation if (!pDib) cx_throw("CxImageTIF can't create image"); #if CXIMAGE_SUPPORT_ALPHA if (samplesperpixel==4) AlphaCreate(); //add alpha support for 32bpp tiffs if (samplesperpixel==2 && bitspersample==8) AlphaCreate(); //add alpha support for 8bpp + alpha #endif //CXIMAGE_SUPPORT_ALPHA TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression); SetCodecOption(compression); // <DPR> save original compression type if (isRGB) { // Read the whole image into one big RGBA buffer using // the traditional TIFFReadRGBAImage() API that we trust. uint32* raster; // retrieve RGBA image uint32 *row; raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32)); if (raster == NULL) cx_throw("No space for raster buffer"); // Read the image in one chunk into an RGBA array if(!TIFFReadRGBAImage(m_tif, width, height, raster, 1)) { _TIFFfree(raster); cx_throw("Corrupted TIFF file!"); } // read the raster lines and save them in the DIB // with RGB mode, we have to change the order of the 3 samples RGB row = &raster[0]; bits2 = info.pImage; for (y = 0; y < height; y++) { if (info.nEscape){ // <vho> - cancel decoding _TIFFfree(raster); cx_throw("Cancelled"); } bits = bits2; for (x = 0; x < width; x++) { *bits++ = (uint8_t)TIFFGetB(row[x]); *bits++ = (uint8_t)TIFFGetG(row[x]); *bits++ = (uint8_t)TIFFGetR(row[x]); #if CXIMAGE_SUPPORT_ALPHA if (samplesperpixel==4) AlphaSet(x,y,(uint8_t)TIFFGetA(row[x])); #endif //CXIMAGE_SUPPORT_ALPHA } row += width; bits2 += info.dwEffWidth; } _TIFFfree(raster); } else { int32_t BIG_palette = (bitspersample > 8) && // + VK (photometric==PHOTOMETRIC_PALETTE); if (BIG_palette && (bitspersample > 24)) // + VK cx_throw("Too big palette to handle"); // + VK RGBQuad *pal; pal=(RGBQuad*)calloc(BIG_palette ? 1<<bitspersample : 256,sizeof(RGBQuad)); // ! VK: it coasts nothing but more correct to use 256 as temp palette storage // ! VK: but for case of BIG palette it just copied if (pal==NULL) cx_throw("Unable to allocate TIFF palette"); int32_t bpp = bitspersample <= 8 ? bitspersample : 8; // + VK (to use instead of bitspersample for case of > 8) // set up the colormap based on photometric switch(photometric) { case PHOTOMETRIC_MINISBLACK: // bitmap and greyscale image types case PHOTOMETRIC_MINISWHITE: if (bitspersample == 1) { // Monochrome image if (photometric == PHOTOMETRIC_MINISBLACK) { pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; } else { pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255; } } else { // need to build the scale for greyscale images if (photometric == PHOTOMETRIC_MINISBLACK) { for (int32_t i=0; i<(1<<bpp); i++){ pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (uint8_t)(i*(255/((1<<bpp)-1))); } } else { for (int32_t i=0; i<(1<<bpp); i++){ pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (uint8_t)(255-i*(255/((1<<bpp)-1))); } } } break; case PHOTOMETRIC_PALETTE: // color map indexed uint16 *red; uint16 *green; uint16 *blue; TIFFGetField(m_tif, TIFFTAG_COLORMAP, &red, &green, &blue); // Is the palette 16 or 8 bits ? bool Palette16Bits = /*false*/ BIG_palette; if (!BIG_palette) { int32_t n= 1<<bpp; while (n-- > 0) { if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256) { Palette16Bits=true; break; } } } // load the palette in the DIB for (int32_t i = (1 << ( BIG_palette ? bitspersample : bpp )) - 1; i >= 0; i--) { if (Palette16Bits) { pal[i].rgbRed =(uint8_t) CVT(red[i]); pal[i].rgbGreen = (uint8_t) CVT(green[i]); pal[i].rgbBlue = (uint8_t) CVT(blue[i]); } else { pal[i].rgbRed = (uint8_t) red[i]; pal[i].rgbGreen = (uint8_t) green[i]; pal[i].rgbBlue = (uint8_t) blue[i]; } } break; } if (!BIG_palette) { // + VK (BIG palette is stored until image is ready) SetPalette(pal,/*head.biClrUsed*/ 1<<bpp); //palette assign // * VK free(pal); pal = NULL; } // read the tiff lines and save them in the DIB uint32 nrow; uint32 ys; int32_t line = CalculateLine(width, bitspersample * samplesperpixel); int32_t bitsize = TIFFStripSize(m_tif); //verify bitsize: could be wrong if StripByteCounts is missing. if (bitsize>(int32_t)(head.biSizeImage*samplesperpixel)) bitsize = head.biSizeImage*samplesperpixel; if (bitsize<(int32_t)(info.dwEffWidth*rowsperstrip)) bitsize = info.dwEffWidth*rowsperstrip; if ((bitspersample > 8) && (bitspersample != 16)) // + VK (for bitspersample == 9..15,17..32..64 bitsize *= (bitspersample + 7)/8; int32_t tiled_image = TIFFIsTiled(m_tif); uint32 tw=0, tl=0; uint8_t* tilebuf=NULL; if (tiled_image){ TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &tw); TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &tl); rowsperstrip = tl; bitsize = TIFFTileSize(m_tif) * (int32_t)(1+width/tw); tilebuf = (uint8_t*)malloc(TIFFTileSize(m_tif)); } bits = (uint8_t*)malloc(bitspersample==16? bitsize*2 : bitsize); // * VK uint8_t * bits16 = NULL; // + VK int32_t line16 = 0; // + VK if (!tiled_image && bitspersample==16) { // + VK + line16 = line; line = CalculateLine(width, 8 * samplesperpixel); bits16 = bits; bits = (uint8_t*)malloc(bitsize); } if (bits==NULL){ if (bits16) free(bits16); // + VK if (pal) free(pal); // + VK if (tilebuf)free(tilebuf); // + VK cx_throw("CxImageTIF can't allocate memory"); } #ifdef FIX_16BPP_DARKIMG // + VK: for each line, store shift count bits used to fix it uint8_t* row_shifts = NULL; if (bits16) row_shifts = (uint8_t*)malloc(height); #endif for (ys = 0; ys < height; ys += rowsperstrip) { if (info.nEscape){ // <vho> - cancel decoding free(bits); cx_throw("Cancelled"); } nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip); if (tiled_image){ uint32 imagew = TIFFScanlineSize(m_tif); uint32 tilew = TIFFTileRowSize(m_tif); int32_t iskew = imagew - tilew; uint8* bufp = (uint8*) bits; uint32 colb = 0; for (uint32 col = 0; col < width; col += tw) { if (TIFFReadTile(m_tif, tilebuf, col, ys, 0, 0) < 0){ free(tilebuf); free(bits); cx_throw("Corrupted tiled TIFF file!"); } if (colb + tw > imagew) { uint32 owidth = imagew - colb; uint32 oskew = tilew - owidth; TileToStrip(bufp + colb, tilebuf, nrow, owidth, oskew + iskew, oskew ); } else { TileToStrip(bufp + colb, tilebuf, nrow, tilew, iskew, 0); } colb += tilew; } } else { if (TIFFReadEncodedStrip(m_tif, TIFFComputeStrip(m_tif, ys, 0), (bits16? bits16 : bits), nrow * (bits16 ? line16 : line)) == -1) { // * VK #ifdef NOT_IGNORE_CORRUPTED free(bits); if (bits16) free(bits16); // + VK cx_throw("Corrupted TIFF file!"); #else break; #endif } } for (y = 0; y < nrow; y++) { int32_t offset=(nrow-y-1)*line; if ((bitspersample==16) && !BIG_palette) { // * VK int32_t offset16 = (nrow-y-1)*line16; // + VK if (bits16) { // + VK + #ifdef FIX_16BPP_DARKIMG int32_t the_shift; uint8_t hi_byte, hi_max=0; uint32_t xi; for (xi=0;xi<(uint32)line;xi++) { hi_byte = bits16[xi*2+offset16+1]; if(hi_byte>hi_max) hi_max = hi_byte; } the_shift = (hi_max == 0) ? 8 : 0; if (!the_shift) while( ! (hi_max & 0x80) ) { the_shift++; hi_max <<= 1; } row_shifts[height-ys-nrow+y] = the_shift; the_shift = 8 - the_shift; for (xi=0;xi<(uint32)line;xi++) bits[xi+offset]= ((bits16[xi*2+offset16+1]<<8) | bits16[xi*2+offset16]) >> the_shift; #else for (uint32_t xi=0;xi<(uint32)line;xi++) bits[xi+offset]=bits16[xi*2+offset16+1]; #endif } else { for (uint32_t xi=0;xi<width;xi++) bits[xi+offset]=bits[xi*2+offset+1]; } } if (samplesperpixel==1) { if (BIG_palette) if (bits16) { int32_t offset16 = (nrow-y-1)*line16; // + VK MoveBitsPal( info.pImage + info.dwEffWidth * (height-ys-nrow+y), bits16 + offset16, width, bitspersample, pal ); } else MoveBitsPal( info.pImage + info.dwEffWidth * (height-ys-nrow+y), bits + offset, width, bitspersample, pal ); else if ((bitspersample == head.biBitCount) || (bitspersample == 16)) //simple 8bpp, 4bpp image or 16bpp memcpy(info.pImage+info.dwEffWidth*(height-ys-nrow+y),bits+offset,min((unsigned)line, info.dwEffWidth)); else MoveBits( info.pImage + info.dwEffWidth * (height-ys-nrow+y), bits + offset, width, bitspersample ); } else if (samplesperpixel==2) { //8bpp image with alpha layer int32_t xi=0; int32_t ii=0; int32_t yi=height-ys-nrow+y; #if CXIMAGE_SUPPORT_ALPHA if (!pAlpha) AlphaCreate(); // + VK #endif //CXIMAGE_SUPPORT_ALPHA while (ii<line){ SetPixelIndex(xi,yi,bits[ii+offset]); #if CXIMAGE_SUPPORT_ALPHA AlphaSet(xi,yi,bits[ii+offset+1]); #endif //CXIMAGE_SUPPORT_ALPHA ii+=2; xi++; if (xi>=(int32_t)width){ yi--; xi=0; } } } else { //photometric==PHOTOMETRIC_CIELAB if (head.biBitCount!=24){ //fix image Create(width,height,24,CXIMAGE_FORMAT_TIF); #if CXIMAGE_SUPPORT_ALPHA if (samplesperpixel==4) AlphaCreate(); #endif //CXIMAGE_SUPPORT_ALPHA } int32_t xi=0; uint32 ii=0; int32_t yi=height-ys-nrow+y; RGBQuad c; int32_t l,a,b,bitsoffset; double p,cx,cy,cz,cr,cg,cb; while (ii</*line*/width){ // * VK bitsoffset = ii*samplesperpixel+offset; l=bits[bitsoffset]; a=bits[bitsoffset+1]; b=bits[bitsoffset+2]; if (a>127) a-=256; if (b>127) b-=256; // lab to xyz p = (l/2.55 + 16) / 116.0; cx = pow( p + a * 0.002, 3); cy = pow( p, 3); cz = pow( p - b * 0.005, 3); // white point cx*=0.95047; //cy*=1.000; cz*=1.0883; // xyz to rgb cr = 3.240479 * cx - 1.537150 * cy - 0.498535 * cz; cg = -0.969256 * cx + 1.875992 * cy + 0.041556 * cz; cb = 0.055648 * cx - 0.204043 * cy + 1.057311 * cz; if ( cr > 0.00304 ) cr = 1.055 * pow(cr,0.41667) - 0.055; else cr = 12.92 * cr; if ( cg > 0.00304 ) cg = 1.055 * pow(cg,0.41667) - 0.055; else cg = 12.92 * cg; if ( cb > 0.00304 ) cb = 1.055 * pow(cb,0.41667) - 0.055; else cb = 12.92 * cb; c.rgbRed =(uint8_t)max(0,min(255,(int32_t)(cr*255))); c.rgbGreen=(uint8_t)max(0,min(255,(int32_t)(cg*255))); c.rgbBlue =(uint8_t)max(0,min(255,(int32_t)(cb*255))); SetPixelColor(xi,yi,c); #if CXIMAGE_SUPPORT_ALPHA if (samplesperpixel==4) AlphaSet(xi,yi,bits[bitsoffset+3]); #endif //CXIMAGE_SUPPORT_ALPHA ii++; xi++; if (xi>=(int32_t)width){ yi--; xi=0; } } } } } free(bits); if (bits16) free(bits16); #ifdef FIX_16BPP_DARKIMG if (row_shifts && (samplesperpixel == 1) && (bitspersample==16) && !BIG_palette) { // 1. calculate maximum necessary shift int32_t min_row_shift = 8; for( y=0; y<height; y++ ) { if (min_row_shift > row_shifts[y]) min_row_shift = row_shifts[y]; } // 2. for rows having less shift value, correct such rows: for( y=0; y<height; y++ ) { if (min_row_shift < row_shifts[y]) { int32_t need_shift = row_shifts[y] - min_row_shift; uint8_t* data = info.pImage + info.dwEffWidth * y; for( x=0; x<width; x++, data++ ) *data >>= need_shift; } }
bool CxImageRAW::Decode(CxFile *hFile) { return false; #if 0 if (hFile==NULL) return false; if (mutexInitialized == false) { #ifdef _LINUX pthread_mutex_init(&rawMutex, 0); #else rawMutex = ::CreateMutex(NULL, false, NULL); #endif mutexInitialized = true; } #ifdef _LINUX pthread_mutex_lock(&rawMutex); #else ::WaitForSingleObject(rawMutex, INFINITE); #endif DCRAW dcr; cx_try { // initialization dcr_init_dcraw(&dcr); dcr.opt.user_qual = GetCodecOption(CXIMAGE_FORMAT_RAW) & 0x03; // setup variables for debugging char szClass[] = "CxImageRAW"; dcr.ifname = szClass; dcr.sz_error = info.szLastError; // setup library options, see dcr_print_manual for the available switches // call dcr_parse_command_line_options(&dcr,0,0,0) to set default options // if (dcr_parse_command_line_options(&dcr,argc,argv,&arg)) if (dcr_parse_command_line_options(&dcr,0,0,0)){ cx_throw("CxImageRAW: unknown option"); } // set return point for error handling if (setjmp (dcr.failure)) { cx_throw(""); } // install file manager CxFileRaw src(hFile,&dcr); // check file header dcr_identify(&dcr); if(!dcr.is_raw){ cx_throw("CxImageRAW: not a raw image"); } if (dcr.load_raw == NULL) { cx_throw("CxImageRAW: missing raw decoder"); } // verify special case if (dcr.load_raw == dcr_kodak_ycbcr_load_raw) { dcr.height += dcr.height & 1; dcr.width += dcr.width & 1; } if (info.nEscape == -1){ head.biWidth = dcr.width; head.biHeight= dcr.height; info.dwType = CXIMAGE_FORMAT_RAW; cx_throw("output dimensions returned"); } // shrinked decoding available and requested? dcr.shrink = dcr.filters && (dcr.opt.half_size || dcr.opt.threshold || dcr.opt.aber[0] != 1 || dcr.opt.aber[2] != 1); dcr.iheight = (dcr.height + dcr.shrink) >> dcr.shrink; dcr.iwidth = (dcr.width + dcr.shrink) >> dcr.shrink; // install custom camera matrix if (dcr.opt.use_camera_matrix && dcr.cmatrix[0][0] > 0.25) { memcpy (dcr.rgb_cam, dcr.cmatrix, sizeof dcr.cmatrix); dcr.raw_color = 0; } else { dcr.opt.use_camera_wb = 1; } // allocate memory for the image dcr.image = (ushort (*)[4]) calloc (dcr.iheight*dcr.iwidth, sizeof *dcr.image); dcr_merror (&dcr, dcr.image, szClass); if (dcr.meta_length) { dcr.meta_data = (char *) malloc (dcr.meta_length); dcr_merror (&dcr, dcr.meta_data, szClass); } // start image decoder hFile->Seek(dcr.data_offset, SEEK_SET); (*dcr.load_raw)(&dcr); // post processing if (dcr.zero_is_bad) dcr_remove_zeroes(&dcr); dcr_bad_pixels(&dcr,NULL); if (dcr.opt.dark_frame) dcr_subtract (&dcr,dcr.opt.dark_frame); dcr.quality = 2 + !dcr.fuji_width; if (dcr.opt.user_qual >= 0) dcr.quality = dcr.opt.user_qual; if (dcr.opt.user_black >= 0) dcr.black = dcr.opt.user_black; #ifdef COLORCHECK dcr_colorcheck(&dcr); #endif #if RESTRICTED if (dcr.is_foveon && !dcr.opt.document_mode) dcr_foveon_interpolate(&dcr); #endif if (!dcr.is_foveon && dcr.opt.document_mode < 2) dcr_scale_colors(&dcr); // pixel interpolation and filters dcr_pre_interpolate(&dcr); if (dcr.filters && !dcr.opt.document_mode) { if (dcr.quality == 0) dcr_lin_interpolate(&dcr); else if (dcr.quality == 1 || dcr.colors > 3) dcr_vng_interpolate(&dcr); else if (dcr.quality == 2) dcr_ppg_interpolate(&dcr); else dcr_ahd_interpolate(&dcr); } if (dcr.mix_green) { long i; for (dcr.colors=3, i=0; i < dcr.height*dcr.width; i++) { dcr.image[i][1] = (dcr.image[i][1] + dcr.image[i][3]) >> 1; } } if (!dcr.is_foveon && dcr.colors == 3) dcr_median_filter(&dcr); if (!dcr.is_foveon && dcr.opt.highlight == 2) dcr_blend_highlights(&dcr); if (!dcr.is_foveon && dcr.opt.highlight > 2) dcr_recover_highlights(&dcr); if (dcr.opt.use_fuji_rotate) dcr_fuji_rotate(&dcr); #ifndef NO_LCMS if (dcr.opt.cam_profile) dcr_apply_profile (dcr.opt.cam_profile, dcr.opt.out_profile); #endif // final conversion dcr_convert_to_rgb(&dcr); if (dcr.opt.use_fuji_rotate) dcr_stretch(&dcr); dcr.iheight = dcr.height; dcr.iwidth = dcr.width; if (dcr.flip & 4) SWAP(dcr.height,dcr.width); // ready to transfer data from dcr.image if (!Create(dcr.width,dcr.height,24,CXIMAGE_FORMAT_RAW)){ cx_throw(""); } uchar *ppm = (uchar *) calloc (dcr.width, dcr.colors*dcr.opt.output_bps/8); ushort *ppm2 = (ushort *) ppm; dcr_merror (&dcr, ppm, szClass); uchar lut[0x10000]; if (dcr.opt.output_bps == 8) dcr_gamma_lut (&dcr, lut); long c, row, col, soff, rstep, cstep; soff = dcr_flip_index (&dcr, 0, 0); cstep = dcr_flip_index (&dcr, 0, 1) - soff; rstep = dcr_flip_index (&dcr, 1, 0) - dcr_flip_index (&dcr, 0, dcr.width); for (row=0; row < dcr.height; row++, soff += rstep) { for (col=0; col < dcr.width; col++, soff += cstep) { if (dcr.opt.output_bps == 8) for (c=0; c < dcr.colors; c++) ppm [col*dcr.colors+c] = lut[dcr.image[soff][c]]; else for (c=0; c < dcr.colors; c++) ppm2[col*dcr.colors+c] = dcr.image[soff][c]; } if (dcr.opt.output_bps == 16 && !dcr.opt.output_tiff && htons(0x55aa) != 0x55aa) #if defined(_LINUX) || defined(__APPLE__) swab ((char*)ppm2, (char*)ppm2, dcr.width*dcr.colors*2); #else _swab ((char*)ppm2, (char*)ppm2, dcr.width*dcr.colors*2); #endif DWORD size = dcr.width * (dcr.colors*dcr.opt.output_bps/8); RGBtoBGR(ppm,size); memcpy(GetBits(dcr.height - 1 - row), ppm, min(size,GetEffWidth())); } free (ppm); dcr_cleanup_dcraw(&dcr); #ifdef _LINUX pthread_mutex_unlock(&rawMutex); #else ::ReleaseMutex(rawMutex); #endif } cx_catch {
bool CxImagePCX::Decode(CxFile *hFile) { if (hFile == NULL) return false; PCXHEADER pcxHeader; int i, x, y, y2, nbytes, count, Height, Width; BYTE c, ColorMap[PCX_MAXCOLORS][3]; BYTE *pcximage = NULL, *lpHead1 = NULL, *lpHead2 = NULL; BYTE *pcxplanes, *pcxpixels; cx_try { if (hFile->Read(&pcxHeader,sizeof(PCXHEADER),1)==0) cx_throw("Can't read PCX image"); PCX_toh(&pcxHeader); if (pcxHeader.Manufacturer != PCX_MAGIC) cx_throw("Error: Not a PCX file"); // Check for PCX run length encoding if (pcxHeader.Encoding != 1) cx_throw("PCX file has unknown encoding scheme"); Width = (pcxHeader.Xmax - pcxHeader.Xmin) + 1; Height = (pcxHeader.Ymax - pcxHeader.Ymin) + 1; info.xDPI = pcxHeader.Hres; info.yDPI = pcxHeader.Vres; if (info.nEscape == -1){ head.biWidth = Width; head.biHeight= Height; info.dwType = CXIMAGE_FORMAT_PCX; return true; } // Check that we can handle this image format if (pcxHeader.ColorPlanes > 4) cx_throw("Can't handle image with more than 4 planes"); // Create the image if (pcxHeader.ColorPlanes >= 3 && pcxHeader.BitsPerPixel == 8){ Create (Width, Height, 24, CXIMAGE_FORMAT_PCX); #if CXIMAGE_SUPPORT_ALPHA if (pcxHeader.ColorPlanes==4) AlphaCreate(); #endif //CXIMAGE_SUPPORT_ALPHA } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 1) Create (Width, Height, 4, CXIMAGE_FORMAT_PCX); else Create (Width, Height, pcxHeader.BitsPerPixel, CXIMAGE_FORMAT_PCX); if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding //Read the image and check if it's ok nbytes = pcxHeader.BytesPerLine * pcxHeader.ColorPlanes * Height; lpHead1 = pcximage = (BYTE*)malloc(nbytes); while (nbytes > 0){ if (hFile == NULL || hFile->Eof()) cx_throw("corrupted PCX"); hFile->Read(&c,1,1); if ((c & 0XC0) != 0XC0){ // Repeated group *pcximage++ = c; --nbytes; continue; } count = c & 0X3F; // extract count hFile->Read(&c,1,1); if (count > nbytes) cx_throw("repeat count spans end of image"); nbytes -= count; while (--count >=0) *pcximage++ = c; } pcximage = lpHead1; //store the palette for (i = 0; i < 16; i++){ ColorMap[i][0] = pcxHeader.ColorMap[i][0]; ColorMap[i][1] = pcxHeader.ColorMap[i][1]; ColorMap[i][2] = pcxHeader.ColorMap[i][2]; } if (pcxHeader.BitsPerPixel == 8 && pcxHeader.ColorPlanes == 1){ hFile->Read(&c,1,1); if (c != PCX_256_COLORS) cx_throw("bad color map signature"); for (i = 0; i < PCX_MAXCOLORS; i++){ hFile->Read(&ColorMap[i][0],1,1); hFile->Read(&ColorMap[i][1],1,1); hFile->Read(&ColorMap[i][2],1,1); } } if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){ ColorMap[0][0] = ColorMap[0][1] = ColorMap[0][2] = 0; ColorMap[1][0] = ColorMap[1][1] = ColorMap[1][2] = 255; } for (DWORD idx=0; idx<head.biClrUsed; idx++) SetPaletteColor((BYTE)idx,ColorMap[idx][0],ColorMap[idx][1],ColorMap[idx][2]); lpHead2 = pcxpixels = (BYTE *)malloc(Width + pcxHeader.BytesPerLine * 8); // Convert the image for (y = 0; y < Height; y++){ if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding y2=Height-1-y; pcxpixels = lpHead2; pcxplanes = pcximage + (y * pcxHeader.BytesPerLine * pcxHeader.ColorPlanes); if (pcxHeader.ColorPlanes == 3 && pcxHeader.BitsPerPixel == 8){ // Deal with 24 bit color image for (x = 0; x < Width; x++){ SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x])); } continue; #if CXIMAGE_SUPPORT_ALPHA } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 8){ for (x = 0; x < Width; x++){ SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x])); AlphaSet(x,y2,pcxplanes[3*pcxHeader.BytesPerLine + x]); } continue; #endif //CXIMAGE_SUPPORT_ALPHA } else if (pcxHeader.ColorPlanes == 1) { if (!PCX_UnpackPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel)){ cx_throw("PCX_UnpackPixels: Can't handle packed pixels with more than 1 plane"); } } else { if (!PCX_PlanesToPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel)){ cx_throw("PCX_PlanesToPixels: more than 4 planes or more than 1 bit per pixel"); } } for (x = 0; x < Width; x++) SetPixelIndex(x,y2,pcxpixels[x]); } } cx_catch { if (strcmp(message,"")) strncpy(info.szLastError,message,255); if (lpHead1){ free(lpHead1); lpHead1 = NULL; } if (lpHead2){ free(lpHead2); lpHead2 = NULL; } return false; } if (lpHead1){ free(lpHead1); lpHead1 = NULL; } if (lpHead2){ free(lpHead2); lpHead2 = NULL; } return true; }
bool CxImagePCX::Encode(CxFile * hFile) { if (EncodeSafeCheck(hFile)) return false; cx_try { PCXHEADER pcxHeader; memset(&pcxHeader,0,sizeof(pcxHeader)); pcxHeader.Manufacturer = PCX_MAGIC; pcxHeader.Version = 5; pcxHeader.Encoding = 1; pcxHeader.Xmin = 0; pcxHeader.Ymin = 0; pcxHeader.Xmax = (WORD)head.biWidth-1; pcxHeader.Ymax = (WORD)head.biHeight-1; pcxHeader.Hres = (WORD)info.xDPI; pcxHeader.Vres = (WORD)info.yDPI; pcxHeader.Reserved = 0; pcxHeader.PaletteType = head.biClrUsed==0; switch(head.biBitCount){ case 24: case 8: { pcxHeader.BitsPerPixel = 8; pcxHeader.ColorPlanes = head.biClrUsed==0 ? 3 : 1; #if CXIMAGE_SUPPORT_ALPHA if (AlphaIsValid() && head.biClrUsed==0) pcxHeader.ColorPlanes =4; #endif //CXIMAGE_SUPPORT_ALPHA pcxHeader.BytesPerLine = (WORD)head.biWidth; break; } default: //(4 1) pcxHeader.BitsPerPixel = 1; pcxHeader.ColorPlanes = head.biClrUsed==16 ? 4 : 1; pcxHeader.BytesPerLine = (WORD)((head.biWidth * pcxHeader.BitsPerPixel + 7)>>3); } if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){ pcxHeader.ColorMap[0][0] = pcxHeader.ColorMap[0][1] = pcxHeader.ColorMap[0][2] = 0; pcxHeader.ColorMap[1][0] = pcxHeader.ColorMap[1][1] = pcxHeader.ColorMap[1][2] = 255; } if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 4){ RGBQUAD c; for (int i = 0; i < 16; i++){ c=GetPaletteColor(i); pcxHeader.ColorMap[i][0] = c.rgbRed; pcxHeader.ColorMap[i][1] = c.rgbGreen; pcxHeader.ColorMap[i][2] = c.rgbBlue; } } pcxHeader.BytesPerLine = (pcxHeader.BytesPerLine + 1)&(~1); PCX_toh(&pcxHeader); if (hFile->Write(&pcxHeader, sizeof(pcxHeader), 1) == 0 ) cx_throw("cannot write PCX header"); PCX_toh(&pcxHeader); CxMemFile buffer; buffer.Open(); BYTE c,n; long x,y; if (head.biClrUsed==0){ for (y = head.biHeight-1; y >=0 ; y--){ for (int p=0; p<pcxHeader.ColorPlanes; p++){ c=n=0; for (x = 0; x<head.biWidth; x++){ if (p==0) PCX_PackPixels(BlindGetPixelColor(x,y).rgbRed,c,n,buffer); else if (p==1) PCX_PackPixels(BlindGetPixelColor(x,y).rgbGreen,c,n,buffer); else if (p==2) PCX_PackPixels(BlindGetPixelColor(x,y).rgbBlue,c,n,buffer); #if CXIMAGE_SUPPORT_ALPHA else if (p==3) PCX_PackPixels(BlindAlphaGet(x,y),c,n,buffer); #endif //CXIMAGE_SUPPORT_ALPHA } PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer); } } hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1); } else if (head.biBitCount==8) { for (y = head.biHeight-1; y >=0 ; y--){ c=n=0; for (x = 0; x<head.biWidth; x++){ PCX_PackPixels(GetPixelIndex(x,y),c,n,buffer); } PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer); } hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1); if (head.biBitCount == 8){ hFile->PutC(0x0C); BYTE* pal = (BYTE*)malloc(768); RGBQUAD c; for (int i=0;i<256;i++){ c=GetPaletteColor(i); pal[3*i+0] = c.rgbRed; pal[3*i+1] = c.rgbGreen; pal[3*i+2] = c.rgbBlue; } hFile->Write(pal,768,1); free(pal); } } else { //(head.biBitCount==4) || (head.biBitCount==1) RGBQUAD *rgb = GetPalette(); bool binvert = false; if (CompareColors(&rgb[0],&rgb[1])>0) binvert=(head.biBitCount==1); BYTE* plane = (BYTE*)malloc(pcxHeader.BytesPerLine); BYTE* raw = (BYTE*)malloc(head.biWidth); for(y = head.biHeight-1; y >=0 ; y--) { for( x = 0; x < head.biWidth; x++) raw[x] = (BYTE)GetPixelIndex(x,y); if (binvert) for( x = 0; x < head.biWidth; x++) raw[x] = 1-raw[x]; for( x = 0; x < pcxHeader.ColorPlanes; x++ ) { PCX_PixelsToPlanes(raw, head.biWidth, plane, x); PCX_PackPlanes(plane, pcxHeader.BytesPerLine, buffer); } } free(plane); free(raw); hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1); } } cx_catch { if (strcmp(message,"")) strncpy(info.szLastError,message,255); return false; } return true; }
int32_t CxMapFile::Scanf(const char *format, void* output) { cx_throw("Not Impl"); //if (!m_fp) return EOF; //return fscanf(m_fp, format, output); }
bool CxImageJAS::Decode(CxFile *hFile, uint32_t imagetype) { if (hFile == NULL) return false; jas_image_t *image=0; jas_stream_t *in=0; jas_matrix_t **bufs=0; int32_t i,error=0; int32_t fmt; //jas_setdbglevel(0); cx_try { if (jas_init()) cx_throw("cannot initialize jasper"); in = jas_stream_fdopen(0, "rb"); if (!in) cx_throw("error: cannot open standard input"); CxFileJas src(hFile,in); fmt = jas_image_getfmt(in); if (fmt<0) cx_throw("error: unknowm format"); image = jas_image_decode(in, fmt, 0); if (!image){ fmt = -1; cx_throw("error: cannot load image data"); } char szfmt[4]; *szfmt = '\0'; strncpy(szfmt,jas_image_fmttostr(fmt),3); szfmt[3] = '\0'; fmt = -1; #if CXIMAGE_SUPPORT_JP2 if (strcmp(szfmt,"jp2")==0) fmt = CXIMAGE_FORMAT_JP2; #endif #if CXIMAGE_SUPPORT_JPC if (strcmp(szfmt,"jpc")==0) fmt = CXIMAGE_FORMAT_JPC; #endif #if CXIMAGE_SUPPORT_RAS if (strcmp(szfmt,"ras")==0) fmt = CXIMAGE_FORMAT_RAS; #endif #if CXIMAGE_SUPPORT_PNM if (strcmp(szfmt,"pnm")==0) fmt = CXIMAGE_FORMAT_PNM; #endif #if CXIMAGE_SUPPORT_PGX if (strcmp(szfmt,"pgx")==0) fmt = CXIMAGE_FORMAT_PGX; #endif //if (fmt<0) // cx_throw("error: unknowm format"); int32_t x,y,w,h,depth,cmptno; w = jas_image_cmptwidth(image,0); h = jas_image_cmptheight(image,0); depth = jas_image_cmptprec(image,0); if (info.nEscape == -1){ head.biWidth = w; head.biHeight= h; info.dwType = fmt<0 ? 0 : fmt; cx_throw("output dimensions returned"); } if (image->numcmpts_ > 64 || image->numcmpts_ < 0) cx_throw("error: too many components"); // <LD> 01/Jan/2005: Always force conversion to sRGB. Seems to be required for many types of JPEG2000 file. // if (depth!=1 && depth!=4 && depth!=8) if (image->numcmpts_>=3 && depth <=8) { jas_image_t *newimage; jas_cmprof_t *outprof; //jas_eprintf("forcing conversion to sRGB\n"); outprof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB); if (!outprof) { cx_throw("cannot create sRGB profile"); } newimage = jas_image_chclrspc(image, outprof, JAS_CMXFORM_INTENT_PER); if (!newimage) { jas_cmprof_destroy(outprof); // <LD> 01/Jan/2005: Destroy color profile on error. cx_throw("cannot convert to sRGB"); } jas_image_destroy(image); jas_cmprof_destroy(outprof); image = newimage; } bufs = (jas_matrix_t **)calloc(image->numcmpts_, sizeof(jas_matrix_t**)); for (i = 0; i < image->numcmpts_; ++i) { bufs[i] = jas_matrix_create(1, w); if (!bufs[i]) { cx_throw("error: cannot allocate memory"); } } int32_t nshift = (depth>8) ? (depth-8) : 0; if (image->numcmpts_==3 && image->cmpts_[0]->width_ == image->cmpts_[1]->width_ && image->cmpts_[1]->width_ == image->cmpts_[2]->width_ && image->cmpts_[0]->height_ == image->cmpts_[1]->height_ && image->cmpts_[1]->height_ == image->cmpts_[2]->height_ && image->cmpts_[0]->prec_ == image->cmpts_[1]->prec_ && image->cmpts_[1]->prec_ == image->cmpts_[2]->prec_ ) { if(!Create(w,h,24,fmt)) cx_throw(""); RGBQUAD c; for (y=0; y<h; y++) { for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) { jas_image_readcmpt(image, cmptno, 0, y, w, 1, bufs[cmptno]); } for (x=0; x<w; x++){ c.rgbRed = (uint8_t)((jas_matrix_getv(bufs[0], x)>>nshift)); c.rgbGreen = (uint8_t)((jas_matrix_getv(bufs[1], x)>>nshift)); c.rgbBlue = (uint8_t)((jas_matrix_getv(bufs[2], x)>>nshift)); SetPixelColor(x,h-1-y,c); } } } else { info.nNumFrames = image->numcmpts_; if ((info.nFrame<0)||(info.nFrame>=info.nNumFrames)){ cx_throw("wrong frame!"); } for (cmptno=0; cmptno<=info.nFrame; cmptno++) { w = jas_image_cmptwidth(image,cmptno); h = jas_image_cmptheight(image,cmptno); depth = jas_image_cmptprec(image,cmptno); if (depth>8) depth=8; if(!Create(w,h,depth,imagetype)) cx_throw(""); SetGrayPalette(); for (y=0; y<h; y++) { jas_image_readcmpt(image, cmptno, 0, y, w, 1, bufs[0]); for (x=0; x<w; x++){ SetPixelIndex(x,h-1-y,(uint8_t)((jas_matrix_getv(bufs[0], x)>>nshift))); } } } } } cx_catch {
bool CxImageTIF::Decode(CxFile * hFile) { //Comment this line if you need more information on errors TIFFSetErrorHandler(NULL); //Open file and fill the TIFF structure // m_tif = TIFFOpen(imageFileName,"rb"); TIFF* m_tif = _TIFFOpenEx(hFile, "rb"); uint32 height=0; uint32 width=0; uint16 bitspersample=1; uint16 samplesperpixel=1; uint32 rowsperstrip=(DWORD)-1; uint16 photometric=0; uint16 compression=1; uint16 orientation=ORIENTATION_TOPLEFT; //<vho> uint16 res_unit; //<Trifon> uint32 x, y; float resolution, offset; BOOL isRGB; BYTE *bits; //pointer to source data BYTE *bits2; //pointer to destination data cx_try { //check if it's a tiff file if (!m_tif) cx_throw("Error encountered while opening TIFF file"); // <Robert Abram> - 12/2002 : get NumFrames directly, instead of looping // info.nNumFrames=0; // while(TIFFSetDirectory(m_tif,(uint16)info.nNumFrames)) info.nNumFrames++; info.nNumFrames = TIFFNumberOfDirectories(m_tif); if (!TIFFSetDirectory(m_tif, (uint16)info.nFrame)) cx_throw("Error: page not present in TIFF file"); //get image info TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height); TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &photometric); TIFFGetField(m_tif, TIFFTAG_ORIENTATION, &orientation); if (info.nEscape == -1) { // Return output dimensions only head.biWidth = width; head.biHeight = height; info.dwType = CXIMAGE_FORMAT_TIF; cx_throw("output dimensions returned"); } TIFFGetFieldDefaulted(m_tif, TIFFTAG_RESOLUTIONUNIT, &res_unit); if (TIFFGetField(m_tif, TIFFTAG_XRESOLUTION, &resolution)) { if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f); SetXDPI((long)resolution); } if (TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &resolution)) { if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f); SetYDPI((long)resolution); } if (TIFFGetField(m_tif, TIFFTAG_XPOSITION, &offset)) info.xOffset = (long)offset; if (TIFFGetField(m_tif, TIFFTAG_YPOSITION, &offset)) info.yOffset = (long)offset; head.biClrUsed=0; info.nBkgndIndex =-1; if (rowsperstrip>height){ rowsperstrip=height; TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); } isRGB = /*(bitspersample >= 8) && (VK: it is possible so for RGB to have < 8 bpp!)*/ (photometric == PHOTOMETRIC_RGB) || (photometric == PHOTOMETRIC_YCBCR) || (photometric == PHOTOMETRIC_SEPARATED) || (photometric == PHOTOMETRIC_LOGL) || (photometric == PHOTOMETRIC_LOGLUV); if (isRGB){ head.biBitCount=24; }else{ if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE)||(photometric==PHOTOMETRIC_PALETTE)){ if (bitspersample == 1){ head.biBitCount=1; //B&W image head.biClrUsed =2; } else if (bitspersample == 4) { head.biBitCount=4; //16 colors gray scale head.biClrUsed =16; } else { head.biBitCount=8; //gray scale head.biClrUsed =256; } } else if (bitspersample == 4) { head.biBitCount=4; // 16 colors head.biClrUsed=16; } else { head.biBitCount=8; //256 colors head.biClrUsed=256; } if ((bitspersample > 8) && (photometric==PHOTOMETRIC_PALETTE)) // + VK + (BIG palette! => convert to RGB) { head.biBitCount=24; head.biClrUsed =0; } } if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding Create(width,height,head.biBitCount,CXIMAGE_FORMAT_TIF); //image creation if (!pDib) cx_throw("CxImageTIF can't create image"); #if CXIMAGE_SUPPORT_ALPHA if (samplesperpixel==4) AlphaCreate(); //add alpha support for 32bpp tiffs if (samplesperpixel==2 && bitspersample==8) AlphaCreate(); //add alpha support for 8bpp + alpha #endif //CXIMAGE_SUPPORT_ALPHA TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression); SetCodecOption(compression); // <DPR> save original compression type if (isRGB) { // Read the whole image into one big RGBA buffer using // the traditional TIFFReadRGBAImage() API that we trust. uint32* raster; // retrieve RGBA image uint32 *row; raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32)); if (raster == NULL) cx_throw("No space for raster buffer"); // Read the image in one chunk into an RGBA array if(!TIFFReadRGBAImage(m_tif, width, height, raster, 1)) { _TIFFfree(raster); cx_throw("Corrupted TIFF file!"); } // read the raster lines and save them in the DIB // with RGB mode, we have to change the order of the 3 samples RGB row = &raster[0]; bits2 = info.pImage; for (y = 0; y < height; y++) { if (info.nEscape){ // <vho> - cancel decoding _TIFFfree(raster); cx_throw("Cancelled"); } bits = bits2; for (x = 0; x < width; x++) { *bits++ = (BYTE)TIFFGetB(row[x]); *bits++ = (BYTE)TIFFGetG(row[x]); *bits++ = (BYTE)TIFFGetR(row[x]); #if CXIMAGE_SUPPORT_ALPHA if (samplesperpixel==4) AlphaSet(x,y,(BYTE)TIFFGetA(row[x])); #endif //CXIMAGE_SUPPORT_ALPHA } row += width; bits2 += info.dwEffWidth; } _TIFFfree(raster); } else { int BIG_palette = (bitspersample > 8) && // + VK (photometric==PHOTOMETRIC_PALETTE); if (BIG_palette && (bitspersample > 24)) // + VK cx_throw("Too big palette to handle"); // + VK RGBQUAD *pal; pal=(RGBQUAD*)calloc(BIG_palette ? 1<<bitspersample : 256,sizeof(RGBQUAD)); // ! VK: it coasts nothing but more correct to use 256 as temp palette storage // ! VK: but for case of BIG palette it just copied if (pal==NULL) cx_throw("Unable to allocate TIFF palette"); int bpp = bitspersample <= 8 ? bitspersample : 8; // + VK (to use instead of bitspersample for case of > 8) // set up the colormap based on photometric switch(photometric) { case PHOTOMETRIC_MINISBLACK: // bitmap and greyscale image types case PHOTOMETRIC_MINISWHITE: if (bitspersample == 1) { // Monochrome image if (photometric == PHOTOMETRIC_MINISBLACK) { pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; } else { pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255; } } else { // need to build the scale for greyscale images if (photometric == PHOTOMETRIC_MINISBLACK) { for (int i=0; i<(1<<bpp); i++){ pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(i*(255/((1<<bpp)-1))); } } else { for (int i=0; i<(1<<bpp); i++){ pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(255-i*(255/((1<<bpp)-1))); } } } break; case PHOTOMETRIC_PALETTE: // color map indexed uint16 *red; uint16 *green; uint16 *blue; TIFFGetField(m_tif, TIFFTAG_COLORMAP, &red, &green, &blue); // Is the palette 16 or 8 bits ? BOOL Palette16Bits = /*FALSE*/ BIG_palette; if (!BIG_palette) { int n= 1<<bpp; while (n-- > 0) { if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256) { Palette16Bits=TRUE; break; } } } // load the palette in the DIB for (int i = (1 << ( BIG_palette ? bitspersample : bpp )) - 1; i >= 0; i--) { if (Palette16Bits) {