KDint xmGetDecodeTIFF ( KDFile* file, XMImage* image ) { TIFFInfo* info = (TIFFInfo*) image->info; TIFFDecode* decode = 0; image->decode = kdCalloc ( 1, sizeof ( TIFFDecode ) ); decode = (TIFFDecode*) image->decode; if ( !decode ) { return -1; } decode->pixels = (KDuint32*) _TIFFmalloc ( image->width * image->height * sizeof (KDuint32) ); if ( !decode->pixels ) { return -1; } if ( !TIFFReadRGBAImageOriented ( info->tiff, image->width, image->height, decode->pixels , ORIENTATION_TOPLEFT, 0 ) ) { return -1; } return 0; }
int ReadTIFF(const char* const filename, WebPPicture* const pic, int keep_alpha, Metadata* const metadata) { TIFF* const tif = TIFFOpen(filename, "r"); uint32 width, height; uint32* raster; int ok = 0; tdir_t dircount; if (tif == NULL) { fprintf(stderr, "Error! Cannot open TIFF file '%s'\n", filename); return 0; } dircount = TIFFNumberOfDirectories(tif); if (dircount > 1) { fprintf(stderr, "Warning: multi-directory TIFF files are not supported.\n" "Only the first will be used, %d will be ignored.\n", dircount - 1); } if (!(TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width) && TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height))) { fprintf(stderr, "Error! Cannot retrieve TIFF image dimensions.\n"); return 0; } raster = (uint32*)_TIFFmalloc(width * height * sizeof(*raster)); if (raster != NULL) { if (TIFFReadRGBAImageOriented(tif, width, height, raster, ORIENTATION_TOPLEFT, 1)) { const int stride = width * sizeof(*raster); pic->width = width; pic->height = height; // TIFF data is ABGR #ifdef WORDS_BIGENDIAN TIFFSwabArrayOfLong(raster, width * height); #endif ok = keep_alpha ? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride) : WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride); } _TIFFfree(raster); } else { fprintf(stderr, "Error allocating TIFF RGBA memory!\n"); } if (ok) { if (metadata != NULL) { ok = ExtractMetadataFromTIFF(tif, metadata); if (!ok) { fprintf(stderr, "Error extracting TIFF metadata!\n"); MetadataFree(metadata); WebPPictureFree(pic); } } } TIFFClose(tif); return ok; }
int main(int, char **) { tdata_t buffer = _TIFFmalloc(128); _TIFFfree(buffer); // some libtiff implementations where TIFF_VERSION >= 42 do not // have TIFFReadRGBAImageOriented(), so let's check for it TIFFReadRGBAImageOriented(0, 0, 0, 0, 0, 0); return 0; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int TiffUtilities::readTiffAsGrayScale(TIFF* in, TiffImage* data) { unsigned char* raster; /* retrieve RGBA image */ int32_t pixel_count; unsigned char* src = static_cast<unsigned char*>(NULL); unsigned char* dst = static_cast<unsigned char*>(NULL); tsize_t totalBytes; unsigned char r, g, b; float R,G,B; // This will eventually be TOO much data but we need it to read the initial data totalBytes = data->width * data->height * 4; raster = (unsigned char*)_TIFFmalloc( totalBytes ); if (raster == NULL) { TIFFError(TIFFFileName(in), "No space for raster buffer"); return 0; } // TIFFReadRGBAImageOriented converts non 8bit images including: // Grayscale, bilevel, CMYK, and YCbCR transparently into 32bit RGBA // samples /* Read the image in one chunk into an RGBA array */ if (!TIFFReadRGBAImageOriented(in, (data->width), (data->height), (unsigned int*)(raster), ORIENTATION_TOPLEFT, 0)) { _TIFFfree(raster); return 0; } // Collapse the data down to a single channel, that will end up // being the grayscale values pixel_count = (data->height) * (data->width); // The collapse is done IN PLACE src = raster; dst = raster; while (pixel_count > 0) { PIXEL24_TO_GREYVALUE(src, *(dst)); dst++; src += 4; //skip ahead by 4 bytes because we read the raw array into an RGBA array. pixel_count--; } (void) TIFFClose(in); // Close the tiff structures data->imageData = raster; return 1; }
void HILL_read_tiff( HILL_input_stream i, struct HILL_image_data *img ){ TIFF *t; uint32_t width=0; uint32_t height=0; uint32_t bytes=0; TIFFSetErrorHandler(read_tiff_error_handler); TIFFSetWarningHandler(read_tiff_error_handler); t=TIFFClientOpen( "Memory", "r", (thandle_t)i, read_tiff_read, read_tiff_write, read_tiff_seek, read_tiff_close, read_tiff_size, NULL, NULL ); if(t==NULL) { img->err=HILL_IMAGE_LIBRARY_ERROR; return; } TIFFGetField(t, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(t, TIFFTAG_IMAGELENGTH, &height); bytes=width*height*sizeof(uint32_t); img->w=width; img->h=height; img->fmt=HILL_RGBA8; img->data=malloc(bytes); if(TIFFReadRGBAImageOriented(t, width, height, (uint32_t *)img->data, ORIENTATION_TOPLEFT, 1) != 0) { img->err=HILL_IMAGE_NO_ERROR; TIFFClose(t); } else { img->err=HILL_IMAGE_NOT_SUPPORTED; free(img->data); TIFFClose(t); } }
int ReadTIFF(const char* const filename, WebPPicture* const pic, int keep_alpha) { TIFF* const tif = TIFFOpen(filename, "r"); uint32 width, height; uint32* raster; int ok = 0; int dircount = 1; if (tif == NULL) { fprintf(stderr, "Error! Cannot open TIFF file '%s'\n", filename); return 0; } while (TIFFReadDirectory(tif)) ++dircount; if (dircount > 1) { fprintf(stderr, "Warning: multi-directory TIFF files are not supported.\n" "Only the first will be used, %d will be ignored.\n", dircount - 1); } TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); raster = (uint32*)_TIFFmalloc(width * height * sizeof(*raster)); if (raster != NULL) { if (TIFFReadRGBAImageOriented(tif, width, height, raster, ORIENTATION_TOPLEFT, 1)) { const int stride = width * sizeof(*raster); pic->width = width; pic->height = height; // TIFF data is ABGR #ifdef __BIG_ENDIAN__ TIFFSwabArrayOfLong(raster, width * height); #endif ok = keep_alpha ? WebPPictureImportRGBA(pic, (const uint8_t*)raster, stride) : WebPPictureImportRGBX(pic, (const uint8_t*)raster, stride); } _TIFFfree(raster); } else { fprintf(stderr, "Error allocating TIFF RGBA memory!\n"); } if (ok && keep_alpha == 2) { WebPCleanupTransparentArea(pic); } TIFFClose(tif); return ok; }
int ReadTiff(const char * filename, std::vector<unsigned char> * ptr, int * w, int * h, int * depth) { TIFF* tiff = TIFFOpen(filename, "r"); if (!tiff) { std::cerr << "Error: Couldn't open " << filename << " fopen returned 0"; return 0; } uint16 bps, spp; TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, w); TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, h); TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bps); TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &spp); *depth = bps * spp / 8; ptr->resize((*h)*(*w)*(*depth)); if (*depth==4) { if (ptr != nullptr) { if (!TIFFReadRGBAImageOriented(tiff, *w, *h, (uint32*)&((*ptr)[0]), ORIENTATION_TOPLEFT, 0)) { TIFFClose(tiff); return 0; } } } else { for (size_t i=0; i<TIFFNumberOfStrips(tiff); ++i) { if (TIFFReadEncodedStrip(tiff, i, ((uint8*)&((*ptr)[0]))+i*TIFFStripSize(tiff),(tsize_t)-1) == std::numeric_limits<tsize_t>::max()) { TIFFClose(tiff); return 0; } } } TIFFClose(tiff); return 1; }
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; }
static int cvt_whole_image( TIFF *in, TIFF *out ) { uint32* raster; /* retrieve RGBA image */ uint32 width, height; /* image width & height */ uint32 row; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32)); if (raster == 0) { TIFFError(TIFFFileName(in), "No space for raster buffer"); return (0); } /* Read the image in one chunk into an RGBA array */ if (!TIFFReadRGBAImageOriented(in, width, height, raster, ORIENTATION_TOPLEFT, 0)) { _TIFFfree(raster); return (0); } /* ** Do we want to strip away alpha components? */ if( no_alpha ) { int pixel_count = width * height; unsigned char *src, *dst; src = (unsigned char *) raster; dst = (unsigned char *) raster; while( pixel_count > 0 ) { *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); src++; pixel_count--; } } /* Write out the result in strips */ for( row = 0; row < height; row += rowsperstrip ) { unsigned char * raster_strip; int rows_to_write; int bytes_per_pixel; if( no_alpha ) { raster_strip = ((unsigned char *) raster) + 3 * row * width; bytes_per_pixel = 3; } else { raster_strip = (unsigned char *) (raster + row * width); bytes_per_pixel = 4; } if( row + rowsperstrip > height ) rows_to_write = height - row; else rows_to_write = rowsperstrip; if( TIFFWriteEncodedStrip( out, row / rowsperstrip, raster_strip, bytes_per_pixel * rows_to_write * width ) == -1 ) { _TIFFfree( raster ); return 0; } } _TIFFfree( raster ); return 1; }
static int cvt_whole_image( TIFF *in, TIFF *out ) { uint32* raster; /* retrieve RGBA image */ uint32 width, height; /* image width & height */ uint32 row; size_t pixel_count; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); pixel_count = width * height; /* XXX: Check the integer overflow. */ if (!width || !height || pixel_count / width != height) { TIFFError(TIFFFileName(in), "Malformed input file; can't allocate buffer for raster of %lux%lu size", (unsigned long)width, (unsigned long)height); return 0; } rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); raster = (uint32*)_TIFFCheckMalloc(in, pixel_count, sizeof(uint32), "raster buffer"); if (raster == 0) { TIFFError(TIFFFileName(in), "Failed to allocate buffer (%lu elements of %lu each)", (unsigned long)pixel_count, (unsigned long)sizeof(uint32)); return (0); } /* Read the image in one chunk into an RGBA array */ if (!TIFFReadRGBAImageOriented(in, width, height, raster, ORIENTATION_TOPLEFT, 0)) { _TIFFfree(raster); return (0); } /* * XXX: raster array has 4-byte unsigned integer type, that is why * we should rearrange it here. */ #if HOST_BIGENDIAN TIFFSwabArrayOfLong(raster, width * height); #endif /* * Do we want to strip away alpha components? */ if (no_alpha) { size_t count = pixel_count; unsigned char *src, *dst; src = dst = (unsigned char *) raster; while (count > 0) { *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); src++; count--; } } /* * Write out the result in strips */ for (row = 0; row < height; row += rowsperstrip) { unsigned char * raster_strip; int rows_to_write; int bytes_per_pixel; if (no_alpha) { raster_strip = ((unsigned char *) raster) + 3 * row * width; bytes_per_pixel = 3; } else { raster_strip = (unsigned char *) (raster + row * width); bytes_per_pixel = 4; } if( row + rowsperstrip > height ) rows_to_write = height - row; else rows_to_write = rowsperstrip; if( TIFFWriteEncodedStrip( out, row / rowsperstrip, raster_strip, bytes_per_pixel * rows_to_write * width ) == -1 ) { _TIFFfree( raster ); return 0; } } _TIFFfree( raster ); return 1; }
void WCTextureManager::LoadTexture(WSTexture *texObj) { //Set the warning handler TIFFSetWarningHandler(_TIFFWarning); //Create the image from file std::string filename = _ResourceDirectory() + "\\" + texObj->_name + ".tiff"; TIFF *tif; try { tif = TIFFOpen(filename.c_str(), "r"); } catch (...) { CLOGGER_ERROR(WCLogManager::RootLogger(), "WCTextureManager::LoadTexture - Caught an exception."); } if (tif == NULL){ CLOGGER_ERROR(WCLogManager::RootLogger(), "WCTextureManager::LoadTexture - Not able to load: " << texObj->_name); return; } //Read the tif image data into a buffer char emsg[1024]; TIFFRGBAImage img; TIFFRGBAImageBegin(&img, tif, 1, emsg); if(WCAdapter::HasGL15()) { texObj->_texture_width = img.width; texObj->_texture_height = img.height; } else { // use pow(2, n) for texture width and height for(texObj->_texture_width = 1; texObj->_texture_width < (GLint)img.width; texObj->_texture_width *= 2){} for(texObj->_texture_height = 1; texObj->_texture_height < (GLint)img.height; texObj->_texture_height *= 2){} } //Get all of the raster data size_t npixels = texObj->_texture_width * texObj->_texture_height; uint32 *data = new uint32[npixels]; TIFFReadRGBAImageOriented(tif, texObj->_texture_width, texObj->_texture_height, data, ORIENTATION_TOPLEFT, 0); TIFFRGBAImageEnd(&img); //Enable texturing glEnable(texObj->_target); //Generate a new texture glGenTextures (1, &(texObj->_id)); glBindTexture (texObj->_target, texObj->_id); //Set the min/mag filters glTexParameteri(texObj->_target, GL_TEXTURE_MIN_FILTER, texObj->_minFilter); glTexParameteri(texObj->_target, GL_TEXTURE_MAG_FILTER, texObj->_magFilter); glTexParameteri(texObj->_target, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(texObj->_target, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(texObj->_target, 0, 4, texObj->_texture_width, texObj->_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); //Clean up glDisable(texObj->_target); //Check for errors GLenum err = glGetError(); if (err != GL_NO_ERROR) { CLOGGER_ERROR(WCLogManager::RootLogger(), "WCTextureManager::LoadTexture - At clean up on image: " << texObj->_name); } //Get the object width and height texObj->_width = (GLfloat)img.width; texObj->_height = (GLfloat)img.height; //Clean up delete data; }
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; }