aboutsummaryrefslogblamecommitdiff
path: root/gtviewer/tileTest.c
blob: 62f416ec95b5ce437704aa8ba813f010642452c0 (plain) (tree)




























































































































































































































































































































                                                                                     
/*
 * 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>

#include <gtk/gtk.h>

#include <tiffio.h>
#include <xtiffio.h>
//#include <geotiff.h>
//#include <geo_normalize.h>

#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;
}