static bool decode_tile(struct level *l, TIFF *tiff, uint32_t *dest, int64_t tile_col, int64_t tile_row, GError **err) { struct _openslide_tiff_level *tiffl = &l->tiffl; // some Aperio slides have some zero-length tiles, possibly due to an // encoder bug bool is_empty; if (!check_for_empty_tile(tiffl, tiff, tile_col, tile_row, &is_empty, err)) { return false; } if (is_empty) { // fill with transparent memset(dest, 0, tiffl->tile_w * tiffl->tile_h * 4); return true; } // select color space enum _openslide_jp2k_colorspace space; switch (l->compression) { case APERIO_COMPRESSION_JP2K_YCBCR: space = OPENSLIDE_JP2K_YCBCR; break; case APERIO_COMPRESSION_JP2K_RGB: space = OPENSLIDE_JP2K_RGB; break; default: // not for us? fallback return _openslide_tiff_read_tile(tiffl, tiff, dest, tile_col, tile_row, err); } // read raw tile void *buf; int32_t buflen; if (!_openslide_tiff_read_tile_data(tiffl, tiff, &buf, &buflen, tile_col, tile_row, err)) { return false; // ok, haven't allocated anything yet } // decompress bool success = _openslide_jp2k_decode_buffer(dest, tiffl->tile_w, tiffl->tile_h, buf, buflen, space, err); // clean up g_free(buf); return success; }
static bool read_tile(openslide_t *osr, cairo_t *cr, struct _openslide_level *level, int64_t tile_col, int64_t tile_row, void *arg, GError **err) { struct level *l = (struct level *) level; struct _openslide_tiff_level *tiffl = &l->tiffl; TIFF *tiff = arg; // tile size int64_t tw = tiffl->tile_w; int64_t th = tiffl->tile_h; // cache struct _openslide_cache_entry *cache_entry; uint32_t *tiledata = _openslide_cache_get(osr->cache, level, tile_col, tile_row, &cache_entry); if (!tiledata) { tiledata = g_slice_alloc(tw * th * 4); if (!_openslide_tiff_read_tile(tiffl, tiff, tiledata, tile_col, tile_row, err)) { g_slice_free1(tw * th * 4, tiledata); return false; } // clip, if necessary if (!_openslide_tiff_clip_tile(tiffl, tiledata, tile_col, tile_row, err)) { g_slice_free1(tw * th * 4, tiledata); return false; } // put it in the cache _openslide_cache_put(osr->cache, level, tile_col, tile_row, tiledata, tw * th * 4, &cache_entry); } // draw it cairo_surface_t *surface = cairo_image_surface_create_for_data((unsigned char *) tiledata, CAIRO_FORMAT_ARGB32, tw, th, tw * 4); cairo_set_source_surface(cr, surface, 0, 0); cairo_surface_destroy(surface); cairo_paint(cr); // done with the cache entry, release it _openslide_cache_entry_unref(cache_entry); return true; }
static bool decode_tile(struct level *l, TIFF *tiff, uint32_t *dest, int64_t tile_col, int64_t tile_row, GError **err) { struct _openslide_tiff_level *tiffl = &l->tiffl; // check for missing tile int64_t tile_no = tile_row * tiffl->tiles_across + tile_col; if (g_hash_table_lookup_extended(l->missing_tiles, &tile_no, NULL, NULL)) { //g_debug("missing tile in level %p: (%"PRId64", %"PRId64")", (void *) l, tile_col, tile_row); return render_missing_tile(l, tiff, dest, tile_col, tile_row, err); } // select color space enum _openslide_jp2k_colorspace space; switch (l->compression) { case APERIO_COMPRESSION_JP2K_YCBCR: space = OPENSLIDE_JP2K_YCBCR; break; case APERIO_COMPRESSION_JP2K_RGB: space = OPENSLIDE_JP2K_RGB; break; default: // not for us? fallback return _openslide_tiff_read_tile(tiffl, tiff, dest, tile_col, tile_row, err); } // read raw tile void *buf; int32_t buflen; if (!_openslide_tiff_read_tile_data(tiffl, tiff, &buf, &buflen, tile_col, tile_row, err)) { return false; // ok, haven't allocated anything yet } // decompress bool success = _openslide_jp2k_decode_buffer(dest, tiffl->tile_w, tiffl->tile_h, buf, buflen, space, err); // clean up g_free(buf); return success; }