/*
* OpenSlide, a library for reading whole slide image files
*
* Copyright (c) 2007-2009 Carnegie Mellon University
* All rights reserved.
*
* OpenSlide is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* OpenSlide is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with OpenSlide. If not, see
* .
*
*/
#define _GNU_SOURCE
#include "config.h"
#include "openslide.h"
#include "callgrind.h"
#include
#include
#include
#ifndef _MSC_VER
#include
#include
#endif
#include
#include
#include
#include
static void print_downsamples(openslide_t *osr) {
for (int32_t layer = 0; layer < openslide_get_layer_count(osr); layer++) {
printf("layer %d: downsample: %g\n",
layer,
openslide_get_layer_downsample(osr, layer));
}
}
static void test_next_biggest(openslide_t *osr, double downsample) {
int32_t layer = openslide_get_best_layer_for_downsample(osr, downsample);
printf("layer for downsample %g: %d (%g)\n",
downsample, layer, openslide_get_layer_downsample(osr, layer));
}
static void test_tile_walk(openslide_t *osr,
int64_t tile_size) {
printf("test_tile_walk: %" G_GINT64_FORMAT "\n", tile_size);
uint32_t *buf = (uint32_t *) malloc(tile_size * tile_size * 4);
//struct timeval tv, tv2;
int64_t w, h;
openslide_get_layer0_dimensions(osr, &w, &h);
for (int64_t y = 0; y < h; y += tile_size) {
for (int64_t x = 0; x < w; x += tile_size) {
//gettimeofday(&tv, NULL);
openslide_read_region(osr, buf, x, y, 0, tile_size, tile_size);
//gettimeofday(&tv2, NULL);
//printf("time: %d\n", (tv2.tv_sec - tv.tv_sec) * 1000 + (tv2.tv_usec - tv.tv_usec) / 1000);
}
}
free(buf);
}
static void write_as_ppm(const char *filename,
int64_t w, int64_t h, uint32_t *buf) {
FILE *f = fopen(filename, "w");
if (f == NULL) {
perror("Cannot open file");
return;
}
fprintf(f, "P6\n%" G_GINT64_FORMAT " %" G_GINT64_FORMAT "\n255\n", w, h);
for (int64_t i = 0; i < w * h; i++) {
uint32_t val = buf[i];
putc((val >> 16) & 0xFF, f); // R
putc((val >> 8) & 0xFF, f); // G
putc((val >> 0) & 0xFF, f); // B
// no A
}
fclose(f);
}
static void test_image_fetch(openslide_t *osr,
const char *name,
int64_t x, int64_t y,
int64_t w, int64_t h,
bool skip_write) {
char *filename;
int64_t xx=x, yy=y;
printf("test image fetch %s\n", name);
// for (int32_t layer = 0; layer < 1; layer++) {
for (int32_t layer = 0; layer < openslide_get_layer_count(osr); layer++) {
filename = g_strdup_printf("%s-%.2d.ppm", name, layer);
int64_t num_bytes = w * h * 4;
printf("Going to allocate %" G_GINT64_FORMAT " bytes...\n", num_bytes);
uint32_t *buf = (uint32_t *) malloc(num_bytes);
xx >>= 1 ; yy >>= 1; /*divide coords by 2 for each layer below to get the same relative coords*/
printf("x: %" G_GINT64_FORMAT ", y: %" G_GINT64_FORMAT ", layer: %d, w: %" G_GINT64_FORMAT ", h: %" G_GINT64_FORMAT "\n", xx, yy, layer, w, h);
openslide_read_region(osr, buf, 0, 0, layer, w, h);
// write as PPM
if (!skip_write) {
write_as_ppm(filename, w, h, buf);
}
free(buf);
g_free(filename);
}
}
static void test_horizontal_walk(openslide_t *osr,
int64_t start_x,
int64_t y,
int32_t layer,
int64_t patch_w, int64_t patch_h,
int stride) {
int64_t w, h;
openslide_get_layer_dimensions(osr, layer, &w, &h);
int64_t d = MIN(w,h);
uint32_t *buf = (uint32_t *) malloc(patch_w * patch_h * 4);
for (int64_t x = start_x; x < d; x += stride) {
openslide_read_region(osr, buf, x, y, layer, patch_w, patch_h);
printf("%" G_GINT64_FORMAT "\r", x);
fflush(stdout);
}
free(buf);
}
static void test_vertical_walk(openslide_t *osr,
int64_t x,
int64_t start_y,
int32_t layer,
int64_t patch_w, int64_t patch_h,
int stride) {
int64_t w, h;
openslide_get_layer_dimensions(osr, layer, &w, &h);
int64_t d = MIN(w,h);
uint32_t *buf = (uint32_t *) malloc(patch_w * patch_h * 4);
for (int64_t y = start_y; y < d; y += stride) {
openslide_read_region(osr, buf, x, y, layer, patch_w, patch_h);
printf("%" G_GINT64_FORMAT "\r", y);
fflush(stdout);
}
free(buf);
}
static void dump_as_tiles(openslide_t *osr, const char *name,
int64_t tile_w, int64_t tile_h) {
int64_t w, h;
openslide_get_layer0_dimensions(osr, &w, &h);
uint32_t *buf = (uint32_t *) malloc(tile_w * tile_h * 4);
for (int64_t y = 0; y < h; y += tile_h) {
for (int64_t x = 0; x < w; x += tile_w) {
char *filename;
filename = g_strdup_printf("%s-%.10" G_GINT64_FORMAT "-%.10" G_GINT64_FORMAT ".ppm",
name, x, y);
printf("%s\n", filename);
openslide_read_region(osr, buf, x, y, 0, tile_w, tile_h);
write_as_ppm(filename, tile_w, tile_h, buf);
g_free(filename);
}
}
free(buf);
}
/*
static void test_pdf(openslide_t *osr, const char *filename) {
printf("test_pdf: %s\n", filename);
cairo_surface_t *pdf = cairo_pdf_surface_create(filename, 0, 0);
cairo_t *cr = cairo_create(pdf);
cairo_rotate(cr, M_PI_4);
for (int i = 0; i < openslide_get_layer_count(osr); i++) {
int64_t orig_w, orig_h;
openslide_get_layer_dimensions(osr, i, &orig_w, &orig_h);
int64_t w = MIN(orig_w, 2000);
int64_t h = MIN(orig_h, 2000);
printf(" layer %d (%" G_GINT64_FORMAT "x%" G_GINT64_FORMAT ").",
i, w, h);
fflush(stdout);
cairo_pdf_surface_set_size(pdf, w, h);
printf(".");
fflush(stdout);
cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);
cairo_paint(cr);
openslide_cairo_read_region(osr, cr, (orig_w - w) / 2, (orig_h - h) / 2, i, w, h);
printf(".");
fflush(stdout);
cairo_show_page(cr);
printf(" done\n");
}
cairo_surface_destroy(pdf);
cairo_destroy(cr);
printf(" done with pdf\n");
}
*/
int main(int argc, char **argv) {
if (argc != 2) {
printf("give file!\n");
return 1;
}
// struct timeval start_tv;
// struct timeval end_tv;
printf("openslide_can_open returns %s\n", openslide_can_open(argv[1]) ? "true" : "false");
openslide_t *osr = openslide_open(argv[1]);
int64_t w, h;
if (osr == NULL) {
printf("oh no\n");
exit(1);
}
openslide_close(osr);
osr = openslide_open(argv[1]);
if (osr == NULL) {
printf("oh no\n");
exit(1);
}
openslide_get_layer0_dimensions(osr, &w, &h);
printf("dimensions: %" G_GINT64_FORMAT " x %" G_GINT64_FORMAT "\n", w, h);
printf("comment: %s\n", openslide_get_comment(osr));
int32_t layers = openslide_get_layer_count(osr);
printf("num layers: %d\n", layers);
for (int32_t i = -1; i < layers + 1; i++) {
int64_t ww, hh;
openslide_get_layer_dimensions(osr, i, &ww, &hh);
printf(" layer %d dimensions: %" G_GINT64_FORMAT " x %" G_GINT64_FORMAT "\n", i, ww, hh);
}
print_downsamples(osr);
test_next_biggest(osr, 0.8);
test_next_biggest(osr, 1.0);
test_next_biggest(osr, 1.5);
test_next_biggest(osr, 2.0);
test_next_biggest(osr, 3.0);
test_next_biggest(osr, 3.1);
test_next_biggest(osr, 10);
test_next_biggest(osr, 20);
test_next_biggest(osr, 25);
test_next_biggest(osr, 100);
test_next_biggest(osr, 1000);
test_next_biggest(osr, 10000);
// int64_t elapsed;
// test NULL dest
openslide_read_region(osr, NULL, 0, 0, 0, 1000, 1000);
// test empty dest
uint32_t item[0];
openslide_read_region(osr, item, 0, 0, 0, 0, 0);
/*
// test empty surface
cairo_surface_t *surface =
cairo_image_surface_create(CAIRO_FORMAT_RGB24, 0, 0);
cairo_t *cr = cairo_create(surface);
cairo_surface_destroy(surface);
openslide_cairo_read_region(osr, cr, 0, 0, 0, 1000, 1000);
cairo_destroy(cr);
*/
// read properties
const char * const *property_names = openslide_get_property_names(osr);
while (*property_names) {
const char *name = *property_names;
const char *value = openslide_get_property_value(osr, name);
printf("property: %s -> %s\n", name, value);
property_names++;
}
// read associated images
const char * const *associated_image_names = openslide_get_associated_image_names(osr);
while (*associated_image_names) {
int64_t w;
int64_t h;
const char *name = *associated_image_names;
openslide_get_associated_image_dimensions(osr, name, &w, &h);
printf("associated image: %s -> (%" G_GINT64_FORMAT "x%" G_GINT64_FORMAT ")\n", name, w, h);
associated_image_names++;
}
CALLGRIND_START_INSTRUMENTATION
/*
// simulate horizonal scrolling?
gettimeofday(&start_tv, NULL);
printf("test_horizontal_walk start\n");
test_horizontal_walk(osr, 0, 0, 0, 10, 400, 10);
gettimeofday(&end_tv, NULL);
elapsed = (end_tv.tv_sec * 1000 + end_tv.tv_usec / 1000) -
(start_tv.tv_sec * 1000 + start_tv.tv_usec / 1000);
printf("test_horizontal_walk end: %d\n", elapsed);
// simulate vertical scrolling?
gettimeofday(&start_tv, NULL);
printf("test_vertical_walk start\n");
test_vertical_walk(osr, 0, 0, 0, 400, 10, 10);
gettimeofday(&end_tv, NULL);
elapsed = (end_tv.tv_sec * 1000 + end_tv.tv_usec / 1000) -
(start_tv.tv_sec * 1000 + start_tv.tv_usec / 1000);
printf("test_vertical_walk end: %d\n", elapsed);
*/
// dump_as_tiles(osr, "file1", 512, 512);
// return 0;
bool skip = false;
//test_tile_walk(osr, 16);
//test_tile_walk(osr, 4096);
//test_tile_walk(osr, 256);
//test_image_fetch(osr, "test0", 61000, 61000, 1024, 1024, skip);
//test_image_fetch(osr, "test1", w/2, h/2, 1024, 1024, skip);
//test_image_fetch(osr, "test2", w - 500, h - 300, 900, 800, skip);
//test_image_fetch(osr, "test3", w*2, h*2, 900, 800, skip);
//test_image_fetch(osr, "test4", 10, 10, 1900, 800, skip);
//test_image_fetch(osr, "test5", w - 20, 0, 40, 100, skip);
//test_image_fetch(osr, "test6", 0, h - 20, 100, 40, skip);
int64_t iw, ih;
openslide_get_layer_dimensions(osr, 0, &iw, &ih);
test_image_fetch(osr, "test7", 1000, ih-4000, 400, 400, skip);
// test_pdf(osr, "test0.pdf");
CALLGRIND_STOP_INSTRUMENTATION
openslide_close(osr);
return 0;
}