예제 #1
0
파일: tiffgt.c 프로젝트: basecq/magic-txd
static void
raster_special(int key, int x, int y)
{
        (void) x;
        (void) y;
        switch (key) {
                case GLUT_KEY_PAGE_UP:          /* previous logical image */
                    if (TIFFCurrentDirectory(tif) > 0) {
                            if (TIFFSetDirectory(tif,
                                                 TIFFCurrentDirectory(tif)-1)) {
                                    initImage();
                                    setWindowSize();
                        }
                    } else {
                            TIFFRGBAImageEnd(&img);
                            prevImage();
                            initImage();
                            setWindowSize();
                    }
                break;
                case GLUT_KEY_PAGE_DOWN:        /* next logical image */
                    if (!TIFFLastDirectory(tif)) {
                            if (TIFFReadDirectory(tif)) {
                                    initImage();
                                    setWindowSize();
                            }
                    } else {
                            TIFFRGBAImageEnd(&img);
                            nextImage();
                            initImage();
                            setWindowSize();
                    }
                break;
                case GLUT_KEY_HOME:             /* 1st image in current file */
                        if (TIFFSetDirectory(tif, 0)) {
                                TIFFRGBAImageEnd(&img);
                                initImage();
                                setWindowSize();
                        }
                break;
                case GLUT_KEY_END:              /* last image in current file */
                        TIFFRGBAImageEnd(&img);
                        while (!TIFFLastDirectory(tif))
                                TIFFReadDirectory(tif);
                        initImage();
                        setWindowSize();
                break;
        }
        glutPostRedisplay();
}
예제 #2
0
tdir_t tif_DirCount(TIFF* tif)
{
    tdir_t dirCurrent = TIFFCurrentDirectory(tif);
    int dirCount = 0;
    TIFFSetDirectory(tif, 0);
    do{
      dirCount++;
    }
    while(TIFFReadDirectory(tif));
    TIFFSetDirectory(tif, dirCurrent);
    return dirCount;
}
예제 #3
0
static void
raster_reshape(int win_w, int win_h)
{
	GLfloat xratio = (GLfloat)win_w/img.width;
	GLfloat yratio = (GLfloat)win_h/img.height;
	int	ratio = (int)(((xratio > yratio)?xratio:yratio) * 100);

	glPixelZoom(xratio, yratio);
	glViewport(0, 0, win_w, win_h);
	snprintf(title, 1024, "%s [%u] %d%%", filelist[fileindex],
		(unsigned int) TIFFCurrentDirectory(tif), ratio);
	glutSetWindowTitle(title);
}
예제 #4
0
int
main(int argc, char* argv[])
{
	int c;
	int dirnum = -1;
	uint32 diroff = 0;

	oerror = TIFFSetErrorHandler(NULL);
	owarning = TIFFSetWarningHandler(NULL);
	while ((c = getopt(argc, argv, "d:o:p:eflmsvw?")) != -1)
	    switch (c) {
	    case 'd':
		dirnum = atoi(optarg);
		break;
	    case 'e':
		oerror = TIFFSetErrorHandler(oerror);
		break;
	    case 'l':
		order0 = FILLORDER_LSB2MSB;
		break;
	    case 'm':
		order0 = FILLORDER_MSB2LSB;
		break;
	    case 'o':
		diroff = strtoul(optarg, NULL, 0);
		break;
	    case 'p':
		photo0 = photoArg(optarg);
		break;
	    case 's':
		stoponerr = 1;
		break;
	    case 'w':
		owarning = TIFFSetWarningHandler(owarning);
		break;
	    case 'v':
		verbose = 1;
		break;
	    case '?':
		usage();
		/*NOTREACHED*/
	    }
	filenum = argc - optind;
	if ( filenum < 1)
	        usage();

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

	/*
	 * Get the screen size
	 */
	xmax = glutGet(GLUT_SCREEN_WIDTH);
	ymax = glutGet(GLUT_SCREEN_HEIGHT);

	/*
	 * Use 90% of the screen size
	 */
	xmax = xmax - xmax / 10.0;
	ymax = ymax - ymax / 10.0;

        filelist = (char **) _TIFFmalloc(filenum * sizeof(char*));
        if (!filelist) {
                TIFFError(argv[0], "Can not allocate space for the file list.");
                return 1;
        }
        _TIFFmemcpy(filelist, argv + optind, filenum * sizeof(char*));
	fileindex = -1;
	if (nextImage() < 0) {
		_TIFFfree(filelist);
		return 2;
	}
	/*
	 * Set initial directory if user-specified
	 * file was opened successfully.
	 */
	if (dirnum != -1 && !TIFFSetDirectory(tif, dirnum))
	    TIFFError(argv[0], "Error, seeking to directory %d", dirnum);
	if (diroff != 0 && !TIFFSetSubDirectory(tif, diroff))
	    TIFFError(argv[0], "Error, setting subdirectory at %#x", diroff);
	order = order0;
	photo = photo0;
	initImage();
	/*
	 * Create a new window or reconfigure an existing
	 * one to suit the image to be displayed.
	 */
	glutInitWindowSize(width, height);
	snprintf(title, 1024, "%s [%u]", filelist[fileindex],
		(unsigned int) TIFFCurrentDirectory(tif));
	glutCreateWindow(title);
	glutDisplayFunc(raster_draw);
	glutReshapeFunc(raster_reshape);
	glutKeyboardFunc(raster_keys);
	glutSpecialFunc(raster_special);
	glutMainLoop();

	cleanup_and_exit();
        return 0;
}
예제 #5
0
bool _openslide_try_ventana(openslide_t *osr,
                            struct _openslide_tiffcache *tc,
                            TIFF *tiff,
                            struct _openslide_hash *quickhash1,
                            GError **err) {
  GPtrArray *level_array = g_ptr_array_new();

  // parse iScan XML
  char *xml = read_xml_packet(tiff);
  if (!xml) {
    g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED,
                "Not a Ventana slide");
    goto FAIL;
  }
  if (!parse_initial_xml(osr, xml, err)) {
    g_free(xml);
    goto FAIL;
  }
  g_free(xml);

  // okay, assume Ventana slide

  // walk directories
  do {
    tdir_t dir = TIFFCurrentDirectory(tiff);

    // read ImageDescription
    char *image_desc;
    if (!TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &image_desc)) {
      continue;
    }

    if (strstr(image_desc, LEVEL_DESCRIPTION_TOKEN)) {
      // is a level

      // confirm that this directory is tiled
      if (!TIFFIsTiled(tiff)) {
        g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                    "Directory %d is not tiled", dir);
        goto FAIL;
      }

      // verify that we can read this compression (hard fail if not)
      uint16_t compression;
      if (!TIFFGetField(tiff, TIFFTAG_COMPRESSION, &compression)) {
        g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                    "Can't read compression scheme");
        goto FAIL;
      };
      if (!TIFFIsCODECConfigured(compression)) {
        g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                    "Unsupported TIFF compression: %u", compression);
        goto FAIL;
      }

      // create level
      struct level *l = g_slice_new0(struct level);
      struct _openslide_tiff_level *tiffl = &l->tiffl;
      if (!_openslide_tiff_level_init(tiff, dir,
                                      (struct _openslide_level *) l,
                                      tiffl,
                                      err)) {
        g_slice_free(struct level, l);
        goto FAIL;
      }
      l->grid = _openslide_grid_create_simple(osr,
                                              tiffl->tiles_across,
                                              tiffl->tiles_down,
                                              tiffl->tile_w,
                                              tiffl->tile_h,
                                              read_tile);

      // add to array
      g_ptr_array_add(level_array, l);

    } else if (!strcmp(image_desc, MACRO_DESCRIPTION)) {
      // macro image
      if (!_openslide_tiff_add_associated_image(osr, "macro", tc, dir,
                                                err)) {
	g_prefix_error(err, "Can't read macro image: ");
	goto FAIL;
      }

    } else if (!strcmp(image_desc, THUMBNAIL_DESCRIPTION)) {
      // thumbnail image
      if (!_openslide_tiff_add_associated_image(osr, "thumbnail", tc, dir,
                                                err)) {
	g_prefix_error(err, "Can't read thumbnail image: ");
	goto FAIL;
      }
    }
  } while (TIFFReadDirectory(tiff));
bool _openslide_try_aperio(openslide_t *osr, TIFF *tiff,
			   struct _openslide_hash *quickhash1,
			   GError **err) {
  int32_t level_count = 0;
  int32_t *levels = NULL;
  int32_t i = 0;

  if (!TIFFIsTiled(tiff)) {
    g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED,
                "TIFF is not tiled");
    goto FAIL;
  }

  char *tagval;
  int tiff_result;
  tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval);
  if (!tiff_result ||
      (strncmp(APERIO_DESCRIPTION, tagval, strlen(APERIO_DESCRIPTION)) != 0)) {
    g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED,
                "Not an Aperio slide");
    goto FAIL;
  }

  /*
   * http://www.aperio.com/documents/api/Aperio_Digital_Slides_and_Third-party_data_interchange.pdf
   * page 14:
   *
   * The first image in an SVS file is always the baseline image (full
   * resolution). This image is always tiled, usually with a tile size
   * of 240 x 240 pixels. The second image is always a thumbnail,
   * typically with dimensions of about 1024 x 768 pixels. Unlike the
   * other slide images, the thumbnail image is always
   * stripped. Following the thumbnail there may be one or more
   * intermediate "pyramid" images. These are always compressed with
   * the same type of compression as the baseline image, and have a
   * tiled organization with the same tile size.
   *
   * Optionally at the end of an SVS file there may be a slide label
   * image, which is a low resolution picture taken of the slide’s
   * label, and/or a macro camera image, which is a low resolution
   * picture taken of the entire slide. The label and macro images are
   * always stripped.
   */

  // for aperio, the tiled directories are the ones we want
  do {
    if (TIFFIsTiled(tiff)) {
      level_count++;
    }
  } while (TIFFReadDirectory(tiff));
  levels = g_new(int32_t, level_count);

  TIFFSetDirectory(tiff, 0);
  i = 0;
  do {
    tdir_t dir = TIFFCurrentDirectory(tiff);
    if (TIFFIsTiled(tiff)) {
      levels[i++] = dir;
      //g_debug("tiled directory: %d", dir);
    } else {
      // associated image
      const char *name = (dir == 1) ? "thumbnail" : NULL;
      if (!add_associated_image(osr ? osr->associated_images : NULL,
                                name, tiff, err)) {
	g_prefix_error(err, "Can't read associated image: ");
	goto FAIL;
      }
      //g_debug("associated image: %d", dir);
    }

    // check depth
    uint32_t depth;
    tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDEPTH, &depth);
    if (tiff_result && depth != 1) {
      // we can't handle depth != 1
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                  "Cannot handle ImageDepth=%d", depth);
      goto FAIL;
    }

    // check compression
    uint16_t compression;
    if (!TIFFGetField(tiff, TIFFTAG_COMPRESSION, &compression)) {
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                  "Can't read compression scheme");
      goto FAIL;
    }
    if ((compression != APERIO_COMPRESSION_JP2K_YCBCR) &&
        (compression != APERIO_COMPRESSION_JP2K_RGB) &&
        !TIFFIsCODECConfigured(compression)) {
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                  "Unsupported TIFF compression: %u", compression);
      goto FAIL;
    }
  } while (TIFFReadDirectory(tiff));

  // read properties
  if (osr) {
    TIFFSetDirectory(tiff, 0);
    TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval); // XXX? should be safe, we just did it
    char **props = g_strsplit(tagval, "|", -1);
    add_properties(osr->properties, props);
    g_strfreev(props);
  }

  // special jpeg 2000 aperio thing (with fallback)
  _openslide_add_tiff_ops(osr, tiff, 0, 0, NULL, level_count, levels,
			  aperio_tiff_tilereader,
			  quickhash1);
  return true;

 FAIL:
  g_free(levels);
  return false;
}
예제 #7
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;
}