Ejemplo n.º 1
0
static int check_rgba_pixel( int pixel,
			     int min_red, int max_red,
			     int min_green, int max_green,
			     int min_blue, int max_blue,
			     int min_alpha, int max_alpha,
			     uint32 *buffer ) {
	/* RGBA images are upside down - adjust for normal ordering */
	int adjusted_pixel = pixel % 128 + (127 - (pixel/128)) * 128;
	uint32 rgba = buffer[adjusted_pixel];

	if( TIFFGetR(rgba) >= (uint32) min_red &&
	    TIFFGetR(rgba) <= (uint32) max_red &&
	    TIFFGetG(rgba) >= (uint32) min_green &&
	    TIFFGetG(rgba) <= (uint32) max_green &&
	    TIFFGetB(rgba) >= (uint32) min_blue &&
	    TIFFGetB(rgba) <= (uint32) max_blue &&
	    TIFFGetA(rgba) >= (uint32) min_alpha &&
	    TIFFGetA(rgba) <= (uint32) max_alpha ) {
		return 0;
	}

	fprintf( stderr, "Pixel %d did not match expected results.\n", pixel );
	fprintf( stderr, "Got R=%d (expected %d..%d), G=%d (expected %d..%d), B=%d (expected %d..%d), A=%d (expected %d..%d)\n",
		 TIFFGetR(rgba), min_red, max_red,
		 TIFFGetG(rgba), min_green, max_green,
		 TIFFGetB(rgba), min_blue, max_blue,
		 TIFFGetA(rgba), min_alpha, max_alpha );
	return 1;
}
Ejemplo n.º 2
0
static void
cvtClump(unsigned char* op, uint32* raster, uint32 ch, uint32 cw, uint32 w)
{
	float Y, Cb = 0, Cr = 0;
	uint32 j, k;
	/*
	 * Convert ch-by-cw block of RGB
	 * to YCbCr and sample accordingly.
	 */
	for (k = 0; k < ch; k++) {
		for (j = 0; j < cw; j++) {
			uint32 RGB = (raster - k*w)[j];
			Y = lumaRed[TIFFGetR(RGB)] +
			    lumaGreen[TIFFGetG(RGB)] +
			    lumaBlue[TIFFGetB(RGB)];
			/* accumulate chrominance */
			Cb += (TIFFGetB(RGB) - Y) * D1;
			Cr += (TIFFGetR(RGB) - Y) * D2;
			/* emit luminence */
			*op++ = V2Code(Y,
			    refBlackWhite[0], refBlackWhite[1], 255);
		}
		for (; j < horizSubSampling; j++)
			*op++ = Yzero;
	}
	for (; k < vertSubSampling; k++) {
		for (j = 0; j < horizSubSampling; j++)
			*op++ = Yzero;
	}
	/* emit sampled chrominance values */
	*op++ = V2Code(Cb / (ch*cw), refBlackWhite[2], refBlackWhite[3], 127);
	*op++ = V2Code(Cr / (ch*cw), refBlackWhite[4], refBlackWhite[5], 127);
}
Ejemplo n.º 3
0
_declspec (dllexport) int readImage(TIFF* tif,              // TIFF handle - IN 
  const int directory,   // page ordinal number - IN
  uint8_t* redvals)      // OUT, caller allocates memory
{
  TIFFSetDirectory(tif, directory);
  int err = 0;
  uint32_t w, h;
  size_t npixels;

  TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
  TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
  //TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, bits);
  npixels = w * h;
  uint32_t* raster = (uint32_t*) _TIFFmalloc(npixels * sizeof (uint32_t));
  if (raster != NULL) {
    err = TIFFReadRGBAImage(tif, w, h, raster, 1);
    if (err != 1) {
      return err;
    }
    uint32_t* pFrom = raster;
    uint8_t* pTo = redvals;
    for (int i = 0; i < npixels; i++, ++pFrom) {
      *pTo++ = (uint8_t) TIFFGetR(*pFrom);
    }
  }
  _TIFFfree(raster);
  return err;
}
Ejemplo n.º 4
0
static int check_rgba_pixel( int pixel, int red, int green, int blue, int alpha, uint32 *buffer ) {
	/* RGBA images are upside down - adjust for normal ordering */
	int adjusted_pixel = pixel % 128 + (127 - (pixel/128)) * 128;
	uint32 rgba = buffer[adjusted_pixel];

	if( TIFFGetR(rgba) == (uint32) red && TIFFGetG(rgba) == (uint32) green &&
	    TIFFGetB(rgba) == (uint32) blue && TIFFGetA(rgba) == (uint32) alpha ) {
		return 0;
	}

	fprintf( stderr, "Pixel %d did not match expected results.\n", pixel );
	fprintf( stderr, "Expect: %3d %3d %3d %3d\n", red, green, blue, alpha );
	fprintf( stderr, "   Got: %3d %3d %3d %3d\n",
		 TIFFGetR(rgba), TIFFGetG(rgba), TIFFGetB(rgba), TIFFGetA(rgba) );
	return 1;
}
Ejemplo n.º 5
0
void TiffImage::transformToComplementary()
{
    if (this->imgBuffer.size() > 0) //Look if there is something in the image Buffer
    {
        vector<int> rgba;
        int newDec = 0;
        vector<uint32>::iterator vit = imgBuffer.begin();
        for (auto i : imgBuffer) //Loop over Im age Buffer
        {
            //Get RGB values
            if (i != 0)
            {
                rgba.push_back(TIFFGetR(i));
                rgba.push_back(TIFFGetG(i));
                rgba.push_back(TIFFGetB(i));
                //request complementary color
                newDec = getComplementaryColour(rgba);
                *vit = bUIntValue + newDec; //use iterator to update data in buffer
            }
            vit++; //don't forget to increase the iterator so we look at the right position
            rgba.clear(); //deletes all entries in the vector
            rgba.shrink_to_fit(); //shrinks vector to fit actual size.
        }
    }
}
Ejemplo n.º 6
0
timg_t *timg_readtiff(const char *fname) {
  
  TIFF *tif = TIFFOpen(fname, "r");
  
  uint32_t width=0, height=0;
  TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
  TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
  
  uint32_t *raster = (uint32_t*)_TIFFmalloc(width*height*sizeof(uint32_t));
  
  if(TIFFReadRGBAImage(tif, width, height, raster, 0) == 0) {
    fprintf(stderr, "An error occurred reading the TIFF file.\n");
    exit(1);
  }
  
  timg_t *img = timg_create(height, width);
  
  int i;
  for(i=0; i<height*width; ++i) {
    img->pixels[i].r = (uint8_t)TIFFGetR(raster[i]);
    img->pixels[i].g = (uint8_t)TIFFGetG(raster[i]);
    img->pixels[i].b = (uint8_t)TIFFGetB(raster[i]);
    img->pixels[i].a = (uint8_t)TIFFGetA(raster[i]);
  }

  _TIFFfree(raster);
  TIFFClose(tif);
  
  return img;
}
Ejemplo n.º 7
0
void TiffImage::readImage()
{
    TIFF *tif = TIFFOpen(this->getimageFile().c_str(), "r");
    if (tif) {
        size_t npixels;
        uint32* raster;

        TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imgWidth);
        TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imgHeight);
        TIFFGetField(tif, TIFFTAG_ORIENTATION, &imgOrientation);
        npixels = imgWidth * imgHeight; //no of pixels in image
        raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
        if (raster != NULL) {
            if (TIFFReadRGBAImage(tif, imgWidth, imgHeight, raster, 0)) {
                //...process raster data...
                //write data in vector member so we can do with it what we want

                uint32 *rasterPrint = raster;
                for(size_t n=0;n<npixels;n++)
                {
                    imgBuffer.push_back(raster[n]);
                    cout << "New Pixel R: ";
                    cout << TIFFGetR(*rasterPrint) << " G: ";
                    cout << TIFFGetG(*rasterPrint) << " B: ";
                    cout << TIFFGetB(*rasterPrint) << " A: ";
                    cout << TIFFGetA(*rasterPrint) << " uint32: ";
                    cout << *rasterPrint << endl;
                    *rasterPrint++;
                }
            }
            _TIFFfree(raster);
            //TIFFRedRGBAImage is starting in the lower left corner, so we
            //got to swap our vector. this means we hve to swap first row with last
            //and so on.
            uint32 upBufPos, downBufPos;
            for (uint32 i = 0 ; i < this->imgHeight / 2; i++)
            {
                for (uint32 j = 0 ; j < this->imgWidth; j++)
                {
                    upBufPos = i * this->imgWidth + j;
                    if (i*j == 0)
                    {
                        upBufPos = i+j;
                    }
                    downBufPos = ((this->imgHeight - i - 1) * this->imgWidth) + j;
                    swap(this->imgBuffer[upBufPos], this->imgBuffer[downBufPos]);
                }
            }
        }
        TIFFClose(tif);
    }
}
static void unpack_tiff_raster(Pic *pic, uint32 *raster)
{
    int x,y;
    uint32 pixel;
    uint32 pic_index = 0;

    for(y=(pic->ny-1); y>=0; y--)
	for(x=0; x<pic->nx; x++)
	{
	    pixel = raster[y*pic->nx + x];

	    pic->pix[pic_index++] = TIFFGetR(pixel);
	    pic->pix[pic_index++] = TIFFGetG(pixel);
	    pic->pix[pic_index++] = TIFFGetB(pixel);
	}
}
Ejemplo n.º 9
0
tdata_t tif_ReadRGBData(TIFF* tif)
{
  int* buffer = (int*)tif_Malloc(tif);
  char* raster = (char*)tif_Malloc(tif);
  printf("sizeof(raster) = %ld\n", malloc_usable_size(raster));
  printf("sizeof(buffer) = %ld\n", malloc_usable_size(buffer));

  int rgba;

  tsize_t  result;
  uint16 c = tif_nChannels(tif);
  uint32 w = tif_Width(tif);
  uint32 h = tif_Height(tif);
  uint16 ic;
  uint32 iw, ih;

  if (tif == NULL)
    return NULL;

  if (buffer != NULL) { 
    printf("Reading raster rgba: w = %d, h = %d, c = %d, tif = %p, buffer = %p, raster = %p\n", w, h, c, tif, buffer, raster);
      result = TIFFReadRGBAImage(tif, w, h, (uint32*)buffer, 0);
      printf("Result = %ld\n", result);
      if (result == 0) {
          printf("Read error on input rgba image.\n");
      }
      printf("Read ok: result = %ld\n", result);
  }
  if (raster != NULL) { 
      for(ih = 0; ih < h; ih++){
        for(iw = 0; iw < w; iw++){
          rgba = buffer[(h-ih-1)*w+iw];
          ic = 0;
          raster[macro_RasterPos2dRgb] = TIFFGetR(rgba);
          ic = 1;
          if (c >= 2) raster[macro_RasterPos2dRgb] = TIFFGetG(rgba);
          ic = 2;
          if (c >= 3) raster[macro_RasterPos2dRgb] = TIFFGetB(rgba);
          ic = 3;
          if (c >= 4) raster[macro_RasterPos2dRgb] = TIFFGetA(rgba);
        }
      }
  }

  return (tdata_t)raster;
}
static void
raster(TIFFRGBAImage_Extra * img, uint32 * rast,
       uint32 x, uint32 y, uint32 w, uint32 h)
{
   int                 image_width, image_height;
   uint32             *pixel, pixel_value;
   int                 i, j, dy, rast_offset;
   DATA32             *buffer_pixel, *buffer = evas_cache_image_pixels(img->image);
   int                 alpha_premult = 0;

   image_width = img->image->w;
   image_height = img->image->h;

   dy = h > y ? -1 : y - h;

   /* rast seems to point to the beginning of the last strip processed */
   /* so you need use negative offsets. Bizzare. Someone please check this */
   /* I don't understand why, but that seems to be what's going on. */
   /* libtiff needs better docs! */

   if (img->rgba.alpha == EXTRASAMPLE_UNASSALPHA)
     alpha_premult = 1;
   for (i = y, rast_offset = 0; i > dy; i--, rast_offset--)
     {
        pixel = rast + (rast_offset * image_width);
        buffer_pixel = buffer + ((((image_height - 1) - i) * image_width) + x);

        for (j = 0; j < w; j++)
          {
	     int a, r, g, b;

             pixel_value = (*(pixel++));
	     a = TIFFGetA(pixel_value);
	     r = TIFFGetR(pixel_value);
	     g = TIFFGetG(pixel_value);
	     b = TIFFGetB(pixel_value);
	     if (!alpha_premult && (a < 255))
	       {
		  r = (r * (a + 1)) >> 8;
		  g = (g * (a + 1)) >> 8;
		  b = (b * (a + 1)) >> 8;
	       }
             (*(buffer_pixel++)) = ARGB_JOIN(a, r, g, b);
          }
     }
Ejemplo n.º 11
0
GImage *
GImageReadTiff (char *filename)
{
  TIFF *tif;
  uint32_t w, h, i, j;
  uint32_t *ipt, *fpt;
  size_t npixels;
  uint32 *raster;
  GImage *ret = NULL;
  struct _GImage *base;

  tif = TIFFOpen (filename, "r");

  if (tif == NULL)
    return (ret);

  TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &w);
  TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &h);
  npixels = w * h;
  raster = (uint32_t *) xmalloc (szmax (1, npixels * sizeof (uint32_t)));
  if (raster != NULL)
    {
      if (TIFFReadRGBAImage (tif, w, h, raster, 0))
        {
          ret = GImageCreate (it_true, w, h);
          if (ret != NULL)
            {
              base = ret->u.image;
              for (i = 0; i < h; ++i)
                {
                  ipt = (uint32_t *) (base->data + i * base->bytes_per_line);
                  fpt = raster + (h - 1 - i) * w;
                  for (j = 0; j < w; ++j)
                    *ipt++ =
                      COLOR_CREATE (TIFFGetR (fpt[j]), TIFFGetG (fpt[j]),
                                    TIFFGetB (fpt[j]));
                }
            }
        }
      free (raster);
    }
  TIFFClose (tif);
  return (ret);
}
Ejemplo n.º 12
0
static int
TifReadImage(Tcl_Interp *interp, TIFF *tifPtr, Blt_Chain chain)
{
    int w, h, nPixels;
    uint32 *srcBits, *sp;
    Picture *destPtr;
    Blt_Pixel *destRowPtr;
    int y;

    TIFFGetField(tifPtr, TIFFTAG_IMAGEWIDTH, &w);
    TIFFGetField(tifPtr, TIFFTAG_IMAGELENGTH, &h);
    nPixels = w * h;
    srcBits = _TIFFmalloc(sizeof(uint32) * nPixels);
    if (srcBits == NULL) {
	Tcl_AppendResult(interp, "can't allocate ", Blt_Itoa(nPixels), 
		" buffer for TIF image", (char *)NULL);
	return TCL_ERROR;
    }
    if (!TIFFReadRGBAImage(tifPtr, w, h, srcBits, /*stopOnError*/0)) {
	Tcl_AppendResult(interp, "can't read image in directory", 
		(char *)NULL);
	_TIFFfree(srcBits);
	return TCL_ERROR;
    }	
    destPtr = Blt_CreatePicture(w, h);
    destRowPtr = destPtr->bits + (destPtr->pixelsPerRow * (h - 1));
    sp = srcBits;
    for (y = h - 1; y >= 0; y--) {
	Blt_Pixel *dp, *dend;

	for (dp = destRowPtr, dend = dp + w; dp < dend; dp++) {
	    dp->Red   = TIFFGetR(*sp);
	    dp->Green = TIFFGetG(*sp);
	    dp->Blue  = TIFFGetB(*sp);
	    dp->Alpha = TIFFGetA(*sp);
	    sp++;
	}
	destRowPtr -= destPtr->pixelsPerRow;
    }
    Blt_Chain_Append(chain, destPtr);
    return TCL_OK;
}
Ejemplo n.º 13
0
static void read_directory(TIFF *tif, Image *image, char *routine)   //  Used by all readers// 
{ uint32 *raster;
  uint8  *row;
  int     width, height;

  width  = image->width;
  height = image->height;
  raster = get_raster(width*height,routine);

  row = image->array;

  if (image->kind != GREY16)

    { int i, j;
      uint32 *in;
      uint8  *out;

      if (TIFFReadRGBAImage(tif,width,height,raster,0) == 0)
        error("read of tif failed in read_directory()", NULL);

      in = raster;
      if (image->kind == GREY)
        { for (j = height-1; j >= 0; j--)
            { out = row;
              for (i = 0; i < width; i++)
                { uint32 pixel = *in++;
                  *out++ = TIFFGetR(pixel);
                }
              row += width;
            }
        }
      else
        { for (j = height-1; j >= 0; j--)
            { out = row;
              for (i = 0; i < width; i++)
                { uint32 pixel = *in++;
                  *out++ = TIFFGetR(pixel);
                  *out++ = TIFFGetG(pixel);
                  *out++ = TIFFGetB(pixel);
                }
              row += width*3;
            }
        }
    }

  else

    { int tile_width, tile_height;

      if (TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width))    // File is tiled  
        { int x, y;
          int i, j;
          int m, n;
          uint16 *buffer = (uint16 *) raster;
          uint16 *out, *in, *rous;
    
          TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height);

          for (y = 0; y < height; y += tile_height)
            { if (y + tile_height > height)
                n = height - y;
              else
                n = tile_height;
              for (x = 0; x < width; x += tile_width)
                { TIFFReadTile(tif, buffer, x, y, 0, 0);
                  if (x + tile_width > width)
                    m = width - x;
                  else
                    m = tile_width;
                  for (j = 0; j < n; j++)
                    { out = (uint16 *) (row + 2*(j*width + x));
                      in  = buffer + j*tile_width;
                      for (i = 0; i < m; i++)
                        *out++ = *in++; 
                    }
                }
              row += n*width*2;
            }
        }

      else    // File is striped
   
        { int     y;

          for (y = 0; y < height; y++)
            { TIFFReadScanline(tif, row, y, 0);
              row += width*2;
            }
        }
    }
}
Ejemplo n.º 14
0
bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int index )
{
    if (index == -1)
        index = 0;

    image->Destroy();

    TIFF *tif = TIFFwxOpen( stream, "image", "r" );

    if (!tif)
    {
        if (verbose)
            wxLogError( _("TIFF: Error loading image.") );

        return false;
    }

    if (!TIFFSetDirectory( tif, (tdir_t)index ))
    {
        if (verbose)
            wxLogError( _("Invalid TIFF image index.") );

        TIFFClose( tif );

        return false;
    }

    uint32 w, h;
    uint32 *raster;

    TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &w );
    TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &h );

    uint16 extraSamples;
    uint16* samplesInfo;
    TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
                          &extraSamples, &samplesInfo);
    const bool hasAlpha = (extraSamples == 1 &&
                           (samplesInfo[0] == EXTRASAMPLE_ASSOCALPHA ||
                            samplesInfo[0] == EXTRASAMPLE_UNASSALPHA));

    // guard against integer overflow during multiplication which could result
    // in allocating a too small buffer and then overflowing it
    const double bytesNeeded = (double)w * (double)h * sizeof(uint32);
    if ( bytesNeeded >= 4294967295U /* UINT32_MAX */ )
    {
        if ( verbose )
            wxLogError( _("TIFF: Image size is abnormally big.") );

        TIFFClose(tif);

        return false;
    }

    raster = (uint32*) _TIFFmalloc( bytesNeeded );

    if (!raster)
    {
        if (verbose)
            wxLogError( _("TIFF: Couldn't allocate memory.") );

        TIFFClose( tif );

        return false;
    }

    image->Create( (int)w, (int)h );
    if (!image->Ok())
    {
        if (verbose)
            wxLogError( _("TIFF: Couldn't allocate memory.") );

        _TIFFfree( raster );
        TIFFClose( tif );

        return false;
    }

    if ( hasAlpha )
        image->SetAlpha();

    if (!TIFFReadRGBAImage( tif, w, h, raster, 0 ))
    {
        if (verbose)
            wxLogError( _("TIFF: Error reading image.") );

        _TIFFfree( raster );
        image->Destroy();
        TIFFClose( tif );

        return false;
    }

    unsigned char *ptr = image->GetData();
    ptr += w*3*(h-1);

    unsigned char *alpha = hasAlpha ? image->GetAlpha() : NULL;
    if ( hasAlpha )
        alpha += w*(h-1);

    uint32 pos = 0;

    for (uint32 i = 0; i < h; i++)
    {
        for (uint32 j = 0; j < w; j++)
        {
            *(ptr++) = (unsigned char)TIFFGetR(raster[pos]);
            *(ptr++) = (unsigned char)TIFFGetG(raster[pos]);
            *(ptr++) = (unsigned char)TIFFGetB(raster[pos]);
            if ( hasAlpha )
                *(alpha++) = (unsigned char)TIFFGetA(raster[pos]);

            pos++;
        }

        // subtract line we just added plus one line:
        ptr -= 2*w*3;
        if ( hasAlpha )
            alpha -= 2*w;
    }

    _TIFFfree( raster );

    TIFFClose( tif );

    return true;
}
Ejemplo n.º 15
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) {
Ejemplo n.º 16
0
GthImage *
_cairo_image_surface_create_from_tiff (GInputStream  *istream,
				       GthFileData   *file_data,
				       int            requested_size,
				       int           *original_width_p,
				       int           *original_height_p,
				       gboolean      *loaded_original_p,
				       gpointer       user_data,
				       GCancellable  *cancellable,
				       GError       **error)
{
	GthImage		*image;
	Handle			 handle;
	TIFF			*tif;
	gboolean		 first_directory;
	int			 best_directory;
	int        		 max_width, max_height, min_diff;
	uint32			 image_width;
	uint32			 image_height;
	uint32			 spp;
	uint16			 extrasamples;
	uint16			*sampleinfo;
	uint16			 orientation;
	char			 emsg[1024];
	cairo_surface_t		*surface;
	cairo_surface_metadata_t*metadata;
	uint32			*raster;

	image = gth_image_new ();
	handle.cancellable = cancellable;
	handle.size = 0;

	if ((file_data != NULL) && (file_data->info != NULL)) {
		handle.istream = g_buffered_input_stream_new (istream);
		handle.size = g_file_info_get_size (file_data->info);
	}
	else {
		void  *data;
		gsize  size;

		/* read the whole stream to get the file size */

		if (! _g_input_stream_read_all (istream, &data, &size, cancellable, error))
			return image;
		handle.istream = g_memory_input_stream_new_from_data (data, size, g_free);
		handle.size = size;
	}


	TIFFSetErrorHandler (tiff_error_handler);
	TIFFSetWarningHandler (tiff_error_handler);

	tif = TIFFClientOpen ("gth-tiff-reader", "r",
			      &handle,
	                      tiff_read,
	                      tiff_write,
	                      tiff_seek,
	                      tiff_close,
	                      tiff_size,
	                      NULL,
	                      NULL);

	if (tif == NULL) {
		g_object_unref (handle.istream);
		g_set_error_literal (error,
				     GDK_PIXBUF_ERROR,
				     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
				     "Couldn't allocate memory for writing TIFF file");
		return image;
	}

	/* find the best image to load */

	first_directory = TRUE;
	best_directory = -1;
	max_width = -1;
	max_height = -1;
	min_diff = 0;
	do {
		int width;
		int height;

		if (TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &width) != 1)
			continue;
		if (TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &height) != 1)
			continue;

		if (! TIFFRGBAImageOK (tif, emsg))
			continue;

		if (width > max_width) {
			max_width = width;
			max_height = height;
			if (requested_size <= 0)
				best_directory = TIFFCurrentDirectory (tif);
		}

		if (requested_size > 0) {
			int diff = abs (requested_size - width);

			if (first_directory) {
				min_diff = diff;
				best_directory = TIFFCurrentDirectory (tif);
			}
			else if (diff < min_diff) {
				min_diff = diff;
				best_directory = TIFFCurrentDirectory (tif);
			}
		}

		first_directory = FALSE;
	}
	while (TIFFReadDirectory (tif));

	if (best_directory == -1) {
		TIFFClose (tif);
		g_object_unref (handle.istream);
		g_set_error_literal (error,
				     G_IO_ERROR,
				     G_IO_ERROR_INVALID_DATA,
				     "Invalid TIFF format");
		return image;
	}

	/* read the image */

	TIFFSetDirectory (tif, best_directory);
	TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &image_width);
	TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &image_height);
	TIFFGetField (tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
	TIFFGetFieldDefaulted (tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo);
	if (TIFFGetFieldDefaulted (tif, TIFFTAG_ORIENTATION, &orientation) != 1)
		orientation = ORIENTATION_TOPLEFT;

	if (original_width_p)
		*original_width_p = max_width;
	if (original_height_p)
		*original_height_p = max_height;
	if (loaded_original_p)
		*loaded_original_p = (max_width == image_width);

	surface = _cairo_image_surface_create (CAIRO_FORMAT_ARGB32, image_width, image_height);
	if (surface == NULL) {
		TIFFClose (tif);
		g_object_unref (handle.istream);
		g_set_error_literal (error,
				     GDK_PIXBUF_ERROR,
				     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
				     "Couldn't allocate memory for writing TIFF file");
		return image;
	}

	metadata = _cairo_image_surface_get_metadata (surface);
	_cairo_metadata_set_has_alpha (metadata, (extrasamples == 1) || (spp == 4));
	_cairo_metadata_set_original_size (metadata, max_width, max_height);

	raster = (uint32*) _TIFFmalloc (image_width * image_height * sizeof (uint32));
	if (raster == NULL) {
		cairo_surface_destroy (surface);
		TIFFClose (tif);
		g_object_unref (handle.istream);
		g_set_error_literal (error,
				     GDK_PIXBUF_ERROR,
				     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
				     "Couldn't allocate memory for writing TIFF file");
		return image;
	}

	if (TIFFReadRGBAImageOriented (tif, image_width, image_height, raster, orientation, 0)) {
		guchar *surface_row;
		int     line_step;
		int     x, y, temp;
		guchar  r, g, b, a;
		uint32 *src_pixel;

		surface_row = _cairo_image_surface_flush_and_get_data (surface);
		line_step = cairo_image_surface_get_stride (surface);
		src_pixel = raster;
		for (y = 0; y < image_height; y++) {
			guchar *dest_pixel = surface_row;

			if (g_cancellable_is_cancelled (cancellable))
				goto stop_loading;

			for (x = 0; x < image_width; x++) {
				r = TIFFGetR (*src_pixel);
				g = TIFFGetG (*src_pixel);
				b = TIFFGetB (*src_pixel);
				a = TIFFGetA (*src_pixel);
				CAIRO_SET_RGBA (dest_pixel, r, g, b, a);

				dest_pixel += 4;
				src_pixel += 1;
			}

			surface_row += line_step;
		}
	}

stop_loading:

	cairo_surface_mark_dirty (surface);
	if (! g_cancellable_is_cancelled (cancellable))
		gth_image_set_cairo_surface (image, surface);

	_TIFFfree (raster);
	cairo_surface_destroy (surface);
	TIFFClose (tif);
	g_object_unref (handle.istream);

	return image;
}
Ejemplo n.º 17
0
HANDLE TIFFRGBA2DIB(TIFFDibImage* dib, uint32* raster)
{
    void*   pDIB = 0;
    TIFFRGBAImage* img = &dib->tif;

    uint32 imageLength;
    uint32 imageWidth;
    uint16 BitsPerSample;
    uint16 SamplePerPixel;
    uint32 RowsPerStrip;
    uint16 PhotometricInterpretation;

    BITMAPINFOHEADER   bi;
    int                dwDIBSize ;

    TIFFGetField(img->tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
    TIFFGetField(img->tif, TIFFTAG_IMAGELENGTH, &imageLength);
    TIFFGetField(img->tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample);
    TIFFGetField(img->tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip);
    TIFFGetField(img->tif, TIFFTAG_SAMPLESPERPIXEL, &SamplePerPixel);
    TIFFGetField(img->tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation);

    if ( BitsPerSample == 1 && SamplePerPixel == 1 && dib->dibinstalled ) {   // bilevel
        bi.biSize           = sizeof(BITMAPINFOHEADER);
        bi.biWidth          = imageWidth;
        bi.biHeight         = imageLength;
        bi.biPlanes         = 1;  // always
        bi.biBitCount       = 1;
        bi.biCompression    = BI_RGB;
        bi.biSizeImage      = WIDTHBYTES(bi.biWidth * bi.biBitCount) * bi.biHeight;
        bi.biXPelsPerMeter  = 0;
        bi.biYPelsPerMeter  = 0;
        bi.biClrUsed        = 0;  //  must be zero for RGB compression (none)
        bi.biClrImportant   = 0;  // always

        // Get the size of the DIB
        dwDIBSize = GetDIBSize( &bi );

        // Allocate for the BITMAPINFO structure and the color table.
        pDIB = GlobalAllocPtr( GHND, dwDIBSize );
        if (pDIB == 0) {
            return( NULL );
        }

        // Copy the header info
        *((BITMAPINFOHEADER*)pDIB) = bi;

        // Get a pointer to the color table
        RGBQUAD   *pRgbq = (RGBQUAD   *)((LPSTR)pDIB + sizeof(BITMAPINFOHEADER));

        pRgbq[0].rgbRed      = 0;
        pRgbq[0].rgbBlue     = 0;
        pRgbq[0].rgbGreen    = 0;
        pRgbq[0].rgbReserved = 0;
        pRgbq[1].rgbRed      = 255;
        pRgbq[1].rgbBlue     = 255;
        pRgbq[1].rgbGreen    = 255;
        pRgbq[1].rgbReserved = 255;

        // Pointers to the bits
        //PVOID pbiBits = (LPSTR)pRgbq + bi.biClrUsed * sizeof(RGBQUAD);
        //
        // In the BITMAPINFOHEADER documentation, it appears that
        // there should be no color table for 32 bit images, but
        // experience shows that the image is off by 3 words if it
        // is not included.  So here it is.
        PVOID pbiBits = GetDIBImagePtr((BITMAPINFOHEADER*)pDIB);  //(LPSTR)pRgbq + 3 * sizeof(RGBQUAD);

        int       sizeWords = bi.biSizeImage/4;
        RGBQUAD*  rgbDib = (RGBQUAD*)pbiBits;
        long*     rgbTif = (long*)raster;

        _TIFFmemcpy(pbiBits, raster, bi.biSizeImage);
    }

        //  For now just always default to the RGB 32 bit form.                                                       // save as 32 bit for simplicity
    else if ( true /*BitsPerSample == 8 && SamplePerPixel == 3*/ ) {   // 24 bit color

        bi.biSize           = sizeof(BITMAPINFOHEADER);
        bi.biWidth          = imageWidth;
        bi.biHeight         = imageLength;
        bi.biPlanes         = 1;  // always
        bi.biBitCount       = 32;
        bi.biCompression    = BI_RGB;
        bi.biSizeImage      = WIDTHBYTES(bi.biWidth * bi.biBitCount) * bi.biHeight;
        bi.biXPelsPerMeter  = 0;
        bi.biYPelsPerMeter  = 0;
        bi.biClrUsed        = 0;  //  must be zero for RGB compression (none)
        bi.biClrImportant   = 0;  // always

        // Get the size of the DIB
        dwDIBSize = GetDIBSize( &bi );

        // Allocate for the BITMAPINFO structure and the color table.
        pDIB = GlobalAllocPtr( GHND, dwDIBSize );
        if (pDIB == 0) {
            return( NULL );
        }

        // Copy the header info
        *((BITMAPINFOHEADER*)pDIB) = bi;

        // Get a pointer to the color table
        RGBQUAD   *pRgbq = (RGBQUAD   *)((LPSTR)pDIB + sizeof(BITMAPINFOHEADER));

        // Pointers to the bits
        //PVOID pbiBits = (LPSTR)pRgbq + bi.biClrUsed * sizeof(RGBQUAD);
        //
        // In the BITMAPINFOHEADER documentation, it appears that
        // there should be no color table for 32 bit images, but
        // experience shows that the image is off by 3 words if it
        // is not included.  So here it is.
        PVOID pbiBits = (LPSTR)pRgbq + 3 * sizeof(RGBQUAD);

        int       sizeWords = bi.biSizeImage/4;
        RGBQUAD*  rgbDib = (RGBQUAD*)pbiBits;
        long*     rgbTif = (long*)raster;

        // Swap the byte order while copying
        for ( int i = 0 ; i < sizeWords ; ++i )
        {
            rgbDib[i].rgbRed   = TIFFGetR(rgbTif[i]);
            rgbDib[i].rgbBlue  = TIFFGetB(rgbTif[i]);
            rgbDib[i].rgbGreen = TIFFGetG(rgbTif[i]);
            rgbDib[i].rgbReserved = 0;
        }
    }

    return pDIB;
}
Ejemplo n.º 18
0
bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int index )
{
    if (index == -1)
        index = 0;

    image->Destroy();

    TIFF *tif = TIFFwxOpen( stream, "image", "r" );

    if (!tif)
    {
        if (verbose)
            wxLogError( _("TIFF: Error loading image.") );

        return false;
    }

    if (!TIFFSetDirectory( tif, (tdir_t)index ))
    {
        if (verbose)
            wxLogError( _("Invalid TIFF image index.") );

        TIFFClose( tif );

        return false;
    }

    uint32 w, h;
    uint32 npixels;
    uint32 *raster;

    TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &w );
    TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &h );

    npixels = w * h;

    raster = (uint32*) _TIFFmalloc( npixels * sizeof(uint32) );

    if (!raster)
    {
        if (verbose)
            wxLogError( _("TIFF: Couldn't allocate memory.") );

        TIFFClose( tif );

        return false;
    }

    image->Create( (int)w, (int)h );
    if (!image->Ok())
    {
        if (verbose)
            wxLogError( _("TIFF: Couldn't allocate memory.") );

        _TIFFfree( raster );
        TIFFClose( tif );

        return false;
    }

    if (!TIFFReadRGBAImage( tif, w, h, raster, 0 ))
    {
        if (verbose)
            wxLogError( _("TIFF: Error reading image.") );

        _TIFFfree( raster );
        image->Destroy();
        TIFFClose( tif );

        return false;
    }

    bool hasmask = false;

    unsigned char *ptr = image->GetData();
    ptr += w*3*(h-1);
    uint32 pos = 0;

    for (uint32 i = 0; i < h; i++)
    {
        for (uint32 j = 0; j < w; j++)
        {
            unsigned char alpha = (unsigned char)TIFFGetA(raster[pos]);
            if (alpha < 127)
            {
                hasmask = true;
                ptr[0] = image->GetMaskRed();
                ptr++;
                ptr[0] = image->GetMaskGreen();
                ptr++;
                ptr[0] = image->GetMaskBlue();
                ptr++;
            }
            else
            {
                ptr[0] = (unsigned char)TIFFGetR(raster[pos]);
                ptr++;
                ptr[0] = (unsigned char)TIFFGetG(raster[pos]);
                ptr++;
                ptr[0] = (unsigned char)TIFFGetB(raster[pos]);
                ptr++;
            }
            pos++;
        }
        ptr -= 2*w*3; // subtract line we just added plus one line
    }

    _TIFFfree( raster );

    TIFFClose( tif );

    image->SetMask( hasmask );

    return true;
}
Ejemplo n.º 19
0
static GdkPixbuf *
tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error)
{
	guchar *pixels = NULL;
	gint width, height, rowstride, bytes;
	GdkPixbuf *pixbuf;
	guint16 bits_per_sample = 0;
	uint16 orientation = 0;
	uint16 transform = 0;
        uint16 codec;
        gchar *icc_profile_base64;
        const gchar *icc_profile;
        guint icc_profile_size;
        uint16 resolution_unit;
        gchar *density_str;
        gint retval;

        /* We're called with the lock held. */

	if (!TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width)) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_FAILED,
                                     _("Could not get image width (bad TIFF file)"));
                return NULL;
        }
        
        if (!TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height)) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_FAILED,
                                     _("Could not get image height (bad TIFF file)"));
                return NULL;
        }

        if (width <= 0 || height <= 0) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("Width or height of TIFF image is zero"));
                return NULL;                
        }
        
        rowstride = width * 4;
        if (rowstride / 4 != width) { /* overflow */
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("Dimensions of TIFF image too large"));
                return NULL;                
        }
        
        bytes = height * rowstride;
        if (bytes / rowstride != height) { /* overflow */
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
                                     _("Dimensions of TIFF image too large"));
                return NULL;                
        }

	if (context && context->size_func) {
                gint w = width;
                gint h = height;
		(* context->size_func) (&w, &h, context->user_data);
                
		/* This is a signal that this function is being called
		   to support gdk_pixbuf_get_file_info, so we can stop
		   parsing the tiff file at this point. It is not an
		   error condition. */

                if (w == 0 || h == 0)
                    return NULL;
        }

        pixels = g_try_malloc (bytes);

        if (!pixels) {
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     _("Insufficient memory to open TIFF file"));
                return NULL;
        }

	pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, 
                                           width, height, rowstride,
                                           free_buffer, NULL);
        if (!pixbuf) {
                g_free (pixels);
                g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
                                     _("Insufficient memory to open TIFF file"));
                return NULL;
        }

        /* Save the bits per sample as an option since pixbufs are
           expected to be always 8 bits per sample. */
        TIFFGetField (tiff, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
        if (bits_per_sample > 0) {
                gchar str[5];
                g_snprintf (str, sizeof (str), "%d", bits_per_sample);
                gdk_pixbuf_set_option (pixbuf, "bits-per-sample", str);
        }

	/* Set the "orientation" key associated with this image. libtiff 
	   orientation handling is odd, so further processing is required
	   by higher-level functions based on this tag. If the embedded
	   orientation tag is 1-4, libtiff flips/mirrors the image as
	   required, and no client processing is required - so we report 
	   no orientation. Orientations 5-8 require rotations which would 
	   swap the width and height of the image. libtiff does not do this. 
	   Instead it interprets orientations 5-8 the same as 1-4. 
	   See http://bugzilla.remotesensing.org/show_bug.cgi?id=1548.
	   To correct for this, the client must apply the transform normally
	   used for orientation 5 to both orientations 5 and 7, and apply
	   the transform normally used for orientation 7 for both
	   orientations 6 and 8. Then everythings works out OK! */
	
	TIFFGetField (tiff, TIFFTAG_ORIENTATION, &orientation);

	switch (orientation) {
		case 5:
		case 7:
			transform = 5;
			break;
		case 6:
		case 8:
			transform = 7;
			break;
		default:
			transform = 0;
			break;
	}

	if (transform > 0 ) {
		gchar str[5];
		g_snprintf (str, sizeof (str), "%d", transform);
		gdk_pixbuf_set_option (pixbuf, "orientation", str);
	}

        TIFFGetField (tiff, TIFFTAG_COMPRESSION, &codec);
        if (codec > 0) {
          gchar str[5];
          g_snprintf (str, sizeof (str), "%d", codec);
          gdk_pixbuf_set_option (pixbuf, "compression", str);
        }

        /* Extract embedded ICC profile */
        retval = TIFFGetField (tiff, TIFFTAG_ICCPROFILE, &icc_profile_size, &icc_profile);
        if (retval == 1) {
                icc_profile_base64 = g_base64_encode ((const guchar *) icc_profile, icc_profile_size);
                gdk_pixbuf_set_option (pixbuf, "icc-profile", icc_profile_base64);
                g_free (icc_profile_base64);
        }

        retval = TIFFGetField (tiff, TIFFTAG_RESOLUTIONUNIT, &resolution_unit);
        if (retval == 1) {
                float x_resolution = 0, y_resolution = 0;

                TIFFGetField (tiff, TIFFTAG_XRESOLUTION, &x_resolution);
                TIFFGetField (tiff, TIFFTAG_YRESOLUTION, &y_resolution);

                switch (resolution_unit) {
                case RESUNIT_INCH:
                        density_str = g_strdup_printf ("%d", (int) round (x_resolution));
                        gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
                        g_free (density_str);
                        density_str = g_strdup_printf ("%d", (int) round (y_resolution));
                        gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
                        g_free (density_str);
                        break;
                case RESUNIT_CENTIMETER:
                        density_str = g_strdup_printf ("%d", DPCM_TO_DPI (x_resolution));
                        gdk_pixbuf_set_option (pixbuf, "x-dpi", density_str);
                        g_free (density_str);
                        density_str = g_strdup_printf ("%d", DPCM_TO_DPI (y_resolution));
                        gdk_pixbuf_set_option (pixbuf, "y-dpi", density_str);
                        g_free (density_str);
                        break;
                }
        }

	if (context && context->prepare_func)
		(* context->prepare_func) (pixbuf, NULL, context->user_data);

	if (!TIFFReadRGBAImageOriented (tiff, width, height, (uint32 *)pixels, ORIENTATION_TOPLEFT, 1)) {
		g_set_error_literal (error,
                                     GDK_PIXBUF_ERROR,
                                     GDK_PIXBUF_ERROR_FAILED,
                                     _("Failed to load RGB data from TIFF file"));
		g_object_unref (pixbuf);
		return NULL;
	}

	/* Flag multi-page documents, because this loader only handles the
	   first page. The client app may wish to warn the user. */
        if (TIFFReadDirectory (tiff))
                gdk_pixbuf_set_option (pixbuf, "multipage", "yes");

#if G_BYTE_ORDER == G_BIG_ENDIAN
	/* Turns out that the packing used by TIFFRGBAImage depends on 
         * the host byte order... 
         */ 
	while (pixels < pixbuf->pixels + bytes) {
		uint32 pixel = *(uint32 *)pixels;
		int r = TIFFGetR(pixel);
		int g = TIFFGetG(pixel);
		int b = TIFFGetB(pixel);
		int a = TIFFGetA(pixel);
		*pixels++ = r;
		*pixels++ = g;
		*pixels++ = b;
		*pixels++ = a;
	}
#endif

	if (context && context->update_func)
		(* context->update_func) (pixbuf, 0, 0, width, height, context->user_data);

        return pixbuf;
}
Ejemplo n.º 20
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;
					}
				}
Ejemplo n.º 21
0
BOOL CImageTIFF::Read(FILE* stream)
{
	TIFF* m_tif = TIFFOpenEx(stream, "rb");

	uint32 height=0;
	uint32 width=0;
	uint16 bitspersample=1;
	uint16 samplesperpixel=1;
	uint32 rowsperstrip=-1;
	uint16 photometric=0;
	uint16 compression=1;
	uint32 x, y;
	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";

	m_info.nNumFrames=0;
	while(TIFFSetDirectory(m_tif,(uint16)m_info.nNumFrames)) m_info.nNumFrames++;


	if (!TIFFSetDirectory(m_tif, (uint16)m_info.nFrame))
		throw "Error: page not present in TIFF file";			

	//get image m_info
	TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression);
	if (compression == COMPRESSION_LZW)
		throw "LZW compression is no longer supported due to Unisys patent enforcement";			

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

	m_header.biWidth  = width;
	m_header.biHeight = height;
	m_header.biClrUsed=0;
	m_info.nBkgndIndex =-1;

	isRGB = (bitspersample >= 8) &&
		(photometric == PHOTOMETRIC_RGB) ||
		(photometric == PHOTOMETRIC_YCBCR) ||
		(photometric == PHOTOMETRIC_SEPARATED) ||
		(photometric == PHOTOMETRIC_LOGLUV);

	if (isRGB){
		m_header.biBitCount=24;
		m_info.bColorType = COLORTYPE_COLOR;
	}else{
		m_info.bColorType = COLORTYPE_PALETTE;
		if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE)){
			if	(bitspersample == 1){
				m_header.biBitCount=1;		//B&W image
				m_header.biClrUsed =2;
			} else {
				m_header.biBitCount=8;		//gray scale
				m_header.biClrUsed =256;
			}
		} else if (bitspersample == 4) {
			m_header.biBitCount=4;			// 16 colors
			m_header.biClrUsed=16;
		} else {
			m_header.biBitCount=8;			//256 colors
			m_header.biClrUsed=256;
		}
	}

	Create(m_header.biWidth,m_header.biHeight,m_header.biBitCount);	//image creation

	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 = m_info.pImage;
		for (y = 0; y < height; y++) {
			bits = bits2;
			for (x = 0; x < width; x++) {
				*bits++ = (BYTE)TIFFGetB(row[x]);
				*bits++ = (BYTE)TIFFGetG(row[x]);
				*bits++ = (BYTE)TIFFGetR(row[x]);
			}
			row += width;
			bits2 += m_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 (int i = 0; i < 256; i++) {
							pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = i;
						}
					} else {
						for (int i = 0; i < 256; i++) {
							pal[i].rgbRed =	pal[i].rgbGreen = pal[i].rgbBlue = 255 - i;
						}
					}
				}
				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,m_header.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);
//		int pitch = CalculatePitch(line);
		long bitsize= TIFFStripSize(m_tif);
		bits = (BYTE*)malloc(bitsize);

		for (ys = 0; ys < height; ys += rowsperstrip) {
			nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip);
			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++) {
				memcpy(m_info.pImage+m_info.dwEffWidth*(height-ys-nrow+y),bits+(nrow-y-1)*line,line);
			}
			/*if (m_header.biClrUsed==2){
				for (y = 0; y < nrow; y++) { for (x = 0; x < width; x++) {
					SetPixelIndex(x,y+ys,(bits[y*line+(x>>3)]>>(7-x%8))&0x01);
			}}}*/
		}
		free(bits);
	}
  } catch (char *message) {
	  strncpy(m_info.szLastError,message,255);
	  if (m_tif)	TIFFClose(m_tif);
	  return FALSE;
  }
	TIFFClose(m_tif);
	return TRUE;
}
Ejemplo n.º 22
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;
}
Ejemplo n.º 23
0
unsigned char      *
loader_tiff(FILE *f, char *file, int *w, int *h, int *t)
{
  TIFF               *tif;
  unsigned char      *data, *ptr, r, g, b, a;
  int                 x, y;
  uint32              ww, hh, *rast, *tptr;
  size_t              npix;
  int                 istransp;
  int                 fd;

  istransp = 0;
  if (!f)
    return NULL;

  fd = fileno(f);
  /* Apparently rewind(f) isn't sufficient */
  lseek(fd, (long) 0, 0);  
  /* So why does libtif need a filename here ??? */
  tif = TIFFFdOpen(fd, file, "r");

  if (!tif)
    return NULL;

  TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &ww);
  TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &hh);
  npix = ww * hh;
  *w = (int)ww;
  *h = (int)hh;
  if(ww > 32767 || hh > 32767)
    {
      TIFFClose(tif);
      return NULL;
    }
  rast = (uint32 *) _TIFFmalloc(npix * sizeof(uint32));
  if (!rast)
    {
      TIFFClose(tif);
      return NULL;
    }
  data = NULL;
  if (TIFFReadRGBAImage(tif, ww, hh, rast, 0))
    {
      data = (unsigned char *)malloc(*w ** h * 3);
      if (!data)
	{
	  _TIFFfree(rast);
	  TIFFClose(tif);
	  return NULL;
	}
      ptr = data;
      for (y = 0; y < *h; y++)
	{
	  tptr = rast;
	  tptr += ((*h - y - 1) ** w);
	  for (x = 0; x < *w; x++)
	    {
	      a = TIFFGetA(*tptr);
	      b = TIFFGetB(*tptr);
	      g = TIFFGetG(*tptr);
	      r = TIFFGetR(*tptr);
	      tptr++;
	      if (a < 128)
		{
		  *ptr++ = 255;
		  *ptr++ = 0;
		  *ptr++ = 255;
		  istransp = 1;
		}
	      else
		{
		  if ((r == 255) && (g == 0) && (b == 255))
		    r = 254;
		  *ptr++ = r;
		  *ptr++ = g;
		  *ptr++ = b;
		}
	    }
	}
    }
  _TIFFfree(rast);
  TIFFClose(tif);
  *t = istransp;
  return data;
}
Ejemplo n.º 24
0
ImageIO::errorType ImageIO::loadTIFF(const char * filename)
{
#ifdef ENABLE_TIFF
  TIFF * tiff = TIFFOpen(filename, "r");
  if (!tiff)
    return IO_ERROR;

  // read the dimensions
  uint32 tiff_width, tiff_height;
  uint16 tiff_samplesPerPixel;
  uint16 tiff_bits;
  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &tiff_width);
  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &tiff_height);
  TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &tiff_samplesPerPixel);
  TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &tiff_bits);

  //printf("tiff_width: %d tiff_height: %d tiff_samplesPerPixel: %d tiff_bits: %d\n", tiff_width, tiff_height, tiff_samplesPerPixel, tiff_bits);

  if ((tiff_samplesPerPixel != IMAGE_IO_RGB) && (tiff_samplesPerPixel != IMAGE_IO_RGB_ALPHA))
  {
    printf("Error in loadTIFF: Sorry, cannot handle %d-channel images.\n", tiff_samplesPerPixel);
    TIFFClose(tiff);
    return OTHER_ERROR;
  }

  if (tiff_bits != BITS_PER_CHANNEL_8)
  {
    printf("Error in loadTIFF: Sorry, cannot handle %d-bit images.\n", tiff_bits);
    TIFFClose(tiff);
    return OTHER_ERROR;
  }

  width = tiff_width;
  height = tiff_height;
  bytesPerPixel = tiff_samplesPerPixel;

  uint32 * tiff_pixels = (uint32*) _TIFFmalloc(tiff_width * tiff_height * sizeof(uint32));
  if (!tiff_pixels)
  {
    TIFFClose(tiff);
    return MEMORY_ERROR;
  }

  printf("Loading TIFF image from file %s: resolution: %d x %d, %d-bit.\n", filename, width, height, 8 * bytesPerPixel);
 
  int stopOnError = 1;
  if (!TIFFReadRGBAImage(tiff, tiff_width, tiff_height, tiff_pixels, stopOnError))
  { 
    _TIFFfree(tiff_pixels);
    TIFFClose(tiff);
    printf("Error in loadTIFF: Unknown error when calling TIFFReadRGBAImage.\n");
    return IO_ERROR;
  }

  pixels = (unsigned char*) malloc (sizeof(unsigned char) * width * height * bytesPerPixel);

  // write tiff_pixels into the pixels array
  int counter = 0;
  for(unsigned int row=0; row < height; row++)
  {
    for(unsigned int column=0; column < width; column++)
    {
      // read the uint32 pixel
      uint32 tiff_pixel = tiff_pixels[row * tiff_width + column];

      // write R,G,B,A in place into pixels
      pixels[counter] = TIFFGetR(tiff_pixel);
      counter++;

      if (bytesPerPixel < 3) 
        continue;

      pixels[counter] = TIFFGetG(tiff_pixel);
      counter++;
      pixels[counter] = TIFFGetB(tiff_pixel);
      counter++;

      if (bytesPerPixel < 4) 
        continue;

      // alpha channel
      pixels[counter] = TIFFGetA(tiff_pixel);
      counter++;
    }
  }

  _TIFFfree(tiff_pixels);
  TIFFClose(tiff);

  return OK;

#else
  return INVALID_FILE_FORMAT;
#endif
}
Ejemplo n.º 25
0
void TifReader::readLine(char *buffer, int x0, int x1, int shrink)
{
	if (this->m_info.m_bitsPerSample == 16 && this->m_info.m_samplePerPixel >= 3) {
		std::vector<short> app(4 * (m_info.m_lx));
		readLine(&app[0], x0, x1, shrink);

		TPixel64 *pixin = (TPixel64 *)&app[0];

		TPixel32 *pixout = (TPixel32 *)buffer;
		for (int j = 0; j < x0; j++) {
			pixout++;
			pixin++;
		}

		for (int i = 0; i < (x1 - x0) + 1; i++)
			*pixout++ = PixelConverter<TPixel32>::from(*pixin++);

		return;
	}

	assert(shrink > 0);

	const int pixelSize = 4;
	int stripRowSize = m_rowLength * pixelSize;

	if (m_row < m_info.m_y0 || m_row > m_info.m_y1) {
		memset(buffer, 0, (x1 - x0 + 1) * pixelSize);
		m_row++;
		return;
	}

	int stripIndex = m_row / m_rowsPerStrip;
	if (m_stripIndex != stripIndex) {
		m_stripIndex = stripIndex;

		if (TIFFIsTiled(m_tiff)) {
			uint32 tileWidth = 0, tileHeight = 0;
			TIFFGetField(m_tiff, TIFFTAG_TILEWIDTH, &tileWidth);
			TIFFGetField(m_tiff, TIFFTAG_TILELENGTH, &tileHeight);
			assert(tileWidth > 0 && tileHeight > 0);

			int tileSize = tileWidth * tileHeight;
			std::unique_ptr<uint32[]> tile(new uint32[tileSize]);

			int x = 0;
			int y = tileHeight * m_stripIndex;

			int lastTy = std::min((int)tileHeight, m_info.m_ly - y);

			while (x < m_info.m_lx) {
				int ret = TIFFReadRGBATile(m_tiff, x, y, tile.get());
				assert(ret);

				int tileRowSize = std::min((int)tileWidth, (int)(m_info.m_lx - x)) * pixelSize;

				for (int ty = 0; ty < lastTy; ++ty) {
					memcpy(
						m_stripBuffer + (ty * m_rowLength + x) * pixelSize,
						(UCHAR *)tile.get() + ty * tileWidth * pixelSize,
						tileRowSize);
				}

				x += tileWidth;
			}
		} else {
			int y = m_rowsPerStrip * m_stripIndex;
			int ok = TIFFReadRGBAStrip(m_tiff, y, (uint32 *)m_stripBuffer);
			assert(ok);
		}
	}

	uint16 orient = ORIENTATION_TOPLEFT;
	TIFFGetField(m_tiff, TIFFTAG_ORIENTATION, &orient);

	int r = m_rowsPerStrip - 1 - (m_row % m_rowsPerStrip);
	switch (orient) // Pretty weak check for top/bottom orientation
	{
	case ORIENTATION_TOPLEFT:
	case ORIENTATION_TOPRIGHT:
	case ORIENTATION_LEFTTOP:
	case ORIENTATION_RIGHTTOP:
		// We have to invert the fixed BOTTOM-UP returned by TIFF functions - since this function is
		// supposed to ignore orientation issues (which are managed outside).

		// The last tiles row will actually start at the END OF THE IMAGE (not necessarily at
		// m_rowsPerStrip multiples). So, we must adjust for that.

		r = std::min(m_rowsPerStrip, m_info.m_ly - m_rowsPerStrip * m_stripIndex) - 1 -
			(m_row % m_rowsPerStrip);
		break;

	case ORIENTATION_BOTRIGHT:
	case ORIENTATION_BOTLEFT:
	case ORIENTATION_RIGHTBOT:
	case ORIENTATION_LEFTBOT:
		r = m_row % m_rowsPerStrip;
		break;
	}

	TPixel32 *pix = (TPixel32 *)buffer;
	uint32 *v = (uint32 *)(m_stripBuffer + r * stripRowSize);

	pix += x0;
	v += x0;

	int width = (x1 < x0) ? (m_info.m_lx - 1) / shrink + 1 : (x1 - x0) / shrink + 1;

	for (int i = 0; i < width; i++) {
		uint32 c = *v;
		pix->r = (UCHAR)TIFFGetR(c);
		pix->g = (UCHAR)TIFFGetG(c);
		pix->b = (UCHAR)TIFFGetB(c);
		pix->m = (UCHAR)TIFFGetA(c);

		v += shrink;
		pix += shrink;
	}

	m_row++;
}
Ejemplo n.º 26
0
Image *Read (IStream *file, const Image::ReadOptions& options)
{
    int                   nrow;
    int                   result = 0;
    long                  LineSize;
    TIFF                  *tif;
    Image                 *image ;
    uint16                BitsPerSample;
    uint16                BytesPerSample = 1;
    uint16                PhotometricInterpretation;
    uint16                SamplePerPixel;
    uint16                Orientation;
    uint32                RowsPerStrip;
    unsigned int          width;
    unsigned int          height;

    // TODO - TIFF files probably have some gamma info in them by default, but we're currently ignorant about that.
    // Until that is fixed, use whatever the user has chosen as default.
    GammaCurvePtr gamma;
    if (options.gammacorrect && options.defaultGamma)
        gamma = TranscodingGammaCurve::Get(options.workingGamma, options.defaultGamma);

    // [CLi] TIFF is specified to use associated (= premultiplied) alpha, so that's the preferred mode to use for the image container unless the user overrides
    // (e.g. to handle a non-compliant file).
    bool premul = true;
    if (options.premultiplyOverride)
        premul = options.premultiply;

    // Rather than have libTIFF complain about tags it doesn't understand,
    // we just suppress all the warnings.
    TIFFSetWarningHandler(SuppressTIFFWarnings);
    TIFFSetErrorHandler(SuppressTIFFWarnings);

    // Open and do initial processing
    tif = TIFFClientOpen("Dummy File Name", "r", file,
        Tiff_Read, Tiff_Write, Tiff_Seek, Tiff_Close,
        Tiff_Size, Tiff_Map, Tiff_Unmap);
    if (!tif)
        return (NULL) ;

    // Get basic information about the image
    int ExtraSamples, ExtraSampleInfo;
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
    TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample);
    TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip);
    TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation);
    TIFFGetField(tif, TIFFTAG_ORIENTATION, &Orientation);
    TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &SamplePerPixel);
    TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &ExtraSamples, &ExtraSampleInfo);

    // don't support more than 16 bits per sample
    if (BitsPerSample == 16)
    {
        BytesPerSample = 2 ;
        options.warnings.push_back ("Warning: reading 16 bits/sample TIFF file; components crunched to 8");
    }

    LineSize = TIFFScanlineSize(tif);
    assert (SamplePerPixel == (int) (LineSize / width) / BytesPerSample);
    // SamplePerPixel = (int)(LineSize / width);

#if 0
    // For now we are ignoring the orientation of the image...
    switch (Orientation)
    {
    case ORIENTATION_TOPLEFT:
        break;
    case ORIENTATION_TOPRIGHT:
        break;
    case ORIENTATION_BOTRIGHT:
        break;
    case ORIENTATION_BOTLEFT:
        break;
    case ORIENTATION_LEFTTOP:
        break;
    case ORIENTATION_RIGHTTOP:
        break;
    case ORIENTATION_RIGHTBOT:
        break;
    case ORIENTATION_LEFTBOT:
        break;
    default:
        break;
    }
#endif

    //PhotometricInterpretation = 2 image is RGB
    //PhotometricInterpretation = 3 image have a color palette
    if (PhotometricInterpretation == PHOTOMETRIC_PALETTE && (TIFFIsTiled(tif) == 0))
    {
        uint16 *red, *green, *blue;

        //load the palette
        int cmap_len = (1 << BitsPerSample);

        TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue);

        vector<Image::RGBMapEntry> colormap ;
        Image::RGBMapEntry entry;

        // I may be mistaken, but it appears that alpha/opacity information doesn't
        // appear in a Paletted Tiff image.  Well - if it does, it's not as easy to
        // get at as RGB.
        // Read the palette
        // Is the palette 16 or 8 bits ?
        if (checkcmap(cmap_len, red, green, blue) == 16)
        {
            for (int i=0;i<cmap_len;i++)
            {
                entry.red   = IntDecode(gamma, red[i],   65535);
                entry.green = IntDecode(gamma, green[i], 65535);
                entry.blue  = IntDecode(gamma, blue[i],  65535);
                colormap.push_back (entry);
            }
        }
        else
        {
            for (int i=0;i<cmap_len;i++)
            {
                entry.red   = IntDecode(gamma, red[i],   255);
                entry.green = IntDecode(gamma, green[i], 255);
                entry.blue  = IntDecode(gamma, blue[i],  255);
                colormap.push_back (entry);
            }
        }

        Image::ImageDataType imagetype = options.itype;
        if (imagetype == Image::Undefined)
            imagetype = Image::Colour_Map;
        image = Image::Create (width, height, imagetype, colormap) ;
        image->SetPremultiplied(premul); // specify whether the color map data has premultiplied alpha

        boost::scoped_array<unsigned char> buf (new unsigned char [TIFFStripSize(tif)]);

        //read the tiff lines and save them in the image
        //with RGB mode, we have to change the order of the 3 samples RGB <=> BGR
        for (int row=0;row<height;row+=RowsPerStrip)
        {
            nrow = (row + (int)RowsPerStrip > height ? height - row : RowsPerStrip);
            TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0), buf.get(), nrow * LineSize);
            for (int l = 0, offset = 0; l < nrow ; l++, offset += LineSize)
                for (int x = 0 ; x < width ; x++)
                    image->SetIndexedValue (x, row+l, buf[offset+x]) ;
        }
    }
    else
    {
        // Allocate the row buffers for the image
        boost::scoped_array<uint32> buf (new uint32 [width * height]) ;

        Image::ImageDataType imagetype = options.itype;
        if (imagetype == Image::Undefined)
            imagetype = ( GammaCurve::IsNeutral(gamma) ? Image::RGBA_Int8 : Image::RGBA_Gamma8 );
        image = Image::Create (width, height, imagetype) ;
        image->SetPremultiplied(premul); // set desired storage mode regarding alpha premultiplication
        image->TryDeferDecoding(gamma, 255); // try to have gamma adjustment being deferred until image evaluation.

        TIFFReadRGBAImage(tif, width, height, buf.get(), 0);
        uint32 abgr, *tbuf = buf.get();
        for (int i=height-1;i>=0;i--)
        {
            for (int j=0;j<width;j++)
            {
                abgr = *tbuf++;
                unsigned int b = (unsigned char)TIFFGetB(abgr);
                unsigned int g = (unsigned char)TIFFGetG(abgr);
                unsigned int r = (unsigned char)TIFFGetR(abgr);
                unsigned int a = (unsigned char)TIFFGetA(abgr);
                SetEncodedRGBAValue(image, j, i, gamma, 255, r, g, b, a, premul) ;
            }
        }
    }

    TIFFClose(tif);

    return (image) ;
}
Ejemplo n.º 27
0
 /**
  * Retrieves the red component of the given pixel.
  *
  * @param pixel Representation of a LibTIFF pixel value
  *
  * @return The red component
  */
 int TiffImporter::getRed(int pixel) const {
   return TIFFGetR(pixel);
 }
Ejemplo n.º 28
0
bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbose, int index )
{
    if (index == -1)
        index = 0;

    image->Destroy();

    TIFF *tif = TIFFwxOpen( stream, "image", "r" );

    if (!tif)
    {
        if (verbose)
        {
            wxLogError( _("TIFF: Error loading image.") );
        }

        return false;
    }

    if (!TIFFSetDirectory( tif, (tdir_t)index ))
    {
        if (verbose)
        {
            wxLogError( _("Invalid TIFF image index.") );
        }

        TIFFClose( tif );

        return false;
    }

    uint32 w, h;
    uint32 *raster;

    TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &w );
    TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &h );

    uint16 extraSamples;
    uint16* samplesInfo;
    TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
                          &extraSamples, &samplesInfo);
    const bool hasAlpha = (extraSamples == 1 &&
                           (samplesInfo[0] == EXTRASAMPLE_ASSOCALPHA ||
                            samplesInfo[0] == EXTRASAMPLE_UNASSALPHA));

    // guard against integer overflow during multiplication which could result
    // in allocating a too small buffer and then overflowing it
    const double bytesNeeded = (double)w * (double)h * sizeof(uint32);
    if ( bytesNeeded >= wxUINT32_MAX )
    {
        if ( verbose )
        {
            wxLogError( _("TIFF: Image size is abnormally big.") );
        }

        TIFFClose(tif);

        return false;
    }

    raster = (uint32*) _TIFFmalloc( (uint32)bytesNeeded );

    if (!raster)
    {
        if (verbose)
        {
            wxLogError( _("TIFF: Couldn't allocate memory.") );
        }

        TIFFClose( tif );

        return false;
    }

    image->Create( (int)w, (int)h );
    if (!image->Ok())
    {
        if (verbose)
        {
            wxLogError( _("TIFF: Couldn't allocate memory.") );
        }

        _TIFFfree( raster );
        TIFFClose( tif );

        return false;
    }

    if ( hasAlpha )
        image->SetAlpha();

    if (!TIFFReadRGBAImage( tif, w, h, raster, 0 ))
    {
        if (verbose)
        {
            wxLogError( _("TIFF: Error reading image.") );
        }

        _TIFFfree( raster );
        image->Destroy();
        TIFFClose( tif );

        return false;
    }

    unsigned char *ptr = image->GetData();
    ptr += w*3*(h-1);

    unsigned char *alpha = hasAlpha ? image->GetAlpha() : NULL;
    if ( hasAlpha )
        alpha += w*(h-1);

    uint32 pos = 0;

    for (uint32 i = 0; i < h; i++)
    {
        for (uint32 j = 0; j < w; j++)
        {
            *(ptr++) = (unsigned char)TIFFGetR(raster[pos]);
            *(ptr++) = (unsigned char)TIFFGetG(raster[pos]);
            *(ptr++) = (unsigned char)TIFFGetB(raster[pos]);
            if ( hasAlpha )
                *(alpha++) = (unsigned char)TIFFGetA(raster[pos]);

            pos++;
        }

        // subtract line we just added plus one line:
        ptr -= 2*w*3;
        if ( hasAlpha )
            alpha -= 2*w;
    }

    // set the image resolution if it's available
    uint16 tiffRes;
    if ( TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &tiffRes) )
    {
        wxImageResolution res;
        switch ( tiffRes )
        {
            default:
                wxLogWarning(_("Unknown TIFF resolution unit %d ignored"),
                             tiffRes);
                // fall through

            case RESUNIT_NONE:
                res = wxIMAGE_RESOLUTION_NONE;
                break;

            case RESUNIT_INCH:
                res = wxIMAGE_RESOLUTION_INCHES;
                break;

            case RESUNIT_CENTIMETER:
                res = wxIMAGE_RESOLUTION_CM;
                break;
        }

        if ( res != wxIMAGE_RESOLUTION_NONE )
        {
            float xres, yres;
            if ( TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) )
                image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, wxRound(xres));

            if ( TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) )
                image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, wxRound(yres));
        }
    }


    _TIFFfree( raster );

    TIFFClose( tif );

    return true;
}
Ejemplo n.º 29
0
main(int argc, char* argv[])
{
  TIFF* tif;
  uint8 r,g,b,a,i,bpp;
  FILE *rgbf;
  char rgbfile[50];

  if (argc!=2 && argc!=3) {
    printf("Usage: %s [-32] filename.tiff\n",argv[0]);
    exit(1);
  }

  if (argc==2) bpp=16; else bpp=32;

  tif = TIFFOpen(argv[1], "r");
  if (tif) {
    uint32 w, h, pixel,rgba32_pixel;
    uint16 rgba16_pixel;
    size_t npixels;
    uint32* raster;
    int n;
    
    strcpy(rgbfile,argv[1]);
    strcpy((char*)strrchr(rgbfile,'.'),".rgb");
    rgbf=fopen(rgbfile,"wb");
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
    npixels = w * h;
    raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
    if (raster != NULL) {
      if (TIFFReadRGBAImage(tif,w,h,raster,0)) {
	int mw,mh;
	// save rgb data to file
	fputc((w>>8)&0xFF,rgbf); fputc(w&0xFF,rgbf); // u16 w,h header
	fputc((h>>8)&0xFF,rgbf); fputc(h&0xFF,rgbf);
	for (n=0; n<4; n++) fputc(0x0,rgbf); // alignment
	for (mh=h-1; mh>=0; mh--)
	  for (mw=0; mw<w; mw++) 
	    {
	      pixel=raster[w*mh+mw];
	      r=TIFFGetR(pixel);
	      g=TIFFGetG(pixel);
	      b=TIFFGetB(pixel);
	      a=TIFFGetA(pixel);
	      if (bpp==16)
		{
		  rgba16_pixel=PACK_RGBA5551(r,g,b,a);
	      // use white as the mask
	      // if (r==0xff && g==0xff && b==0xff) a|=1; else a&=~(uint16)1;
	      // if (a==0xcff) rgba16_pixel|=1; else rgba16_pixel&=~(uint16)1;
		  fputc((rgba16_pixel>>8)&0xFF,rgbf);
		  fputc(rgba16_pixel&0xFF,rgbf);
		}
	      else
		{
		  // rgba32_pixel=PACK_RGBA8888(r,g,b,a);
		  fputc(r,rgbf);
		  fputc(g,rgbf);
		  fputc(b,rgbf);
		  fputc(a,rgbf);
		}
	    }
      }