/* * Create a tiled interface and draw it. * * * Compile with: * gcc -g -O2 -o tileTest tileTest.c -ltiff -lgeotiff \ * `pkg-config --libs --cflags gtk+-2.0` */ #include #include #include #include #include #include #include #include #include //#include //#include #define APPNAME "tileTest" #define WIDTH 640 #define HEIGHT 480 static GdkPixbuf *pixbuf; static TIFF *tiff; static void FillGradient(guchar *pixels, uint32 chan, uint32 rs, uint32 w, uint32 h) { int x, y; guchar *p; /* * Pattern goes like: * * (0,0,0) ... (X,X/2,0) * . . * . . * . . * (0,Y/2,Y) ... (X,X/2+Y/2,Y) * * X and Y are normalized from 0:width-1 and 0:height-1 to 0:255 and 0:255. * */ #define NORM(v,a) ((v) * 256 / (a)) for (x = 0; x < w; x++) { for (y = 0; y < h; y++) { int r, g, b; r = NORM(x, w); b = NORM(y, h); g = r / 2 + b / 2; p = pixels + y * rs + x * chan; p[0] = r; p[1] = g; p[2] = b; p[3] = 255; } } } struct BackingStore { uint32 w; // width of bs uint32 h; // height of bs uint32 x; // offset into bs of viewport uint32 y; // offset into bs of viewport uint8 *buf; }; static struct BackingStore *bs = NULL; void FreeBackingStore(void) { free(bs->buf); free(bs); } void AllocBackingStore(uint32 w, uint32 h) { assert(bs == NULL); bs = malloc(sizeof(struct BackingStore)); if (bs == NULL) { fprintf(stderr, "Failed to alloc backing store: %s\n", strerror(errno)); exit(EXIT_FAILURE); } bs->buf = malloc(w * h * 16); // 4 bytes/pixel and 2x width and height if (bs == NULL) { free(bs); fprintf(stderr, "Failed to alloc backing store buffer: %s\n", strerror(errno)); exit(EXIT_FAILURE); } bs->w = w * 2; bs->h = h * 2; bs->x = 0; bs->y = 0; } void UpdateBackingStore(uint32 vx, uint32 vy, uint32 vw, uint32 vh) { } void FillImage(guchar *pixels, uint32 chan, uint32 rs, uint32 w, uint32 h) { /* w, h => viewport width, height */ /* rs => row stride */ uint32 tw, th, npix, *ras; /* TIFF width, height, number of pixels, raster */ uint32 txo, tyo; /* TIFF X offset, Y offset to start of viewport */ uint32 xo, yo; uint32 W, H, x, y; TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &tw); TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &th); npix = tw * th; printf("image width %u, height %u, npix %u\n", tw, th, npix); ras = (uint32 *)_TIFFmalloc(npix * 4); if (ras == NULL) { fprintf(stderr, "Failed to _TIFFmalloc %u bytes!\n", npix * 4); gtk_main_quit(); return; } /* * Figure out viewport. */ if (tw > w) { txo = (tw - w) / 2; W = w; xo = 0; } else if (tw < w) { txo = 0; W = tw; xo = (w - tw) / 2; } else { txo = xo = 0; W = w; } if (th > h) { tyo = (th - h) / 2; H = h; yo = 0; } else if (th < h) { tyo = 0; H = th; yo = (h - th) / 2; } else { tyo = yo = 0; H = h; } printf("TIFF offset (%u,%u), pixbuf offset (%u,%u), (W,H) (%u,%u)\n", txo, tyo, xo, yo, W, H); if (TIFFIsTiled(tiff)) { printf("image is tiled, size = %u bytes\n", TIFFTileSize(tiff)); } else { printf("image has %u strips, scanline size = %u\n", TIFFNumberOfStrips(tiff), TIFFScanlineSize(tiff)); } if (!TIFFReadRGBAImage(tiff, tw, th, ras, 0)) { fprintf(stderr, "TIFFReadRGBAImage failed\n"); goto out; } /* if (!TIFFReadRGBAImageOriented(tiff, tw, th, ras, 0, ORIENTATION_TOPLEFT)) { */ /* fprintf(stderr, "Failed to TIFFReadRGBAImage!\n"); */ /* gtk_main_quit(); */ /* return; */ /* } */ for (x = 0; x < W; x++) { for (y = 0; y < H; y++) { guchar *p; uint32 *tp; //uint8 r, g, b; p = pixels + (y + yo) * rs + (x + xo) * chan; tp = ras + (y + tyo) * tw + (x + txo); p[0] = TIFFGetR(*tp); p[1] = TIFFGetG(*tp); p[2] = TIFFGetB(*tp); p[3] = TIFFGetA(*tp); /* printf("(x,y,r,g,b,A) => (%u,%u,%hhu,%hhu,%hhu,%hhu)\n", */ /* x, y, p[0], p[1], p[2], p[3]); */ } } out: _TIFFfree(ras); } void FillPixbuf(void) { uint32 chan, w, h, rs; guchar *pixels; pixels = gdk_pixbuf_get_pixels(pixbuf); chan = gdk_pixbuf_get_n_channels(pixbuf); rs = gdk_pixbuf_get_rowstride(pixbuf); w = gdk_pixbuf_get_width(pixbuf); h = gdk_pixbuf_get_height(pixbuf); FillGradient(pixels, chan, rs, w, h); FillImage(pixels, chan, rs, w, h); } gboolean quit(GtkWidget *widget, GdkEvent *thisevent, gpointer data) { gtk_main_quit(); return TRUE; } gboolean expose(GtkWidget *widget, GdkEvent *thisevent, gpointer data) { gdk_draw_pixbuf(widget->window, NULL, pixbuf, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0); return TRUE; } void ui(void) { GtkWidget *window, *img; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), APPNAME); gtk_window_set_default_size(GTK_WINDOW(window), WIDTH, HEIGHT); gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER); g_signal_connect(G_OBJECT (window), "delete_event", G_CALLBACK(quit),NULL); pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, WIDTH, HEIGHT); FillPixbuf(); img = gtk_drawing_area_new(); gtk_widget_set_size_request(img, WIDTH, HEIGHT); g_signal_connect(G_OBJECT(img), "expose_event", G_CALLBACK(expose), NULL); gtk_container_add(GTK_CONTAINER(window), img); gtk_widget_show_all(window); } int main(int argc, char *argv[]) { gtk_init(&argc, &argv); if (argc != 2) { fprintf(stderr, "Missing filename\n"); exit(EXIT_FAILURE); } if ((tiff = TIFFOpen(argv[1], "r")) == NULL) { fprintf(stderr, "Failed to open %s\n", argv[1]); exit(EXIT_FAILURE); } ui(); g_set_application_name(APPNAME); AllocBackingStore(WIDTH, HEIGHT); gtk_main(); FreeBackingStore(); TIFFClose(tiff); return 0; }