shithub: jbig2

Download patch

ref: 22881a46c322b45b34e20b9270e825dbe5c2c1a1
parent: 4f74ab25a2904a70c3e1e017090aed00cbd4cae3
author: giles <giles@ded80894-8fb9-0310-811b-c03f3676ab4d>
date: Tue Mar 4 21:44:43 EST 2003

Add support for ASCII-format comment extension segments. So far it's just
useful for printing out the contents through the error callback; eventually
there should be a public interface of the metadata tables and references from
the associated ctx/page/segments.


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

--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-# $Id: Makefile.am,v 1.14 2003/03/04 16:52:47 giles Exp $
+# $Id: Makefile.am,v 1.15 2003/03/05 02:44:43 giles Exp $
 ## process this file with automake to generate Makefile.in
 
 AUTOMAKE_OPTIONS = foreign 1.7 dist-bzip2 # require automake 1.7
@@ -16,7 +16,8 @@
 	jbig2.h jbig2_priv.h jbig2_image.h \
 	jbig2_arith.h jbig2_arith_iaid.h jbig2_arith_int.h \
 	jbig2_huffman.h jbig2_hufftab.h jbig2_mmr.h \
-	jbig2_generic.h jbig2_symbol_dict.h
+	jbig2_generic.h jbig2_symbol_dict.h \
+	jbig2_metadata.c jbig2_metadata.h
 
 bin_PROGRAMS = jbig2dec
 #noinst_PROGRAMS = test_huffman test_arith
--- /dev/null
+++ b/jbig2_metadata.c
@@ -1,0 +1,142 @@
+/*
+    jbig2dec
+    
+    Copyright (c) 2001-2002 artofcode LLC.
+    
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    $Id: jbig2_metadata.c,v 1.1 2003/03/05 02:44:43 giles Exp $
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif 
+#include "os_types.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "jbig2.h"
+#include "jbig2_priv.h"
+#include "jbig2_metadata.h"
+
+/* metadata key,value list object */
+Jbig2Metadata *jbig2_metadata_new(Jbig2Ctx *ctx, Jbig2Encoding encoding)
+{
+    Jbig2Metadata *md = jbig2_alloc(ctx->allocator, sizeof(Jbig2Metadata));
+    
+    if (md != NULL) {
+        md->encoding = encoding;
+        md->entries = 0;
+        md->max_entries = 4;
+        md->keys = jbig2_alloc(ctx->allocator, md->max_entries*sizeof(char*));
+        md->values = jbig2_alloc(ctx->allocator, md->max_entries*sizeof(char*));
+        if (md->keys == NULL || md->values == NULL) {
+            jbig2_metadata_free(ctx, md);
+            md = NULL;
+        }
+    }
+    return md;
+}
+
+void jbig2_metadata_free(Jbig2Ctx *ctx, Jbig2Metadata *md)
+{
+    if (md->keys) jbig2_free(ctx->allocator, md->keys);
+    if (md->values) jbig2_free(ctx->allocator, md->values);
+    jbig2_free(ctx->allocator, md);
+}
+
+static char *jbig2_strndup(Jbig2Ctx *ctx, const char *c, const int len)
+{
+    char *s = jbig2_alloc(ctx->allocator, len*sizeof(char));
+    if (s == NULL) {
+        jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+            "unable to duplicate comment string");
+    } else {
+        memcpy(s, c, len);
+    }
+    return s;
+}
+
+int jbig2_metadata_add(Jbig2Ctx *ctx, Jbig2Metadata *md,
+                        const char *key, const int key_length,
+                        const char *value, const int value_length)
+{
+    char **keys, **values;
+    
+    /* grow the array if necessary */
+    if (md->entries == md->max_entries) {
+        md->max_entries >>= 2;
+        keys = jbig2_realloc(ctx->allocator, md->keys, md->max_entries);
+        values = jbig2_realloc(ctx->allocator, md->values, md->max_entries);
+        if (keys == NULL || values == NULL) {
+            jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+                "unable to resize metadata structure");
+            return -1;
+        }
+        md->keys = keys;
+        md->values = values;
+    }
+    
+    /* copy the passed key,value pair */
+    md->keys[md->entries] = jbig2_strndup(ctx, key, key_length);
+    md->values[md->entries] = jbig2_strndup(ctx, value, value_length);
+    md->entries++;
+    
+    return 0;
+}
+
+
+/* decode an ascii comment segment 7.4.15.1 */
+int jbig2_parse_comment_ascii(Jbig2Ctx *ctx, Jbig2Segment *segment,
+                               const uint8_t *segment_data)
+{
+    char *s = (char *)segment_data + 4;
+    char *end = (char *)segment_data + segment->data_length;
+    Jbig2Metadata *comment;
+    char *key, *value;
+    int key_length, value_length;
+    
+    jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
+        "ASCII comment data");
+        
+    comment = jbig2_metadata_new(ctx, JBIG2_ENCODING_ASCII);
+    if (comment == NULL) {
+        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+            "unable to allocate comment structure");
+        return -1;
+    }
+    /* loop over the segment data pulling out the key,value pairs */
+    while(*s && s < end) {
+        key_length = strlen(s) + 1;
+        key = s; s += key_length;
+        if (s >= end) goto too_short;
+        value_length = strlen(s) + 1;
+        value = s; s += value_length;
+        if (s >= end) goto too_short;
+        jbig2_metadata_add(ctx, comment, key, key_length, value, value_length);
+        jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
+            "'%s'\t'%s'", key, value);
+    }
+    
+    /* TODO: associate with ctx, page, or referred-to segment(s) */
+    segment->result = comment;
+    
+    return 0;
+    
+too_short:
+    jbig2_metadata_free(ctx, comment);
+    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+        "unexpected end of comment segment");
+}
+
+/* decode a UCS-16 comment segement 7.4.15.2 */
+int jbig2_parse_comment_unicode(Jbig2Ctx *ctx, Jbig2Segment *segment,
+                               const uint8_t *segment_data)
+{
+    return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+        "unhandled unicode comment segment");
+}
--- /dev/null
+++ b/jbig2_metadata.h
@@ -1,0 +1,46 @@
+/*
+    jbig2dec
+    
+    Copyright (c) 2001-2002 artofcode LLC.
+    
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    $Id: jbig2_metadata.h,v 1.1 2003/03/05 02:44:43 giles Exp $
+*/
+
+
+#ifndef _JBIG2_METADATA_H
+#define _JBIG2_METADATA_H
+
+/* metadata from extension segments */
+
+/* these bits should be moved to jbig2.h for public access */
+typedef enum {
+    JBIG2_ENCODING_ASCII,
+    JBIG2_ENCODING_UCS16
+} Jbig2Encoding;
+
+typedef struct _Jbig2Metadata Jbig2Metadata;
+
+Jbig2Metadata *jbig2_metadata_new(Jbig2Ctx *ctx, Jbig2Encoding encoding);
+void jbig2_metadata_free(Jbig2Ctx *ctx, Jbig2Metadata *md);
+int jbig2_metadata_add(Jbig2Ctx *ctx, Jbig2Metadata *md,
+                        const char *key, const int key_length,
+                        const char *value, const int value_length);
+
+struct _Jbig2Metadata {
+    Jbig2Encoding encoding;
+    char **keys, **values;
+    int entries, max_entries;
+};
+
+/* these bits can go to jbig2_priv.h */
+int jbig2_parse_comment_ascii(Jbig2Ctx *ctx, Jbig2Segment *segment,
+                                const uint8_t *segment_data);
+int jbig2_parse_comment_unicode(Jbig2Ctx *ctx, Jbig2Segment *segment,
+                               const uint8_t *segment_data);
+
+#endif /* _JBIG2_METADATA_H */
--- a/jbig2_segment.c
+++ b/jbig2_segment.c
@@ -8,7 +8,7 @@
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
 
-    $Id: jbig2_segment.c,v 1.20 2003/03/04 17:29:24 giles Exp $
+    $Id: jbig2_segment.c,v 1.21 2003/03/05 02:44:43 giles Exp $
 */
 
 #ifdef HAVE_CONFIG_H
@@ -136,6 +136,39 @@
   info->flags = segment_data[16];
 }
 
+int jbig2_parse_extension_segment(Jbig2Ctx *ctx, Jbig2Segment *segment,
+                            const uint8_t *segment_data)
+{
+    uint32_t type;
+    bool reserved, dependent, necessary;
+
+    type = jbig2_get_int32(segment_data);
+    
+    reserved = type & 0x20000000;
+    dependent = type & 0x40000000;
+    necessary = type & 0x80000000;
+
+    if (necessary && !reserved) {
+        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+            "extension segment is marked 'necessary' but not 'reservered' contrary to spec");
+    }
+    
+    switch (type) {
+        case 0x20000000: return jbig2_parse_comment_ascii(ctx, segment, segment_data);
+        case 0x20000002: return jbig2_parse_comment_unicode(ctx, segment, segment_data);
+        default:
+            if (necessary) {
+                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+                    "unhandled necessary extension segment type 0x%08x", type);
+            } else {
+                return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+                    "unhandled extension segment");
+            }
+    }
+    
+    return 0;
+}
+
 int jbig2_parse_segment (Jbig2Ctx *ctx, Jbig2Segment *segment,
 			 const uint8_t *segment_data)
 {
@@ -198,8 +231,7 @@
       return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
         "unhandled table segment");
     case 62:
-      return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
-        "unhandled extension segment");
+      return jbig2_parse_extension_segment(ctx, segment, segment_data);
     default:
         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
           "unknown segment type %d", segment->flags & 63);