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

_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to