shithub: jbig2

Download patch

ref: cf1418dc01a996a8f351918a5fd6202ce02a22d5
parent: e161b891ac484992cfff4127332498fb46125fa8
author: giles <giles@ded80894-8fb9-0310-811b-c03f3676ab4d>
date: Wed Nov 24 02:14:03 EST 2004

Implement generic refinement region segment handling. Decoding is still 
not correct.


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

--- a/jbig2_refinement.c
+++ b/jbig2_refinement.c
@@ -227,3 +227,164 @@
                                              as, image, GB_stats);
 }
 
+/**
+ * Find the first referred-to intermediate region segment
+ * with a non-NULL result for use as a reference image
+ */
+Jbig2Segment *
+jbig2_region_find_referred(Jbig2Ctx *ctx,Jbig2Segment *segment)
+{
+  const int nsegments = segment->referred_to_segment_count;
+  Jbig2Segment *rsegment;
+  int index;
+
+  for (index = 0; index < nsegments; index++) {
+    rsegment = jbig2_find_segment(ctx, 
+      segment->referred_to_segments[index]);
+    if (rsegment == NULL) {
+      jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+        "could not find referred to segment %d",
+        segment->referred_to_segments[index]);
+      continue;
+    }
+    switch (rsegment->flags & 63) {
+      case 4:  /* intermediate text region */
+      case 20: /* intermediate halftone region */
+      case 36: /* intermediate generic region */
+      case 40: /* intermediate generic refinement region */
+        if (rsegment->result) return rsegment;
+	break;
+      default: /* keep looking */
+        break;
+    }
+  }
+  /* no appropriate reference was found. */
+  return NULL;
+}
+
+/** 
+ * Handler for immediate generic region segments
+ */
+int
+jbig2_refinement_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
+                               const byte *segment_data)
+{
+  Jbig2RefinementRegionParams params;
+  Jbig2RegionSegmentInfo rsi;
+  int offset = 0;
+  byte seg_flags;
+  
+  /* 7.4.7 */
+  if (segment->data_length < 18)
+    return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+                       "Segment too short");
+
+  jbig2_get_region_segment_info(&rsi, segment_data);
+  jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
+              "generic region: %d x %d @ (%d, %d), flags = %02x",
+              rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags);
+
+  /* 7.4.7.2 */
+  seg_flags = segment_data[17];
+  params.GRTEMPLATE = seg_flags & 0x01;
+  params.TPGDON = seg_flags & 0x02;
+  jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
+              "segment flags = %02x %s%s", seg_flags,
+              params.GRTEMPLATE ? " GRTEMPLATE" :"",
+              params.TPGDON ? " TPGON" : "" );
+  if (seg_flags & 0xFC)
+    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+                "reserved segment flag bits are non-zero");
+  offset += 18;
+
+  /* 7.4.7.3 */
+  if (params.GRTEMPLATE) {
+    if (segment->data_length < 22)
+      return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+                         "Segment too short");
+    params.grat[0] = (signed char)segment_data[offset + 0];
+    params.grat[1] = (signed char)segment_data[offset + 1];
+    params.grat[2] = (signed char)segment_data[offset + 2];
+    params.grat[3] = (signed char)segment_data[offset + 3];
+    jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
+                   "grat1: (%d, %d) grat2: (%d, %d)", 
+                   params.grat[0], params.grat[1],
+                   params.grat[2], params.grat[3]);
+    offset += 4;
+  }
+
+  /* 7.4.7.4 - set up the reference image */
+  if (segment->referred_to_segment_count) {
+    Jbig2Segment *ref;
+
+    ref = jbig2_region_find_referred(ctx, segment);
+    if (ref == NULL)
+      return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+        "could not find reference bitmap!");
+    /* the reference bitmap is the result of a previous 
+       intermediate region segment; the reference selection
+       rules say to use the first one available, and not to
+       reuse any intermediate result, so we simply clone it
+       and free the original to keep track of this. */
+    params.reference = jbig2_image_clone(ctx, ref->result);
+    jbig2_image_release(ctx, ref->result);
+    ref->result = NULL;
+    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
+      "found reference bitmap in segment %d", ref->number);
+    jbig2_image_write_pbm_file(params.reference, "ref.pbm");
+  } else {
+    /* the reference is just (a subset of) the page buffer */
+    params.reference = jbig2_image_clone(ctx, 
+      ctx->pages[ctx->current_page].image);
+    /* TODO: subset the image if appropriate */
+  }
+
+  /* 7.4.7.5 */
+  params.DX = 0;
+  params.DY = 0;
+  {
+    Jbig2WordStream *ws;
+    Jbig2ArithState *as;
+    Jbig2ArithCx *GB_stats = NULL;
+    int stats_size;
+    Jbig2Image *image;
+    int code;
+
+    image = jbig2_image_new(ctx, rsi.width, rsi.height);
+    if (image == NULL)
+      return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
+               "unable to allocate image storage");
+    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
+      "allocated %d x %d image buffer for region decode results",
+          rsi.width, rsi.height);
+
+    stats_size = params.GRTEMPLATE ? 1 << 13 : 1 << 10;
+    GB_stats = jbig2_alloc(ctx->allocator, stats_size);
+    memset(GB_stats, 0, stats_size);
+
+    ws = jbig2_word_stream_buf_new(ctx, segment_data + offset,
+           segment->data_length - offset);
+    as = jbig2_arith_new(ctx, ws);
+    code = jbig2_decode_refinement_region(ctx, segment, &params,
+                              as, image, GB_stats);
+    jbig2_image_write_pbm_file(image, "result.pbm");
+
+    /* TODO: free ws, as */
+    jbig2_free(ctx->allocator, GB_stats);
+
+    if ((segment->flags & 63) == 40) {
+        /* intermediate region. save the result for later */
+	segment->result = image;
+    } else {
+	/* immediate region. composite onto the page */
+        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
+            "composing %dx%d decoded refinement region onto page at (%d, %d)",
+            rsi.width, rsi.height, rsi.x, rsi.y);
+	jbig2_image_compose(ctx, ctx->pages[ctx->current_page].image,
+          image, rsi.x, rsi.y, JBIG2_COMPOSE_OR);
+        jbig2_image_release(ctx, image);
+    }
+  }
+
+  return 0;
+}
--- a/jbig2_segment.c
+++ b/jbig2_segment.c
@@ -237,15 +237,10 @@
     case 39:
       return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
         "unhandled segment type 'immediate lossless generic region'");
-    case 40:
-      return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
-        "unhandled segment type 'intermediate generic refinement region'");
-    case 42:
-      return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
-        "unhandled segment type 'immediate generic refinement region'");
-    case 43:
-      return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
-        "unhandled segment type 'immediate lossless generic refinement region'");
+    case 40: /* intermediate generic refinement region */
+    case 42: /* immediate generic refinement region */
+    case 43: /* immediate lossless generic refinement region */
+      return jbig2_refinement_region(ctx, segment, segment_data);
     case 48:
       return jbig2_parse_page_info(ctx, segment, segment_data);
     case 49: