[poppler] test: update-cache.c, NONE, 1.1 read-cache.c, NONE, 1.1 Makefile, 1.10, 1.11 test-poppler.c, 1.5, 1.6 buffer-diff.c, 1.3, 1.4

Jeff Muizelaar jrmuizel at kemper.freedesktop.org
Wed Sep 6 16:28:55 PDT 2006


Update of /cvs/poppler/test
In directory kemper:/tmp/cvs-serv12204

Modified Files:
	Makefile test-poppler.c buffer-diff.c 
Added Files:
	update-cache.c read-cache.c 
Log Message:
Add support for a reference cache file that contains SHA1 hashes of the
reference images. Having the cache avoids the performance hit of reading and
decompressing the reference pngs.


--- NEW FILE: update-cache.c ---
#include <stdlib.h>
#include <stdio.h>
#include <glob.h>
#include <string.h>
#include <openssl/sha.h>
#include <libgen.h>
#include "read-png.h"
#include "read-cache.h"

static void hash_image(FILE *cache, const char *path)
{
  unsigned int width, height, stride;
  unsigned char *buf, *buf_diff;
  unsigned char hash[SHA_DIGEST_LENGTH];
  unsigned int buffer_length;
  read_png_status_t status;
  char *path_copy = strdup(path);
  char *name = basename(path_copy);

  status = read_png_argb32 (path, &buf, &width, &height, &stride);
  buffer_length = height * stride;
  printf("%d %d %d\n", width, height, stride);
  SHA1(buf, buffer_length, hash);
  int i;
  for (i=0; i<sizeof(hash); i++) {
    printf("%02x", hash[i]);
  }
  printf("\n");
  /* write the NULL character as well */
  fwrite(name, 1, strlen(name)+1, cache);
  fwrite(hash, 1, sizeof(hash), cache);

  free(path_copy);
  free(buf);
}

int main(int argc, char **argv)
{
  glob_t globbuf;
  int i;
  FILE *cache;

  if (argc > 1) {
    /* search in directory of first argument for cache file */
    cache = cache_open(argv[1], "w+");
  } else {
    cache = cache_open("test/", "w+");
  }
  if (!cache) {
    printf("could not open cache\n");
    exit(1);
  }
  if (argc > 1) {
    for (i=1; i<argc; i++) {
      char *glob_pat;
      asprintf(&glob_pat, "%s*-ref.png", argv[i]);
      printf("pat: %s\n", glob_pat);
      glob(glob_pat, 0, NULL, &globbuf);
      int j;
      for (j=0; j<globbuf.gl_pathc; j++) {
	printf("%s\n", globbuf.gl_pathv[j]);
	hash_image(cache, globbuf.gl_pathv[j]);
      }
      globfree(&globbuf);
      free(glob_pat);
    }
  } else {
    glob("tests/*.pdf*-ref.png", 0, NULL, &globbuf);
    for (i=0; i<globbuf.gl_pathc; i++) {
      printf("%s\n", globbuf.gl_pathv[i]);
      hash_image(cache, globbuf.gl_pathv[i]);
    }
    globfree(&globbuf);
  }
  fclose(cache);

  return 0;
}

--- NEW FILE: read-cache.c ---
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <libgen.h>
#include <openssl/sha.h>
#include "read-cache.h"

unsigned char *cache;
unsigned char *cache_end;
unsigned char *current_cache_entry;
void cache_init(const char *path)
{
  FILE *f = cache_open(path, "r");
  if (!f) {
    printf("no cache\n");
    return;
  }
  struct stat buf;
  fstat(fileno(f), &buf);
  cache = malloc(buf.st_size);
  fread(cache, 1, buf.st_size, f);
  fclose(f);

  /* set the current entry to the begining of the cache */
  current_cache_entry = cache;
  cache_end = cache + buf.st_size;
}

FILE *cache_open(const char *path, const char *mode)
{
  FILE *cache;
  char *cache_path;
  char *path_copy = strdup(path);
  char *dir = dirname(path_copy);
  asprintf(&cache_path, "%s/cache", dir);
  cache = fopen(cache_path, mode);
  free(cache_path);
  free(path_copy);
  return cache;
}

#define MIN(a, b) (a) < (b) ? (a) : (b)

static void print_hash(const unsigned char *hash)
{
  int i;
  for (i=0; i<SHA_DIGEST_LENGTH; i++) {
    printf("%02x", hash[i]);
  }
  printf("\n");
}

int cache_compare(const char *path, const unsigned char *buffer, unsigned int length)
{
  char *path_copy = strdup(path);
  char *name = basename(path_copy);
  int match = 0;
  //printf("compare: %s\n", path);
  int name_length = strlen(name);
  while (current_cache_entry < cache_end) {
    int cache_length = strlen(current_cache_entry);
    int min_length = MIN(cache_length, name_length);
    int result = memcmp(name, current_cache_entry, min_length);
    if (result == 0) {
      unsigned char *cache_hash = current_cache_entry + cache_length + 1;
      unsigned char hash[SHA_DIGEST_LENGTH];
      //printf("found entry\n");
      SHA1(buffer, length, hash);
      print_hash(cache_hash);
      print_hash(hash);
      current_cache_entry = cache_hash + SHA_DIGEST_LENGTH;
      match = memcmp(hash, cache_hash, SHA_DIGEST_LENGTH) == 0 ? 1 : 0;
      //printf("match %d\n", match);
      break;
    } else if (result < 0) {
      //printf("moving to next entry: %s vs. %s did not match\n", name, current_cache_entry);
      current_cache_entry += cache_length + 1 + SHA_DIGEST_LENGTH;
      break;
    } else {
      //printf("trying next entry: %s vs. %s did not match\n", name, current_cache_entry);
      current_cache_entry += cache_length + 1 + SHA_DIGEST_LENGTH;
    }
  }
  free(path_copy);

  return match;
}

Index: Makefile
===================================================================
RCS file: /cvs/poppler/test/Makefile,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- Makefile	18 Jun 2006 01:44:20 -0000	1.10
+++ Makefile	6 Sep 2006 23:28:53 -0000	1.11
@@ -1,4 +1,4 @@
-CFLAGS = $(shell pkg-config --cflags poppler-glib pango gdk-2.0) -g
+CFLAGS = $(shell pkg-config --cflags poppler-glib pango gdk-2.0) -g -Wall -O2
 LDLIBS = $(shell pkg-config --libs poppler-glib)
 
 PDFS = $(addprefix tests/, mask.pdf text.pdf image.pdf type3.pdf cropbox.pdf inline-image.pdf degenerate-path.pdf)
@@ -7,13 +7,16 @@
 	POPPLER_DEPS = $(POPPLER_DIR)/poppler/libpoppler.la
 endif
 
-all : test-poppler $(PDFS)
+all : test-poppler update-cache $(PDFS)
 
-test-poppler: buffer-diff.o  read-png.o  test-poppler.o  write-png.o  xmalloc.o $(POPPLER_DEPS)
+test-poppler: buffer-diff.o  read-png.o  test-poppler.o  write-png.o  xmalloc.o read-cache.o $(POPPLER_DEPS)
 ifdef POPPLER_DIR
-	$(POPPLER_DIR)/libtool --mode=link gcc  -g -O2  -lpng -o $@  $^ $(POPPLER_DIR)/poppler/libpoppler.la $(POPPLER_DIR)/glib/libpoppler-glib.la 
+	$(POPPLER_DIR)/libtool --mode=link gcc -Wall -g -O2  -lpng -lssl -o $@  $^ $(POPPLER_DIR)/poppler/libpoppler.la $(POPPLER_DIR)/glib/libpoppler-glib.la 
 endif
 
+update-cache: update-cache.o read-cache.o read-png.o xmalloc.o
+	$(CC) -Wall $^ -o $@ -lpng -lssl
+
 clean :
 	rm test-poppler *.o tests/*out.png
 

Index: test-poppler.c
===================================================================
RCS file: /cvs/poppler/test/test-poppler.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- test-poppler.c	12 Apr 2006 05:29:11 -0000	1.5
+++ test-poppler.c	6 Sep 2006 23:28:53 -0000	1.6
@@ -2,7 +2,7 @@
 #include <stdlib.h>
 #include <poppler.h>
 #include <glob.h>
-
+#include "read-cache.h"
 #define FAIL(msg) \
 	do { fprintf (stderr, "FAIL: %s\n", msg); exit (-1); } while (0)
 
@@ -18,7 +18,18 @@
       POPPLER_TEST_FAILURE
 } poppler_test_status_t;
 
-poppler_test_status_t gdk_pixbuf_compare(GdkPixbuf *pixbuf, char *pdf_file, int page_index)
+int ilog10(int a)
+{
+  int l = 10;
+  int log = 0;
+  while (a >= l) {
+    l *= 10;
+    log++;
+  }
+  return log;
+}
+
+poppler_test_status_t gdk_pixbuf_compare(GdkPixbuf *pixbuf, char *page_name)
 {
   char *png_name, *ref_name, *diff_name;
   char *srcdir;
@@ -29,10 +40,9 @@
   srcdir = getenv ("srcdir");
   if (!srcdir)
     srcdir = ".";
- 
-  asprintf (&png_name, "%s-%d-%s%s", pdf_file, page_index, backend, POPPLER_TEST_PNG_SUFFIX);
-  asprintf (&ref_name, "%s/%s-%d-%s%s", srcdir, pdf_file, page_index, backend, POPPLER_TEST_REF_SUFFIX);
-  asprintf (&diff_name, "%s-%d-%s%s", pdf_file, page_index, backend, POPPLER_TEST_DIFF_SUFFIX);
+  asprintf (&png_name, "%s-%s%s", page_name, backend, POPPLER_TEST_PNG_SUFFIX);
+  asprintf (&ref_name, "%s/%s-%s%s", srcdir, page_name, backend, POPPLER_TEST_REF_SUFFIX);
+  asprintf (&diff_name, "%s-%s%s", page_name, backend, POPPLER_TEST_DIFF_SUFFIX);
 #ifdef PNG_SAVE
   gdk_pixbuf_save (pixbuf, png_name, "png", &error, NULL);
   pixels_changed = image_diff (png_name, ref_name, diff_name);
@@ -67,16 +77,19 @@
   return pixels_changed ? POPPLER_TEST_FAILURE : POPPLER_TEST_SUCCESS;
 }
 
-poppler_test_status_t poppler_test_page(char *pdf_file, PopplerDocument *document, int page_index) {
+poppler_test_status_t poppler_test_page(char *pdf_file, PopplerDocument *document, int page_index, int n_pages) {
   GdkPixbuf *pixbuf, *thumb;
   double width, height;
   PopplerPage *page;
   poppler_test_status_t ret;
-  
-  char thumb_file[strlen(pdf_file) + strlen("-thumb") + 1];
-  strcpy(thumb_file, pdf_file);
-  strcat(thumb_file, "-thumb");
-  
+  char *page_format;
+  char *page_name;
+  char *thumb_name;
+
+  asprintf(&page_format, "%%s-%%0%dd", ilog10(n_pages)+1);
+  asprintf(&page_name, page_format, pdf_file, page_index);
+  asprintf(&thumb_name, "%s-thumb", page_name);
+
   page = poppler_document_get_page (document, page_index);
   if (!page)
     FAIL ("page not found");
@@ -87,17 +100,19 @@
   gdk_pixbuf_fill (pixbuf, 0x00106000);
   poppler_page_render_to_pixbuf (page, 0, 0, width, height, 1.0, 0, pixbuf);
 
-  ret = gdk_pixbuf_compare(pixbuf, pdf_file, page_index);
+  ret = gdk_pixbuf_compare(pixbuf, page_name);
   
   thumb = poppler_page_get_thumbnail(page);
   if (thumb)
-    ret |= gdk_pixbuf_compare(thumb, thumb_file, page_index);
+    ret |= gdk_pixbuf_compare(thumb, thumb_name);
  
   if (thumb)
     g_object_unref (G_OBJECT (thumb));
   g_object_unref (G_OBJECT (page));
   g_object_unref (G_OBJECT (pixbuf));
 
+  free(page_format);
+  free(page_name);
   return ret;
 }
 
@@ -125,7 +140,7 @@
   for (i=0; i<n_pages; i++) {
     printf("%s-%d ", pdf_file, i);
     fflush(stdout);
-    if (poppler_test_page(pdf_file, document, i))
+    if (poppler_test_page(pdf_file, document, i, n_pages))
       printf("FAIL\n");
     else
       printf("PASS\n");
@@ -140,10 +155,12 @@
   int i;
   g_type_init ();
   if (argc > 1) {
+	  cache_init(argv[1]);
 	  for (i=1; i<argc; i++) {
 		  poppler_test(argv[i]);
 	  }
   } else {
+	  cache_init("tests/");
 	  glob("tests/*.pdf", 0, NULL, &globbuf);
 	  for (i=0; i<globbuf.gl_pathc; i++) {
 		  poppler_test(globbuf.gl_pathv[i]);

Index: buffer-diff.c
===================================================================
RCS file: /cvs/poppler/test/buffer-diff.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- buffer-diff.c	12 Apr 2006 05:29:11 -0000	1.3
+++ buffer-diff.c	6 Sep 2006 23:28:53 -0000	1.4
@@ -66,6 +66,7 @@
 	    int channel;
 	    uint32_t value_a, value_b;
 	    int pixel_differs = 0;
+	    //XXX: it looks like this might overread...
 	    value_a = *(uint32_t*)(&(row_a[x*4]));
 	    value_b = *(uint32_t*)(&(row_b[x*4]));
 	    if (value_a != value_b) {
@@ -93,6 +94,21 @@
     return pixels_changed;
 }
 
+static void copy_file(const char *filename_a, const char *filename_b)
+{
+  char buf[4096];
+  FILE *filea = fopen(filename_a, "r");	
+  FILE *fileb = fopen (filename_b, "wb");
+  int count = sizeof(buf);
+  while (count == sizeof(buf)) {
+    count = fread(buf, 1, sizeof(buf), filea);
+    fwrite(buf, 1, count, fileb);
+  }
+  fclose(filea);
+  fclose(fileb);
+
+}
+
 int
 image_buf_diff (char *buf_a, int width_a, int height_a, int stride_a,
 	    const char *filename_a,
@@ -104,6 +120,12 @@
     unsigned char *buf_b, *buf_diff;
     read_png_status_t status;
 
+    if (cache_compare(filename_b, buf_a, height_a * stride_a)) {
+      copy_file(filename_b, filename_a);
+      xunlink (filename_diff);
+      return 0;
+    }
+
     status = read_png_argb32 (filename_b, &buf_b, &width_b, &height_b, &stride_b);
     if (status) {
 	// write out the buffer on failure
@@ -140,16 +162,7 @@
 	write_png_argb32 (buf_a, png_file, width_a, height_a, stride_a);
 	fclose (png_file);
     } else {
-	char buf[4096];
-	FILE *ref_file = fopen(filename_b, "r");	
-	FILE *png_file = fopen (filename_a, "wb");
-	int count = sizeof(buf);
-	while (count == sizeof(buf)) {
-	  count = fread(buf, 1, sizeof(buf), ref_file);
-	  fwrite(buf, 1, count, png_file);
-	}
-	fclose(ref_file);
-	fclose(png_file);
+        copy_file(filename_b, filename_a);
 	xunlink (filename_diff);
     }
 



More information about the poppler mailing list