예제 #1
0
int ReadTIFF(const char* const filename,
             WebPPicture* const pic, int keep_alpha,
             Metadata* const metadata) {
  TIFF* const tif = TIFFOpen(filename, "r");
  uint32 width, height;
  uint32* raster;
  int ok = 0;
  tdir_t dircount;

  if (tif == NULL) {
    fprintf(stderr, "Error! Cannot open TIFF file '%s'\n", filename);
    return 0;
  }

  dircount = TIFFNumberOfDirectories(tif);
  if (dircount > 1) {
    fprintf(stderr, "Warning: multi-directory TIFF files are not supported.\n"
                    "Only the first will be used, %d will be ignored.\n",
                    dircount - 1);
  }

  if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) &&
        TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))) {
    fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n");
    return 0;
  }
  raster = (uint32*)_TIFFmalloc(width * height * sizeof(*raster));
  if (raster != NULL) {
    if (TIFFReadRGBAImageOriented(tif, width, height, raster,
                                  ORIENTATION_TOPLEFT, 1)) {
      const int stride = width * sizeof(*raster);
      pic->width = width;
      pic->height = height;
      // TIFF data is ABGR
#ifdef WORDS_BIGENDIAN
      TIFFSwabArrayOfLong(raster, width * height);
#endif
      ok = keep_alpha
         ? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride)
         : WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride);
    }
    _TIFFfree(raster);
  } else {
    fprintf(stderr, "Error allocating TIFF RGBA memory!\n");
  }

  if (ok) {
    if (metadata != NULL) {
      ok = ExtractMetadataFromTIFF(tif, metadata);
      if (!ok) {
        fprintf(stderr, "Error extracting TIFF metadata!\n");
        MetadataFree(metadata);
        WebPPictureFree(pic);
      }
    }
  }

  TIFFClose(tif);
  return ok;
}
예제 #2
0
int GetTiffPages(const char *pFileName)
{
#ifndef WITH_TIFF
  return NOT_IMPLEMENTED;
#else 
  if (!pFileName)
    return BAD_ARGS;

  TIFFSetErrorHandler(NULL);
  TIFFSetWarningHandler(NULL);

  scoped_tiff_handle pTIF(TIFFOpen(pFileName, "r"));
  if (!pTIF)
    return FILE_ERROR;
  const int nPages = TIFFNumberOfDirectories(pTIF);
  if (nPages < 0)
    return INTERNAL_ERROR;
  return nPages;
#endif // WITH_TIFF
}
예제 #3
0
	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;
					}
				}
예제 #4
0
bool CaViewerScanner::registerMasterImage(QString sPath, QString sFileName)
{
    QString sFullName = sPath + sFileName;
    QString sHash = getHash(sFullName);
    if(sHash.isEmpty())  //  couldn't get hash
        return false;

    if(m_slHash.contains(sHash))
        return false;

    if(sFileName.endsWith(".tif", Qt::CaseInsensitive))
    {
        TIFF* tif = TIFFOpen(sFullName.toStdString().c_str(), "r");

        quint32 nColSize, nRowSize;
        TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &nColSize);
        TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &nRowSize);

        char* imageDescBuf;
        TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &imageDescBuf);
        QTextStream imageDescAll(imageDescBuf, QIODevice::ReadOnly);
        QString sImageDesc = imageDescAll.readAll();
        qDebug() << sImageDesc;

        const QRegularExpression regexpTimeSize("(\\t)*Repeat T \\- (?<timeSize>\\d+) times \\(.*\\)");
        const QRegularExpressionMatch matchTimeSize = regexpTimeSize.match(sImageDesc);
        int nTimeSize = 0;
        if(matchTimeSize.hasMatch())
            nTimeSize = matchTimeSize.captured("timeSize").toInt();
        else
            nTimeSize = TIFFNumberOfDirectories(tif);

        TIFFClose(tif);

        const QRegularExpression regexpHeightSize("(\\t)*Repeat Z \\- .* in (?<heightSize>\\d+) planes .*");
        const QRegularExpressionMatch matchHeightSize = regexpHeightSize.match(sImageDesc);
        int nHeightSize = 0;
        if(matchHeightSize.hasMatch())
            nHeightSize = matchHeightSize.captured("heightSize").toInt();
        else
            nHeightSize = 1;

        QStringList lParam;
        QString sSqlString("'%1'");
        lParam << sSqlString.arg(sHash) << sSqlString.arg(sPath) << sSqlString.arg(sFileName);
        lParam << QString::number(nColSize) << QString::number(nRowSize) << QString::number(nHeightSize) << QString::number(nTimeSize);
        m_slQuery << "insert into ImageList (Hash, Path, FileName, ColSize, RowSize, HeightSize, TimeSize, Series)"
                 "values (" + lParam.join(',') + ", False)";

        return true;
    }
    else if(sFileName.endsWith(".avi", Qt::CaseInsensitive))
    {
        cv::VideoCapture capture(sFullName.toStdString());
        if(capture.isOpened())
        {
            const int nRowSize = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
            const int nColSize = capture.get(CV_CAP_PROP_FRAME_WIDTH);
            const int nTimeSize = capture.get(CV_CAP_PROP_FRAME_COUNT);
            const int nHeightSize = 1;  //  fix later

            capture.release();

            QStringList lParam;
            QString sSqlString("'%1'");
            lParam << sSqlString.arg(sHash) << sSqlString.arg(sPath) << sSqlString.arg(sFileName);
            lParam << QString::number(nColSize) << QString::number(nRowSize) << QString::number(nHeightSize) << QString::number(nTimeSize);
            m_slQuery << "insert into ImageList (Hash, Path, FileName, ColSize, RowSize, HeightSize, TimeSize, Series)"
                     "values (" + lParam.join(',') + ", False)";
            return true;
        }
        else
            return false;
    }
    else
        return false;
}
예제 #5
0
CPL_C_END

/************************************************************************/
/*                         GTIFFWriteDirectory()                        */
/*                                                                      */
/*      Create a new directory, without any image data for an overview  */
/*      or a mask                                                       */
/*      Returns offset of newly created directory, but the              */
/*      current directory is reset to be the one in used when this      */
/*      function is called.                                             */
/************************************************************************/

long GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize,
                           int nBitsPerPixel, int nPlanarConfig, int nSamples, 
                           int nBlockXSize, int nBlockYSize,
                           int bTiled, int nCompressFlag, int nPhotometric,
                           int nSampleFormat, 
                           unsigned short *panRed,
                           unsigned short *panGreen,
                           unsigned short *panBlue,
                           int nExtraSamples,
                           unsigned short *panExtraSampleValues,
                           const char *pszMetadata )

{
    toff_t	nBaseDirOffset;
    toff_t	nOffset;

    nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );

#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION >= 20051201 /* 3.8.0 */
    TIFFFreeDirectory( hTIFF );
#endif

    TIFFCreateDirectory( hTIFF );
    
/* -------------------------------------------------------------------- */
/*      Setup TIFF fields.                                              */
/* -------------------------------------------------------------------- */
    TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
    TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
    if( nSamples == 1 )
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
    else
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanarConfig );

    TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerPixel );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples );
    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag );
    TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );

    if( bTiled )
    {
        TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize );
        TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize );
    }
    else
        TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );

    TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, nSubfileType );

    if (panExtraSampleValues != NULL)
    {
        TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples, panExtraSampleValues );
    }
    
/* -------------------------------------------------------------------- */
/*	Write color table if one is present.				*/
/* -------------------------------------------------------------------- */
    if( panRed != NULL )
    {
        TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
    }

/* -------------------------------------------------------------------- */
/*      Write metadata if we have some.                                 */
/* -------------------------------------------------------------------- */
    if( pszMetadata && strlen(pszMetadata) > 0 )
        TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, pszMetadata );

/* -------------------------------------------------------------------- */
/*      Write directory, and return byte offset.                        */
/* -------------------------------------------------------------------- */
    if( TIFFWriteCheck( hTIFF, bTiled, "GTIFFWriteDirectory" ) == 0 )
    {
        TIFFSetSubDirectory( hTIFF, nBaseDirOffset );
        return 0;
    }

    TIFFWriteDirectory( hTIFF );
    TIFFSetDirectory( hTIFF, (tdir_t) (TIFFNumberOfDirectories(hTIFF)-1) );

    nOffset = TIFFCurrentDirOffset( hTIFF );

    TIFFSetSubDirectory( hTIFF, nBaseDirOffset );

    return nOffset;
}
예제 #6
0
int LoadTiff
(
  const MinImg *pImg,
  const char *pFileName,
  int page
)
{
#ifndef WITH_TIFF
  return NOT_IMPLEMENTED;
#else
  if (!pImg || !pFileName || page < 0)
    return BAD_ARGS;
  if (!pImg->pScan0)
    return BAD_ARGS;

  TIFFSetErrorHandler(NULL);
  TIFFSetWarningHandler(NULL);

  scoped_tiff_handle pTIF(TIFFOpen(pFileName, "r"));
  if (!pTIF)
    return FILE_ERROR;
  const int nPages = TIFFNumberOfDirectories(pTIF);
  if (page >= nPages)
    return BAD_ARGS;
  TIFFSetDirectory(pTIF, page);

  int nc = 0, typ = PLANARCONFIG_CONTIG;
  _TIFFGetField(pTIF, TIFFTAG_SAMPLESPERPIXEL, &nc, 1);
  if (nc > 1)
    _TIFFGetField(pTIF, TIFFTAG_PLANARCONFIG, &typ, PLANARCONFIG_CONTIG);
  if (typ != PLANARCONFIG_CONTIG)
    return NOT_IMPLEMENTED;

  int wd = 0, ht = 0, bpc = 0;
  _TIFFGetField(pTIF, TIFFTAG_IMAGEWIDTH, &wd, 0);
  _TIFFGetField(pTIF, TIFFTAG_IMAGELENGTH, &ht, 0);
  _TIFFGetField(pTIF, TIFFTAG_BITSPERSAMPLE, &bpc, 0);

  if (bpc != 1 && bpc & 7)
    return NOT_IMPLEMENTED;
  bpc = bpc >> 3;

  if (pImg->channels != nc)
    return BAD_ARGS;
  if (bpc == 0 && pImg->channelDepth > 1)
    return BAD_ARGS;
  if (bpc > 0 && pImg->channelDepth != bpc)
    return BAD_ARGS;
  if (pImg->height < ht || pImg->width < wd)
    return BAD_ARGS;

  int metr = 0;
  _TIFFGetField(pTIF, TIFFTAG_PHOTOMETRIC, &metr, PHOTOMETRIC_MINISWHITE);
  if (metr == PHOTOMETRIC_MINISWHITE && bpc > 0)
    return NOT_IMPLEMENTED;

  int dtyp = SAMPLEFORMAT_UINT;
  _TIFFGetField(pTIF, TIFFTAG_SAMPLEFORMAT, &dtyp, SAMPLEFORMAT_UINT);
  switch (dtyp)
  {
  case SAMPLEFORMAT_UINT:
    if (pImg->format != FMT_UINT)
      return BAD_ARGS;
    break;
  case SAMPLEFORMAT_INT:
    if (pImg->format != FMT_INT)
      return BAD_ARGS;
    break;
  case SAMPLEFORMAT_IEEEFP:
    if (pImg->format != FMT_REAL)
      return BAD_ARGS;
    break;
  default:
    return NOT_IMPLEMENTED;
  }

  const tsize_t scanLen = TIFFScanlineSize(pTIF);
  scoped_scanline pScanLine(_TIFFmalloc(scanLen));
  if (!pScanLine)
    return NO_MEMORY;
  const int byteWidth = pImg->channelDepth > 0 ?
                        pImg->width * pImg->channels * pImg->channelDepth :
                        (pImg->width * pImg->channels + 7) >> 3;
  if (byteWidth < scanLen)
    return INTERNAL_ERROR;

  bool invert = (metr == PHOTOMETRIC_MINISWHITE);
  uint8_t *pScanLineUint8 = (uint8_t *)((void *)(pScanLine));

  for (int y = 0; y < ht; y++)
  {
    SHOULD_WORK(TIFFReadScanline(pTIF, pScanLine, y));

    if (bpc == 0 && bpc == pImg->channelDepth)
      CopyBits(pImg->pScan0 + pImg->stride * y, pScanLineUint8, wd, invert);
    else if (bpc == 0 && bpc < pImg->channelDepth)
      UnpackLine(pImg->pScan0 + pImg->stride * y, pScanLineUint8, wd, invert);
    else
      memcpy(pImg->pScan0 + pImg->stride * y, pScanLine, scanLen);
  }

  return NO_ERRORS;
#endif // WITH_TIFF
}
예제 #7
0
int GetTiffPropsEx
(
  MinImg *pImg,
  ExtImgProps *pProps,
  const char *pFileName,
  int page
)
{
#ifndef WITH_TIFF
  return NOT_IMPLEMENTED;
#else 
  if (!pFileName || page < 0)
    return BAD_ARGS;
  if (pImg && pImg->pScan0)
    return BAD_ARGS;

  TIFFSetErrorHandler(NULL);
  TIFFSetWarningHandler(NULL);

  scoped_tiff_handle pTIF(TIFFOpen(pFileName, "r"));
  if (!pTIF)
    return FILE_ERROR;
  const int nPages = TIFFNumberOfDirectories(pTIF);
  if (page >= nPages)
    return BAD_ARGS;
  TIFFSetDirectory(pTIF, page);

  if (pImg)
  {
    int nc = 0, typ = PLANARCONFIG_CONTIG;
    _TIFFGetField(pTIF, TIFFTAG_SAMPLESPERPIXEL, &nc, 1);
    if (nc > 1)
      _TIFFGetField(pTIF, TIFFTAG_PLANARCONFIG, &typ, PLANARCONFIG_CONTIG);
    if (typ != PLANARCONFIG_CONTIG)
      return NOT_IMPLEMENTED;

    int wd = 0, ht = 0, bpc = 0;
    _TIFFGetField(pTIF, TIFFTAG_IMAGEWIDTH, &wd, 0);
    _TIFFGetField(pTIF, TIFFTAG_IMAGELENGTH, &ht, 0);
    _TIFFGetField(pTIF, TIFFTAG_BITSPERSAMPLE, &bpc, 0);
    if (bpc != 1 && bpc & 7)
      return NOT_IMPLEMENTED;
    bpc = bpc >> 3;

    int dtyp = 0;
    _TIFFGetField(pTIF, TIFFTAG_SAMPLEFORMAT, &dtyp, 0);
    switch (dtyp)
    {
    case 0:
    case SAMPLEFORMAT_UINT:
      dtyp = FMT_UINT;
      break;
    case SAMPLEFORMAT_INT:
      dtyp = FMT_INT;
      break;
    case SAMPLEFORMAT_IEEEFP:
      dtyp = FMT_REAL;
      break;
    default:
      return NOT_IMPLEMENTED;
    }

    pImg->width = wd;
    pImg->height = ht;
    pImg->channels = nc;
    pImg->channelDepth = bpc;
    pImg->format = (MinFmt)dtyp;
    pImg->stride = 0;
  }

  if (pProps)
  {
    pProps->iff = IFF_TIFF;
    pProps->comp = IFC_NONE;

    int compression = 0;
    _TIFFGetField(pTIF, TIFFTAG_COMPRESSION, &compression, COMPRESSION_NONE);
    switch(compression)
    {
      case COMPRESSION_LZW: pProps->comp = IFC_LZW; break;
      case COMPRESSION_DEFLATE: pProps->comp = IFC_DEFLATE; break;
      case COMPRESSION_PACKBITS: pProps->comp = IFC_PACKBITS; break;
      case COMPRESSION_JPEG: pProps->comp = IFC_JPEG; break;
      case COMPRESSION_CCITTRLE: pProps->comp = IFC_RLE; break;
      case COMPRESSION_CCITTFAX3: pProps->comp = IFC_GROUP3; break;
      case COMPRESSION_CCITTFAX4: pProps->comp = IFC_GROUP4; break;
      default: pProps->comp = IFC_NONE;
    }

    int unit = 0;
    _TIFFGetField(pTIF, TIFFTAG_XRESOLUTION, &pProps->xDPI, 0.f);
    _TIFFGetField(pTIF, TIFFTAG_YRESOLUTION, &pProps->yDPI, 0.f);
    _TIFFGetField(pTIF, TIFFTAG_RESOLUTIONUNIT, &unit, 0);
    switch (unit)
    {
    case RESUNIT_INCH:
      break;
    case RESUNIT_CENTIMETER:
      pProps->xDPI *= 2.54f;
      pProps->yDPI *= 2.54f;
      break;
    default:
      pProps->xDPI = 0.f;
      pProps->yDPI = 0.f;
    }
  }

  return NO_ERRORS;
#endif // WITH_TIFF
}
예제 #8
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam   values[2];
  GimpRunMode        run_mode;
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
  GError            *error  = NULL;

  INIT_I18N ();
  gegl_init (NULL, NULL);

  run_mode = param[0].data.d_int32;

  *nreturn_vals = 1;
  *return_vals  = values;

  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;

  if (strcmp (name, LOAD_PROC) == 0)
    {
      const gchar *filename = param[1].data.d_string;
      TIFF        *tif;

      tif = tiff_open (filename, "r", &error);

      if (tif)
        {
          TiffSelectedPages pages;

          pages.target = GIMP_PAGE_SELECTOR_TARGET_LAYERS;

          gimp_get_data (LOAD_PROC, &pages.target);

          pages.n_pages = pages.o_pages = TIFFNumberOfDirectories (tif);

          if (pages.n_pages == 0)
            {
              g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                           _("TIFF '%s' does not contain any directories"),
                           gimp_filename_to_utf8 (filename));

              status = GIMP_PDB_EXECUTION_ERROR;
            }
          else
            {
              gboolean run_it = FALSE;
              gint     i;

              if (run_mode != GIMP_RUN_INTERACTIVE)
                {
                  pages.pages = g_new (gint, pages.n_pages);

                  for (i = 0; i < pages.n_pages; i++)
                    pages.pages[i] = i;

                  run_it = TRUE;
                }
              else
                {
                  gimp_ui_init (PLUG_IN_BINARY, FALSE);
                }

              if (pages.n_pages == 1)
                {
                  pages.pages  = g_new0 (gint, pages.n_pages);
                  pages.target = GIMP_PAGE_SELECTOR_TARGET_LAYERS;

                  run_it = TRUE;
                }

              if ((! run_it) && (run_mode == GIMP_RUN_INTERACTIVE))
                run_it = load_dialog (tif, LOAD_PROC, &pages);

              if (run_it)
                {
                  gint32   image;
                  gboolean resolution_loaded = FALSE;

                  gimp_set_data (LOAD_PROC,
                                 &pages.target, sizeof (pages.target));

                  image = load_image (param[1].data.d_string, tif, &pages,
                                      &resolution_loaded,
                                      &error);

                  g_free (pages.pages);

                  if (image > 0)
                    {
                      GFile        *file;
                      GimpMetadata *metadata;

                      file = g_file_new_for_path (param[1].data.d_string);

                      metadata = gimp_image_metadata_load_prepare (image,
                                                                   "image/tiff",
                                                                   file, NULL);

                      if (metadata)
                        {
                          GimpMetadataLoadFlags flags = GIMP_METADATA_LOAD_ALL;

                          if (resolution_loaded)
                            flags &= ~GIMP_METADATA_LOAD_RESOLUTION;

                          gimp_image_metadata_load_finish (image, "image/tiff",
                                                           metadata, flags,
                                                           run_mode == GIMP_RUN_INTERACTIVE);

                          g_object_unref (metadata);
                        }

                      g_object_unref (file);

                      *nreturn_vals = 2;
                      values[1].type         = GIMP_PDB_IMAGE;
                      values[1].data.d_image = image;
                    }
                  else
                    {
                      status = GIMP_PDB_EXECUTION_ERROR;
                    }
                }
              else
                {
                  status = GIMP_PDB_CANCEL;
                }
            }

          TIFFClose (tif);
        }
      else
        {
          status = GIMP_PDB_EXECUTION_ERROR;
        }
    }
  else if ((strcmp (name, SAVE_PROC)  == 0) ||
           (strcmp (name, SAVE2_PROC) == 0))
    {
      /* Plug-in is either file_tiff_save or file_tiff_save2 */

      GimpMetadata          *metadata;
      GimpMetadataSaveFlags  metadata_flags;
      GimpParasite          *parasite;
      gint32                 image      = param[1].data.d_int32;
      gint32                 drawable   = param[2].data.d_int32;
      gint32                 orig_image = image;
      GimpExportReturn       export     = GIMP_EXPORT_CANCEL;

      switch (run_mode)
        {
        case GIMP_RUN_INTERACTIVE:
        case GIMP_RUN_WITH_LAST_VALS:
          gimp_ui_init (PLUG_IN_BINARY, FALSE);

          export = gimp_export_image (&image, &drawable, "TIFF",
                                      GIMP_EXPORT_CAN_HANDLE_RGB     |
                                      GIMP_EXPORT_CAN_HANDLE_GRAY    |
                                      GIMP_EXPORT_CAN_HANDLE_INDEXED |
                                      GIMP_EXPORT_CAN_HANDLE_ALPHA);

          if (export == GIMP_EXPORT_CANCEL)
            {
              values[0].data.d_status = GIMP_PDB_CANCEL;
              return;
            }
          break;
        default:
          break;
        }
예제 #9
0
/**
 * Loads a TIFF file.
 *
 *
 * \param mem:   Memory containing the TIFF file.
 * \param size:  Size of the mem buffer.
 * \param flags: If flags has IB_test set then the file is not actually loaded,
 *                but all other operations take place.
 *
 * \return: A newly allocated ImBuf structure if successful, otherwise NULL.
 */
ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
	TIFF *image = NULL;
	ImBuf *ibuf = NULL, *hbuf;
	ImbTIFFMemFile memFile;
	uint32 width, height;
	char *format = NULL;
	int level;
	short spp;
	int ib_depth;

	/* check whether or not we have a TIFF file */
	if (size < IMB_TIFF_NCB) {
		fprintf(stderr, "imb_loadtiff: size < IMB_TIFF_NCB\n");
		return NULL;
	}
	if (imb_is_a_tiff(mem) == 0)
		return NULL;

	/* both 8 and 16 bit PNGs are default to standard byte colorspace */
	colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);

	image = imb_tiff_client_open(&memFile, mem, size);

	if (image == NULL) {
		printf("imb_loadtiff: could not open TIFF IO layer.\n");
		return NULL;
	}

	/* allocate the image buffer */
	TIFFGetField(image, TIFFTAG_IMAGEWIDTH,  &width);
	TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height);
	TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp);
	
	ib_depth = (spp == 3) ? 24 : 32;
	
	ibuf = IMB_allocImBuf(width, height, ib_depth, 0);
	if (ibuf) {
		ibuf->ftype = TIF;
	}
	else {
		fprintf(stderr, 
		        "imb_loadtiff: could not allocate memory for TIFF "
		        "image.\n");
		TIFFClose(image);
		return NULL;
	}

	/* get alpha mode from file header */
	if (flags & IB_alphamode_detect) {
		if (spp == 4) {
			unsigned short extra, *extraSampleTypes;

			TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extra, &extraSampleTypes);

			if (extraSampleTypes[0] == EXTRASAMPLE_ASSOCALPHA)
				ibuf->flags |= IB_alphamode_premul;
		}
	}

	/* if testing, we're done */
	if (flags & IB_test) {
		TIFFClose(image);
		return ibuf;
	}

	/* detect if we are reading a tiled/mipmapped texture, in that case
	 * we don't read pixels but leave it to the cache to load tiles */
	if (flags & IB_tilecache) {
		format = NULL;
		TIFFGetField(image, TIFFTAG_PIXAR_TEXTUREFORMAT, &format);

		if (format && strcmp(format, "Plain Texture") == 0 && TIFFIsTiled(image)) {
			int numlevel = TIFFNumberOfDirectories(image);

			/* create empty mipmap levels in advance */
			for (level = 0; level < numlevel; level++) {
				if (!TIFFSetDirectory(image, level))
					break;

				if (level > 0) {
					width = (width > 1) ? width / 2 : 1;
					height = (height > 1) ? height / 2 : 1;

					hbuf = IMB_allocImBuf(width, height, 32, 0);
					hbuf->miplevel = level;
					hbuf->ftype = ibuf->ftype;
					ibuf->mipmap[level - 1] = hbuf;
				}
				else
					hbuf = ibuf;

				hbuf->flags |= IB_tilecache;

				TIFFGetField(image, TIFFTAG_TILEWIDTH, &hbuf->tilex);
				TIFFGetField(image, TIFFTAG_TILELENGTH, &hbuf->tiley);

				hbuf->xtiles = ceil(hbuf->x / (float)hbuf->tilex);
				hbuf->ytiles = ceil(hbuf->y / (float)hbuf->tiley);

				imb_addtilesImBuf(hbuf);

				ibuf->miptot++;
			}
		}
	}

	/* read pixels */
	if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image)) {
		fprintf(stderr, "imb_loadtiff: Failed to read tiff image.\n");
		TIFFClose(image);
		return NULL;
	}

	/* close the client layer interface to the in-memory file */
	TIFFClose(image);

	/* return successfully */
	return ibuf;
}
예제 #10
0
uint32 TIFF_WriteOverview( TIFF *hTIFF, int nXSize, int nYSize,
                           int nBitsPerPixel, int nPlanarConfig, int nSamples, 
                           int nBlockXSize, int nBlockYSize,
                           int bTiled, int nCompressFlag, int nPhotometric,
                           int nSampleFormat,
                           unsigned short *panRed,
                           unsigned short *panGreen,
                           unsigned short *panBlue,
                           int bUseSubIFDs,
                           int nHorSubsampling, int nVerSubsampling )

{
    uint32	nBaseDirOffset;
    uint32	nOffset;

    nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );

    TIFFCreateDirectory( hTIFF );

/* -------------------------------------------------------------------- */
/*      Setup TIFF fields.                                              */
/* -------------------------------------------------------------------- */
    TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
    TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
    if( nSamples == 1 )
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
    else
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanarConfig );

    TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerPixel );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples );
    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag );
    TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );

    if( bTiled )
    {
        TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize );
        TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize );
    }
    else
        TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );

    TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE );

    if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
    {
        TIFFSetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, nHorSubsampling, nVerSubsampling);
        /* TODO: also write YCbCrPositioning and YCbCrCoefficients tag identical to source IFD */
    }
    /* TODO: add command-line parameter for selecting jpeg compression quality
     * that gets ignored when compression isn't jpeg */

/* -------------------------------------------------------------------- */
/*	Write color table if one is present.				*/
/* -------------------------------------------------------------------- */
    if( panRed != NULL )
    {
        TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
    }

/* -------------------------------------------------------------------- */
/*      Write directory, and return byte offset.                        */
/* -------------------------------------------------------------------- */
    if( TIFFWriteCheck( hTIFF, bTiled, "TIFFBuildOverviews" ) == 0 )
        return 0;

    TIFFWriteDirectory( hTIFF );
    TIFFSetDirectory( hTIFF, (tdir_t) (TIFFNumberOfDirectories(hTIFF)-1) );

    nOffset = TIFFCurrentDirOffset( hTIFF );

    TIFFSetSubDirectory( hTIFF, nBaseDirOffset );

    return nOffset;
}
예제 #11
0
static
uint32 TIFF_WriteOverview( TIFF *hTIFF, int nXSize, int nYSize,
                           int nBitsPerPixel, int nSamples, 
                           int nBlockXSize, int nBlockYSize,
                           int bTiled, int nCompressFlag, int nPhotometric,
                           int nSampleFormat,
                           unsigned short *panRed,
                           unsigned short *panGreen,
                           unsigned short *panBlue,
                           int bUseSubIFDs )

{
    uint32	nBaseDirOffset;
    uint32	nOffset;

    nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );

    TIFFCreateDirectory( hTIFF );
    
/* -------------------------------------------------------------------- */
/*      Setup TIFF fields.                                              */
/* -------------------------------------------------------------------- */
    TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
    TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
    if( nSamples == 1 )
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
    else
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_SEPARATE );

    TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerPixel );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples );
    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag );
    TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );

    if( bTiled )
    {
        TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize );
        TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize );
    }
    else
        TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );

    TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE );
    
/* -------------------------------------------------------------------- */
/*	Write color table if one is present.				*/
/* -------------------------------------------------------------------- */
    if( panRed != NULL )
    {
        TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
    }

/* -------------------------------------------------------------------- */
/*      Write directory, and return byte offset.                        */
/* -------------------------------------------------------------------- */
    TIFFWriteCheck( hTIFF, bTiled, "TIFFBuildOverviews" );
    TIFFWriteDirectory( hTIFF );
    TIFFSetDirectory( hTIFF, TIFFNumberOfDirectories(hTIFF)-1 );

    nOffset = TIFFCurrentDirOffset( hTIFF );

    TIFFSetSubDirectory( hTIFF, nBaseDirOffset );

    return nOffset;
}
예제 #12
0
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=(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

  try{
    //check if it's a tiff file
    if (!m_tif)
        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))
        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;
        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) &&
        (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)){
            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 (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding

    Create(width,height,head.biBitCount,CXIMAGE_FORMAT_TIF);	//image creation
    if (!pDib) 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) 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);
                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);
                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 {
        RGBQUAD *pal;
        pal=(RGBQUAD*)calloc(256,sizeof(RGBQUAD));
        if (pal==NULL) throw "Unable to allocate TIFF palette";

        // 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 (DWORD i=0; i<head.biClrUsed; i++){
                            pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(i*(255/(head.biClrUsed-1)));
                        }
                    } else {
                        for (DWORD i=0; i<head.biClrUsed; i++){
                            pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(255-i*(255/(head.biClrUsed-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;
                int n=1<<bitspersample;
                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 << bitspersample) - 1; i >= 0; i--) {
                    if (Palette16Bits) {
                        pal[i].rgbRed =(BYTE) CVT(red[i]);
                        pal[i].rgbGreen = (BYTE) CVT(green[i]);
                        pal[i].rgbBlue = (BYTE) CVT(blue[i]);           
                    } else {
                        pal[i].rgbRed = (BYTE) red[i];
                        pal[i].rgbGreen = (BYTE) green[i];
                        pal[i].rgbBlue = (BYTE) blue[i];        
                    }
                }
                break;
        }
        SetPalette(pal,head.biClrUsed);	//palette assign
        free(pal);

        // read the tiff lines and save them in the DIB
        uint32 nrow;
        uint32 ys;
        int line = CalculateLine(width, bitspersample * samplesperpixel);
        long bitsize= TIFFStripSize(m_tif);
        //verify bitsize: could be wrong if StripByteCounts is missing.
        if (bitsize>(long)(head.biSizeImage*samplesperpixel)) bitsize=head.biSizeImage*samplesperpixel;

        int tiled_image = TIFFIsTiled(m_tif);
        uint32 tw, tl;
        BYTE* tilebuf;
        if (tiled_image){
            TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &tw);
            TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &tl);
            rowsperstrip = tl;
            bitsize = TIFFTileSize(m_tif) * (int)(1+width/tw);
            tilebuf = (BYTE*)malloc(TIFFTileSize(m_tif));
        }
        
        bits = (BYTE*)malloc(bitsize);
        if (bits==NULL){
            throw "CxImageTIF can't allocate memory";
        }

        for (ys = 0; ys < height; ys += rowsperstrip) {

            if (info.nEscape){ // <vho> - cancel decoding
                free(bits);
                throw "Cancelled";
            }

            nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip);

            if (tiled_image){
                uint32 imagew = TIFFScanlineSize(m_tif);
                uint32 tilew  = TIFFTileRowSize(m_tif);
                int 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);
                        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), bits, nrow * line) == -1) {
                    free(bits);
                    throw "Corrupted TIFF file!";
                }
            }

            for (y = 0; y < nrow; y++) {
                long offset=(nrow-y-1)*line;
                if (bitspersample==16) for (DWORD xi=0;xi<width;xi++) bits[xi+offset]=bits[xi*2+offset+1];
                if (samplesperpixel==1) { //simple 8bpp image
                    memcpy(info.pImage+info.dwEffWidth*(height-ys-nrow+y),bits+offset,info.dwEffWidth);
                } else if (samplesperpixel==2) { //8bpp image with alpha layer
                    int xi=0;
                    int ii=0;
                    int yi=height-ys-nrow+y;
                    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>=(int)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
                    }

                    int xi=0;
                    int ii=0;
                    int yi=height-ys-nrow+y;
                    RGBQUAD c;
                    int l,a,b,bitsoffset;
                    double p,cx,cy,cz,cr,cg,cb;
                    while (ii<line){
                        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  =(BYTE)max(0,min(255,(int)(cr*255)));
                        c.rgbGreen=(BYTE)max(0,min(255,(int)(cg*255)));
                        c.rgbBlue =(BYTE)max(0,min(255,(int)(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>=(int)width){
                            yi--;
                            xi=0;
                        }
                    }
                }
            }
        }
        free(bits);
        if (tiled_image) free(tilebuf);

        switch(orientation){
        case ORIENTATION_TOPRIGHT: /* row 0 top, col 0 rhs */
            Mirror();
            break;
        case ORIENTATION_BOTRIGHT: /* row 0 bottom, col 0 rhs */
            Flip();
            Mirror();
            break;
        case ORIENTATION_BOTLEFT: /* row 0 bottom, col 0 lhs */
            Flip();
            break;
        case ORIENTATION_LEFTTOP: /* row 0 lhs, col 0 top */
            RotateRight();
            Mirror();
            break;
        case ORIENTATION_RIGHTTOP: /* row 0 rhs, col 0 top */
            RotateLeft();
            break;
        case ORIENTATION_RIGHTBOT: /* row 0 rhs, col 0 bottom */
            RotateLeft();
            Mirror();
            break;
        case ORIENTATION_LEFTBOT: /* row 0 lhs, col 0 bottom */
            RotateRight();
            break;
        }

    }
  } catch (char *message) {
      strncpy(info.szLastError,message,255);
      if (m_tif) TIFFClose(m_tif);
      if (info.nEscape==-1) return true;
      return false;
  }
    TIFFClose(m_tif);
    return true;
}
예제 #13
0
static void
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
{
  static GimpParam   values[2];
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
  GError            *error  = NULL;
  gint32             image;
  TiffSelectedPages  pages;

  run_mode = param[0].data.d_int32;

  INIT_I18N ();

  *nreturn_vals = 1;
  *return_vals  = values;

  gegl_init (NULL, NULL);

  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;

  TIFFSetWarningHandler (tiff_warning);
  TIFFSetErrorHandler (tiff_error);

  if (strcmp (name, LOAD_PROC) == 0)
    {
      const gchar *filename = param[1].data.d_string;
      TIFF        *tif      = NULL;
      gint         fd;

      fd = g_open (filename, O_RDONLY | _O_BINARY, 0);

      if (fd == -1)
        {
          g_set_error (&error, G_FILE_ERROR, g_file_error_from_errno (errno),
                       _("Could not open '%s' for reading: %s"),
                       gimp_filename_to_utf8 (filename), g_strerror (errno));

          status = GIMP_PDB_EXECUTION_ERROR;
        }
      else
        {
          tif = TIFFFdOpen (fd, filename, "r");
        }

      if (tif)
        {
          gimp_get_data (LOAD_PROC, &target);

          pages.n_pages = pages.o_pages = TIFFNumberOfDirectories (tif);

          if (pages.n_pages == 0)
            {
              g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                           _("TIFF '%s' does not contain any directories"),
                           gimp_filename_to_utf8 (filename));

              status = GIMP_PDB_EXECUTION_ERROR;
            }
          else
            {
              gboolean run_it = FALSE;
              gint     i;

              if (run_mode != GIMP_RUN_INTERACTIVE)
                {
                  pages.pages = g_new (gint, pages.n_pages);

                  for (i = 0; i < pages.n_pages; i++)
                    pages.pages[i] = i;

                  run_it = TRUE;
                }

              if (pages.n_pages == 1)
                {
                  target = GIMP_PAGE_SELECTOR_TARGET_LAYERS;
                  pages.pages = g_new0 (gint, pages.n_pages);

                  run_it = TRUE;
                }

              if ((! run_it) && (run_mode == GIMP_RUN_INTERACTIVE))
                run_it = load_dialog (tif, &pages);

              if (run_it)
                {
                  gimp_set_data (LOAD_PROC, &target, sizeof (target));

                  image = load_image (param[1].data.d_string, tif, &pages,
                                      &error);

                  g_free (pages.pages);

                  if (image != -1)
                    {
                      *nreturn_vals = 2;
                      values[1].type         = GIMP_PDB_IMAGE;
                      values[1].data.d_image = image;
                    }
                  else
                    {
                      status = GIMP_PDB_EXECUTION_ERROR;
                    }
                }
              else
                {
                  status = GIMP_PDB_CANCEL;
                }
            }

          TIFFClose (tif);
          close (fd);
        }
      else
        {
          close (fd);
          status = GIMP_PDB_EXECUTION_ERROR;
        }
    }
  else
    {
      status = GIMP_PDB_CALLING_ERROR;
    }

  if (status != GIMP_PDB_SUCCESS && error)
    {
      *nreturn_vals = 2;
      values[1].type          = GIMP_PDB_STRING;
      values[1].data.d_string = error->message;
    }

  values[0].data.d_status = status;
}
예제 #14
0
toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize,
                           int nBitsPerPixel, int nPlanarConfig, int nSamples, 
                           int nBlockXSize, int nBlockYSize,
                           int bTiled, int nCompressFlag, int nPhotometric,
                           int nSampleFormat, 
                           int nPredictor,
                           unsigned short *panRed,
                           unsigned short *panGreen,
                           unsigned short *panBlue,
                           int nExtraSamples,
                           unsigned short *panExtraSampleValues,
                           const char *pszMetadata )

{
    toff_t	nBaseDirOffset;
    toff_t	nOffset;

    nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );

#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION >= 20051201 /* 3.8.0 */
    TIFFFreeDirectory( hTIFF );
#endif

    TIFFCreateDirectory( hTIFF );
    
/* -------------------------------------------------------------------- */
/*      Setup TIFF fields.                                              */
/* -------------------------------------------------------------------- */
    TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
    TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
    if( nSamples == 1 )
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
    else
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanarConfig );

    TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerPixel );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples );
    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag );
    TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );

    if( bTiled )
    {
        TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize );
        TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize );
    }
    else
        TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );

    TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, nSubfileType );

    if (panExtraSampleValues != NULL)
    {
        TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples, panExtraSampleValues );
    }

    if ( nCompressFlag == COMPRESSION_LZW ||
         nCompressFlag == COMPRESSION_ADOBE_DEFLATE )
        TIFFSetField( hTIFF, TIFFTAG_PREDICTOR, nPredictor );

/* -------------------------------------------------------------------- */
/*	Write color table if one is present.				*/
/* -------------------------------------------------------------------- */
    if( panRed != NULL )
    {
        TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
    }

/* -------------------------------------------------------------------- */
/*      Write metadata if we have some.                                 */
/* -------------------------------------------------------------------- */
    if( pszMetadata && strlen(pszMetadata) > 0 )
        TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, pszMetadata );

/* -------------------------------------------------------------------- */
/*      Write directory, and return byte offset.                        */
/* -------------------------------------------------------------------- */
    if( TIFFWriteCheck( hTIFF, bTiled, "GTIFFWriteDirectory" ) == 0 )
    {
        TIFFSetSubDirectory( hTIFF, nBaseDirOffset );
        return 0;
    }

    TIFFWriteDirectory( hTIFF );
    TIFFSetDirectory( hTIFF, (tdir_t) (TIFFNumberOfDirectories(hTIFF)-1) );

    nOffset = TIFFCurrentDirOffset( hTIFF );

    TIFFSetSubDirectory( hTIFF, nBaseDirOffset );

    return nOffset;
}
예제 #15
0
toff_t GTIFFWriteDirectory( TIFF *hTIFF, int nSubfileType,
                            int nXSize, int nYSize,
                            int nBitsPerPixel, int nPlanarConfig, int nSamples,
                            int nBlockXSize, int nBlockYSize,
                            int bTiled, int nCompressFlag, int nPhotometric,
                            int nSampleFormat,
                            int nPredictor,
                            unsigned short *panRed,
                            unsigned short *panGreen,
                            unsigned short *panBlue,
                            int nExtraSamples,
                            unsigned short *panExtraSampleValues,
                            const char *pszMetadata,
                            const char* pszJPEGQuality,
                            const char* pszJPEGTablesMode,
                            const char* pszNoData,
                            CPL_UNUSED const uint32* panLercAddCompressionAndVersion
                           )

{
    const toff_t nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );

    // This is a bit of a hack to cause (*tif->tif_cleanup)(tif); to be called.
    // See https://trac.osgeo.org/gdal/ticket/2055
    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, COMPRESSION_NONE );

#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION >= 20051201  // 3.8.0
    TIFFFreeDirectory( hTIFF );
#endif

    TIFFCreateDirectory( hTIFF );

/* -------------------------------------------------------------------- */
/*      Setup TIFF fields.                                              */
/* -------------------------------------------------------------------- */
    TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
    TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
    if( nSamples == 1 )
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
    else
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanarConfig );

    TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerPixel );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples );
    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag );
    TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );

    if( bTiled )
    {
        TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize );
        TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize );
    }
    else
    {
        TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );
    }

    TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, nSubfileType );

    if( panExtraSampleValues != nullptr )
    {
        TIFFSetField( hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples,
                      panExtraSampleValues );
    }

    if( nCompressFlag == COMPRESSION_LZW ||
        nCompressFlag == COMPRESSION_ADOBE_DEFLATE ||
        nCompressFlag == COMPRESSION_ZSTD )
        TIFFSetField( hTIFF, TIFFTAG_PREDICTOR, nPredictor );

/* -------------------------------------------------------------------- */
/*      Write color table if one is present.                            */
/* -------------------------------------------------------------------- */
    if( panRed != nullptr )
    {
        TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
    }

/* -------------------------------------------------------------------- */
/*      Write metadata if we have some.                                 */
/* -------------------------------------------------------------------- */
    if( pszMetadata && strlen(pszMetadata) > 0 )
        TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, pszMetadata );


/* -------------------------------------------------------------------- */
/*      Write JPEG tables if needed.                                    */
/* -------------------------------------------------------------------- */
    if( nCompressFlag == COMPRESSION_JPEG )
    {
        GTiffWriteJPEGTables( hTIFF,
                              (nPhotometric == PHOTOMETRIC_RGB) ? "RGB" :
                              (nPhotometric == PHOTOMETRIC_YCBCR) ? "YCBCR" :
                                                                "MINISBLACK",
                              pszJPEGQuality,
                              pszJPEGTablesMode );

        if( nPhotometric == PHOTOMETRIC_YCBCR )
        {
            // Explicitly register the subsampling so that JPEGFixupTags
            // is a no-op (helps for cloud optimized geotiffs)
            TIFFSetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, 2, 2 );
        }
    }

#ifdef HAVE_LERC
    if( nCompressFlag == COMPRESSION_LERC && panLercAddCompressionAndVersion )
    {
        TIFFSetField(hTIFF, TIFFTAG_LERC_PARAMETERS, 2,
                     panLercAddCompressionAndVersion);
    }
#endif

/* -------------------------------------------------------------------- */
/*      Write no data value if we have one.                             */
/* -------------------------------------------------------------------- */
    if( pszNoData != nullptr )
    {
        TIFFSetField( hTIFF, TIFFTAG_GDAL_NODATA, pszNoData );
    }

/* -------------------------------------------------------------------- */
/*      Write directory, and return byte offset.                        */
/* -------------------------------------------------------------------- */
    if( TIFFWriteCheck( hTIFF, bTiled, "GTIFFWriteDirectory" ) == 0 )
    {
        TIFFSetSubDirectory( hTIFF, nBaseDirOffset );
        return 0;
    }

    TIFFWriteDirectory( hTIFF );
    TIFFSetDirectory( hTIFF,
                      static_cast<tdir_t>(TIFFNumberOfDirectories(hTIFF) - 1) );

    const toff_t nOffset = TIFFCurrentDirOffset( hTIFF );

    TIFFSetSubDirectory( hTIFF, nBaseDirOffset );

    return nOffset;
}
예제 #16
0
파일: ccl.c 프로젝트: physikerwelt/MaxTract
main(int argc, char* argv[])
{
  //START;
  
  // the required page number in a multipage tiff, use 0 for first page
  int dir_num;
  dir_num = atoi(argv[2]);
  //time_t start, end;
  double duration;
  TIFF* tif = TIFFOpen(argv[1], "r");
  //get number of pages (Directories) in a tiff file
    int dir_count;
    dir_count = TIFFNumberOfDirectories(tif);
    if(dir_num < 0 || dir_num > (dir_count-1)){
       printf("Error: invalid directory number\n");
       exit -1;
    }
    else{
    
   if (tif) {
    uint32 w, h;
    size_t npixels;
    uint32* raster;
    // set the required page (directory)
    // change to the requested directory and read its contents with TIFFReadDirectory
    TIFFSetDirectory(tif,dir_num);
      
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
    npixels = w * h;

    int r,v;
    //Foreground and Background pixel values
    int F = 1, B = 0;
    size_t c_h, c_w;
    raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
    // image matrix with added boundary pixels
    int** I = malloc((h+2) * sizeof(int*));    // allocate the rows
    for ( r = 0; r < (h+2); ++r)
     {
       I[r] = malloc((w+2) * sizeof(int));    // allocate the columns
       //for ( cx = 0; cx < COLS; ++cx)
        // I[r][cx] = 0;
     }
     
     // an array of pixel runs (hashtable of pixel runs)
     // each run is a linked list of pixels
     struct pixel **runs = malloc((h*w/4) * sizeof(struct pixel));
     //initialise arrays and linked list
     for ( v = 0; v < (h*w/4); ++v)
     {
       //C[r] = r;    // initialise labels 
       init_pixel(runs[v], 99,99);
     }
     // arrays to save classes and their mappings
     //uint32* C = malloc((ROWS*COLS/2) * sizeof(uint32*)); 
     uint32* rl_table = malloc((h*w/4) * sizeof(uint32*)); 
     uint32* n_label = malloc((h*w/4) * sizeof(uint32*)); 
     uint32* t_label = malloc((h*w/4) * sizeof(uint32*));
     for ( v = 0; v < (h*w/4); ++v)
     {
       //C[r] = r;    
       // initialise classes
       rl_table[v] = v;  
       n_label[v] = -1;
       t_label[v] = v;      
     }
    
    // load image into matrix of F and B pixels (1's and 0's)
    if (raster != NULL) {
      if (TIFFReadRGBAImage(tif, w, h, raster, 0)) {          
        for(c_h=0;c_h<h;c_h++) {
           for(c_w=0;c_w<w;c_w++) {
              v = raster[(w*h)-((c_h*w)+(w-c_w))]%256;
              if (v == 0)
                I[c_h+1][c_w+1] = F;
              else
                I[c_h+1][c_w+1] = B;
           }          
        }               
      }
      _TIFFfree(raster);
    }
    
    /*
     c2  c3  c4
     c1  x 
    */
  

  // FIRST SCAN
  int i,j,k;
  int NewLabel=5; 

 int c1,c2,c3,c4,uu,vv,ii;
  for(c_h=1;c_h<(h-1);c_h++)
    for(c_w=1;c_w<(w-1);c_w++){ // for COLS
      if (I[c_h][c_w] == F) 
	{ 
	    c3 = I[c_h-1][c_w] ;
	    if (c3 != B) 
	    {
		I[c_h][c_w] = c3;
	    }
	    else // else1
	    {
	       c4 = I[c_h-1][c_w+1] ;
	       c1 = I[c_h][c_w-1] ;
	      if (c1 != B) 
	      {
		 I[c_h][c_w] = c1;
		 if (c4 != B && c4 != c1) 
		 {		  
		  //printf ("(%d,%d);", c1, c4);
		  //(* resolve c2 c4 *)	
		  uu = rl_table[c1]; vv = rl_table[c4];
		   if(uu<vv){
		        ii = vv;                      
                        while(ii != -1){
                          rl_table[ii] = uu;
                          ii = n_label[ii];
                        }                      
                        n_label[t_label[uu]] = vv;
                        t_label[uu] = t_label[vv];
		   }
		   else{
		      if(vv<uu){
		        ii = uu;                      
                        while(ii != -1){
                          rl_table[ii] = vv;
                          ii = n_label[ii];
                        }                      
                        n_label[t_label[vv]] = uu;
                        t_label[vv] = t_label[uu];
		      }
		   }		                     
		 }
	      }
	      else // else2
	      {
		 c2 = I[c_h-1][c_w-1] ;
		  if (c2 != B) 
		  {
		     I[c_h][c_w] = c2;
		      if (c4 != B && c4 != c2) 
		      {				               
			 //printf("(%d,%d);\n", c2, c4); 
		  	 //(* resolve c2 c4 *)
		 	 uu = rl_table[c2]; vv = rl_table[c4];
		         if(uu<vv){
	     	            ii = vv;                      
                            while(ii != -1){
                             rl_table[ii] = uu;
                             ii = n_label[ii];
                            }                      
                            n_label[t_label[uu]] = vv;
                            t_label[uu] = t_label[vv];
		         }
		         else{
		             if(vv<uu){
		                ii = uu;                      
                                while(ii != -1){
                                   rl_table[ii] = vv;
                                   ii = n_label[ii];
                                }                      
                               n_label[t_label[vv]] = uu;
                               t_label[vv] = t_label[uu];
		             }
		         }
			 
		     }
		  }
		  else 
		    if (c4 != B) 
		    {
			I[c_h][c_w] = c4;
		    }
		    else
		    {
			I[c_h][c_w] = NewLabel;
			NewLabel=NewLabel+1;
		    }
	       }// else2
	    }// else1
	}
  } // end for COLS
  
  // SECOND SCAN
  for(c_h=0;c_h<h;c_h++)
    for(c_w=0;c_w<w;c_w++) // for COLS
        if (I[c_h][c_w] != B)
          I[c_h][c_w] = rl_table[I[c_h][c_w]];
     
   
   
//get linked lists of pixels with the same class
//i.e. pixels that belong to the same CC
 for(c_h=0;c_h<h;c_h++){
   for(c_w=0;c_w<w;c_w++){
     if (I[c_h][c_w] != B)
     {       
       push(&runs[I[c_h][c_w]], c_w,c_h);
     }
  }
 }

 //now open a file, find coords of each CC and save them
 // char *base = get_basename(argv[1]);// = "filename";  
 char *base = argv[1];
  // find location of last '.' in filename to chop extension
  char *pos = strrchr (base, '.');
  int pos1 = pos ? (pos - base ) : -1;
  
  if(pos1 != -1){
    base[pos1] = 0; // remove file extension
    //printf("%d, %s\n",pos1, base);
  }

  //I'm assuming length of filename doesn't exceed 50 chars
  //I'll deal with this later
  char filename[256];
  
  
  FILE *file;
  //fname1[strlen(fname1) - 4] = 0; // remove file extension
  
  sprintf(filename, "%s-%d.json", base, dir_num);  
  
  //printf("%s\n", filename);
  
  file = fopen(filename,"w+");
  fprintf(file,"{\n");
  fprintf(file,"  \"SrcImage\": \"\",\n"); 
  fprintf(file,"  \"Page\": %d,\n",dir_num);
  fprintf(file,"  \"PageWidth\": %d,\n", w);
  fprintf(file,"  \"PageHeight\": %d,\n",h);
  fprintf(file,"  \"ClipX\": %d,\n",0);
  fprintf(file,"  \"ClipY\": %d,\n",0);
  fprintf(file,"  \"ClipWidth\": %d,\n", w);
  fprintf(file,"  \"ClipHeight\": %d,\n",h);  
  fprintf(file,"  \"ClipImage\": \"\",\n");
  fprintf(file,"  \"glyphs\": [\n");
  
  //count++;
  //file = fopen("file.txt","w+");
  int len;
   for ( v = 0; v < (h*w/4); ++v)
     {
       len = length(runs[v]); 
       if (len > 0 ){
         //printf("run ID: %d, run length %d\n", r, len );
         struct bbox* b = find_bbox (runs[v]);
         //printf("bbox: (%d,%d),(%d,%d)\n", b->x1, b->y1, b->x2, b->y2 );   
         fprintf(file,"    { \"x\" : %d, \"y\" : %d, \"w\" : %d, \"h\" : %d }",(b->x1-1),(b->y1-1), (b->x2 - b->x1 + 1), (b->y2 - b->y1 + 1)); 
	 fprintf(file, ",\n");
         free(runs[v]);// = NULL;
         free(b);
       }
    }
    // trick by Volker to remove comma after last glyph	 
   fseek(file, -( 2*(int)sizeof(char) ), SEEK_CUR);
   fprintf(file,"\n  ]\n");
   fprintf(file,"}\n");
   // close file
   fclose(file); 
   
   //printf("Generated: %s\n",filename);
   //manually free space allocated to various arrays and matrices
     for (v = 0; v < h; ++v)
     {
       free(I[v]);    // this frees the columns
     }
     free(I);    // this frees the rows
     free(runs);
     //free(C);
     free(rl_table);
     free(n_label);
     free(t_label);
 
    TIFFClose(tif);
  }//end if tif
  } //end else 
  //STOP;
  //PRINTTIME;
     
}
예제 #17
0
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) {