shithub: jbig2

Download patch

ref: d53ab5a9d654df525f522afb43c6afeb6c1b6d4b
parent: 778b53afed3f8cd0caa85d81a3f1fd0a3a35c446
author: giles <giles@ded80894-8fb9-0310-811b-c03f3676ab4d>
date: Mon Jul 15 16:01:01 EDT 2002

Add a '--hash' cmdline option to print the SHA-1 hash of the decoded
document. Useful for regression testing. We currently use the openssl/
libcrypto implemention; there's provision for fallback to a local version
but I've not written one yet. It should probably just be the default once
provided.


git-svn-id: http://svn.ghostscript.com/jbig2dec/trunk@138 ded80894-8fb9-0310-811b-c03f3676ab4d

--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
 AM_INIT_AUTOMAKE([AC_PACKAGE_NAME], [AC_PACKAGE_VERSION])
 AM_CONFIG_HEADER(config.h)
 
-AC_REVISION([$Revision: 1.8 $])
+AC_REVISION([$Revision: 1.9 $])
 
 # Checks for programs.
 AC_PROG_CC
@@ -96,6 +96,27 @@
 AC_FUNC_MEMCMP
 AC_CHECK_FUNCS([memset strdup])
 
+dnl use our included md5 if we can't find one
+AC_CHECK_HEADER([openssl/md5.h], [
+  AC_CHECK_LIB(crypto, MD5_Init, [
+    AC_DEFINE(HAVE_OPENSSL_MD5,,[Define to use of the 
+      MD5_*() routines from OpenSSL rather than the included ones])
+    LIBS="$LIBS -lcrypto"
+  ], [
+    AC_LIBOBJ([md5])
+  ])
+],,[ ])
+	
+dnl use our included SHA-1 if we can't find one
+AC_CHECK_HEADER([openssl/sha.h], [
+  AC_CHECK_LIB(crypto, SHA1_Init, [
+    AC_DEFINE(HAVE_OPENSSL_SHA1,,[Define to use of the 
+      SHA1_*() routines from OpenSSL rather than the included ones])
+  ], [
+    AC_LIBOBJ([sha1])
+  ])
+],,[ ])
+	
 dnl use our included getopt if the system doesn't have getopt_long()
 AC_CHECK_FUNC(getopt_long, 
 	[AC_DEFINE(HAVE_GETOPT_LONG,,[Define if the local libc includes getopt_long()])],
--- a/jbig2dec.c
+++ b/jbig2dec.c
@@ -8,7 +8,7 @@
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
 
-    $Id: jbig2dec.c,v 1.31 2002/07/13 00:32:13 giles Exp $
+    $Id: jbig2dec.c,v 1.32 2002/07/15 20:01:01 giles Exp $
 */
 
 #ifdef HAVE_CONFIG_H
@@ -22,10 +22,13 @@
 #endif
 
 #include <stdio.h>
-# include <stdlib.h>
-# include <stddef.h>
-# include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
 
+#include "jbig2.h"
+#include "jbig2_image.h"
+
 #ifdef HAVE_GETOPT_H
 # include <getopt.h>
 #else
@@ -32,8 +35,9 @@
 # include "getopt.h"
 #endif
 
-#include "jbig2.h"
-#include "jbig2_image.h"
+#ifdef HAVE_OPENSSL_SHA1
+# include <openssl/sha.h>
+#endif
 
 typedef enum {
     usage,dump,render
@@ -41,38 +45,67 @@
 
 typedef struct {
 	jbig2dec_mode mode;
-	int verbose;
+	int verbose, hash;
+#ifdef HAVE_OPENSSL_SHA1
+        SHA_CTX *hash_ctx;
+#endif
 	char *output_file;
 } jbig2dec_params_t;
 
+/* page hashing functions */
+static void
+hash_init(jbig2dec_params_t *params)
+{
+#ifdef HAVE_OPENSSL_SHA1
+    params->hash_ctx = malloc(sizeof(SHA_CTX));
+    if (params->hash == NULL) {
+        fprintf(stderr, "unable to allocate hash state\n");
+        params->hash = 0;
+        return;
+    } else {
+        SHA1_Init(params->hash_ctx);
+    }
+#endif /* HAVE_OPENSSL_SHA1 */
+}
 
-static int
-print_usage (void)
+static void
+hash_image(jbig2dec_params_t *params, Jbig2Image *image)
 {
-  fprintf(stderr,
-    "Usage: jbig2dec [options] <file.jbig2>\n"
-    "   or  jbig2dec [options] <global_stream> <page_stream>\n"
-    "\n"
-    "  When invoked with a single file, it attempts to parse it as\n"
-    "  a normal jbig2 file. Invoked with two files, it treats the\n"
-    "  first as the global segments, and the second as the segment\n"
-    "  stream for a particular page. This is useful for examining\n"
-    "  embedded streams.\n"
-    "\n"
-    "  available options:\n"
-    "    -h --help	this usage summary\n"
-    "    -q --quiet     suppress diagnostic output\n"
-    "    -d --dump      print the structure of the jbig2 file\n"
-    "                   rather than explicitly decoding\n"
-    "    -o <file>	send decoded output to <file>\n"
-    "                   Defaults to the the input with a different\n"
-    "                   extension. Pass '-' for stdout.\n"
-    "\n"
-  );
-  
-  return 1;
+    int N = image->stride * image->height;
+#ifdef HAVE_OPENSSL_SHA1
+    SHA1_Update(params->hash_ctx, image->data, N);
+#endif
 }
 
+static void
+hash_print(jbig2dec_params_t *params, FILE *out)
+{
+#ifdef HAVE_OPENSSL_SHA1
+    char md[SHA_DIGEST_LENGTH];
+    char digest[2*SHA_DIGEST_LENGTH + 1];
+    int i;
+    
+    SHA1_Final(md, params->hash_ctx);
+    for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
+        snprintf(&(digest[2*i]), 3, "%02x", md[i]);
+    }
+    fprintf(out, "%s", digest);
+#else
+    fprintf(out, "sorry, hash function unimplemented");
+#endif
+}
+
+static void
+hash_free(jbig2dec_params_t *params)
+{
+#ifdef HAVE_OPENSSL_SHA1
+    // FIXME: need to check for SHA1 finalization?
+    free(params->hash_ctx);
+    params->hash_ctx = NULL;
+#endif
+}
+
+
 static int
 parse_options(int argc, char *argv[], jbig2dec_params_t *params)
 {
@@ -80,6 +113,7 @@
 		{"quiet", 0, NULL, 'q'},
 		{"help", 0, NULL, 'h'},
 		{"dump", 0, NULL, 'd'},
+                {"hash", 0, NULL, 'm'},
 		{"output", 1, NULL, 'o'},
 		{NULL, 0, NULL, 0}
 	};
@@ -108,6 +142,9 @@
 			case 'd':
 				params->mode=dump;
 				break;
+                        case 'm':
+                                params->hash = 1;
+                                break;
 			case 'o':
 				params->output_file = strdup(optarg);
 				break;
@@ -117,10 +154,36 @@
 				break;
 		}
 	}
-	fprintf(stderr, "final option index %d out of %d\n", optind, argc);
 	return (optind);
 }
 
+static int
+print_usage (void)
+{
+  fprintf(stderr,
+    "Usage: jbig2dec [options] <file.jbig2>\n"
+    "   or  jbig2dec [options] <global_stream> <page_stream>\n"
+    "\n"
+    "  When invoked with a single file, it attempts to parse it as\n"
+    "  a normal jbig2 file. Invoked with two files, it treats the\n"
+    "  first as the global segments, and the second as the segment\n"
+    "  stream for a particular page. This is useful for examining\n"
+    "  embedded streams.\n"
+    "\n"
+    "  available options:\n"
+    "    -h --help	this usage summary\n"
+    "    -q --quiet     suppress diagnostic output\n"
+    "    -d --dump      print the structure of the jbig2 file\n"
+    "                   rather than explicitly decoding\n"
+    "       --hash	print a hash of the decode document\n"
+    "    -o <file>	send decoded output to <file>\n"
+    "                   Defaults to the the input with a different\n"
+    "                   extension. Pass '-' for stdout.\n"
+    "\n"
+  );
+  
+  return 1;
+}
 
 static int
 error_callback(void *error_callback_data, const char *buf, Jbig2Severity severity,
@@ -197,7 +260,7 @@
 static int
 write_page_image(jbig2dec_params_t *params, Jbig2Image *image)
 {
-      if (!strcmp(params->output_file, "-"))
+      if (!strncmp(params->output_file, "-", 2))
         {
           fprintf(stderr, "writing decoded page to stdout\n");
 #ifdef HAVE_LIBPNG
@@ -219,6 +282,24 @@
   return 0;
 }
 
+static int
+write_document_hash(jbig2dec_params_t *params)
+{
+    FILE *out;
+    
+    if (!strncmp(params->output_file, "-", 2)) {
+        out = stderr;
+    } else {
+        out = stdout;
+    }
+    
+    fprintf(out, "Hash of decoded document: ");
+    hash_print(params, out);
+    fprintf(out, "\n");
+    
+    return 0;
+}
+
 int
 main (int argc, char **argv)
 {
@@ -225,11 +306,19 @@
   FILE *f = NULL, *f_page = NULL;
   Jbig2Ctx *ctx;
   uint8_t buf[4096];
-  jbig2dec_params_t params = {render,1,NULL};
+  jbig2dec_params_t params;
   int filearg;
+  
+  // set defaults
+  params.mode = render;
+  params.verbose = 1;
+  params.hash = 0;
+  params.output_file = NULL;
 
   filearg = parse_options(argc, argv, &params);
 
+  if (params.hash) hash_init(&params);
+  
   switch (params.mode) {
     case usage:
         print_usage();
@@ -310,7 +399,7 @@
   // retrieve and output the returned pages
   {
     Jbig2Image *image;
-    
+
     /* work around broken CVision embedded streams */
     if (f_page != NULL)
       jbig2_complete_page(ctx);
@@ -327,13 +416,17 @@
     /* retrieve and write out all the completed pages */
     while ((image = jbig2_page_out(ctx)) != NULL) {
       write_page_image(&params, image);
+      if (params.hash) hash_image(&params, image);
       jbig2_release_page(ctx, image);
     }
+    if (params.hash) write_document_hash(&params);
   }
   
   jbig2_ctx_free(ctx);
 
   } /* end params.mode switch */
+
+  if (params.hash) hash_free(&params);
   
   // fin
   return 0;