shithub: jbig2

Download patch

ref: e5bdc75cc8afaf2630953f1784381cc6c9305e36
parent: d954b0f143afbf16da24b2ea0a54d88b39af4129
author: giles <giles@ded80894-8fb9-0310-811b-c03f3676ab4d>
date: Wed Jun 8 10:23:43 EDT 2005

Add support for striped page decode. We still return a full
page buffer, so there is no savings in memory footprint.

We now decode 042_9.jb2 from the UBC test streams.


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

--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,7 @@
 Version 0.9 (unreleased)
 
- * no notable changes
+ * striped page support
+ * successfully decodes ubc test stream 042_9
 
 Version 0.8 (2005 April 6)
 
--- a/jbig2.h
+++ b/jbig2.h
@@ -1,7 +1,7 @@
 /*
     jbig2dec
     
-    Copyright (c) 2002-2003 artofcode LLC.
+    Copyright (c) 2002-2005 artofcode LLC.
     
     This software is distributed under license and may not
     be copied, modified or distributed except as expressly
@@ -64,6 +64,8 @@
 void		jbig2_image_release(Jbig2Ctx *ctx, Jbig2Image *image);
 void            jbig2_image_free(Jbig2Ctx *ctx, Jbig2Image *image);
 void		jbig2_image_clear(Jbig2Ctx *ctx, Jbig2Image *image, int value);
+Jbig2Image	*jbig2_image_resize(Jbig2Ctx *ctx, Jbig2Image *image,
+                                int width, int height);
 
 /* errors are returned from the library via a callback. If no callback
    is provided (a NULL argument is passed ot jbig2_ctx_new) a default
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -1,7 +1,7 @@
 /*
     jbig2dec
     
-    Copyright (c) 2002-2004 artofcode LLC.
+    Copyright (c) 2002-2005 artofcode LLC.
     
     This software is provided AS-IS with no warranty,
     either express or implied.
@@ -617,9 +617,8 @@
       jbig2_free(ctx->allocator, GB_stats);
     }
 
-
-  jbig2_image_compose(ctx, ctx->pages[ctx->current_page].image, image,
-			rsi.x, rsi.y, JBIG2_COMPOSE_OR);
+  jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], 
+			image, rsi.x, rsi.y, JBIG2_COMPOSE_OR);
   jbig2_image_release(ctx, image);
   
   return code;
--- a/jbig2_image.c
+++ b/jbig2_image.c
@@ -81,6 +81,33 @@
 	jbig2_free(ctx->allocator, image);
 }
 
+/* resize a Jbig2Image */
+Jbig2Image *jbig2_image_resize(Jbig2Ctx *ctx, Jbig2Image *image, 
+				int width, int height)
+{
+	if (width == image->width) {
+	    /* use the same stride, just change the length */
+	    image->data = jbig2_realloc(ctx->allocator,
+                image->data, image->stride*height);
+            if (image->data == NULL) {
+                return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
+                    "could not resize image buffer!");
+            }
+	    if (height > image->height) {
+		memset(image->data + image->height*image->stride,
+			0, (height - image->height)*image->stride);
+	    }
+            image->height = height;
+
+	} else {
+	    /* we must allocate a new image buffer and copy */
+	    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1,
+		"jbig2_image_resize called with a different width (NYI)");
+	}
+
+	return 0;
+}
+
 /* composite one jbig2_image onto another
    slow but general version */
 int jbig2_image_compose_unopt(Jbig2Ctx *ctx,
--- a/jbig2_page.c
+++ b/jbig2_page.c
@@ -1,7 +1,7 @@
 /*
     jbig2dec
     
-    Copyright (c) 2001-2002 artofcode LLC.
+    Copyright (c) 2001-2005 artofcode LLC.
     
     This software is distributed under license and may not
     be copied, modified or distributed except as expressly
@@ -132,6 +132,7 @@
             "height is unspecified but page is not markes as striped");
         page->striped = TRUE;
     }
+    page->end_row = 0;
     
     if (segment->data_length > 19) {
         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
@@ -164,11 +165,37 @@
 }
 
 /**
+ * jbig2_parse_end_of_stripe: parse an end of stripe segment
+ **/
+int
+jbig2_parse_end_of_stripe(Jbig2Ctx *ctx, Jbig2Segment *segment, const uint8_t *segment_data)
+{
+    Jbig2Page page = ctx->pages[ctx->current_page];
+    int end_row;
+
+    end_row = jbig2_get_int32(segment_data);
+    if (end_row < page.end_row) {
+	jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
+	    "end of stripe segment with non-positive end row advance"
+	    "(new end row %d vs current end row %d)", 
+	    end_row, page.end_row);
+    } else {
+	jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
+	    "end of stripe: advancing end row to %d", end_row);
+    }
+    
+    page.end_row = end_row;
+
+    return 0;
+}
+
+/**
  * jbig2_complete_page: complete a page image
  *
  * called upon seeing an 'end of page' segment, this routine
- * marks a page as completed. final compositing and output
- * of the page image will also happen from here (NYI)
+ * marks a page as completed so it can be returned.
+ * compositing will have already happened in the previous 
+ * segment handlers.
  **/
 int
 jbig2_complete_page (Jbig2Ctx *ctx)
@@ -200,6 +227,35 @@
 #ifdef OUTPUT_PBM
     jbig2_image_write_pbm(ctx->pages[ctx->current_page].image, stdout);
 #endif
+
+    return 0;
+}
+
+/**
+ * jbig2_add_page_result: composite a decoding result onto a page
+ *
+ * this is called to add the results of segment decode (when it
+ * is an image) to a page image buffer
+ **/
+int
+jbig2_page_add_result(Jbig2Ctx *ctx, Jbig2Page *page, Jbig2Image *image,
+		      int x, int y, Jbig2ComposeOp op)
+{
+    /* grow the page to accomodate a new stripe if necessary */
+    if (page->striped) {
+	int old_height = page->image->height;
+	int new_height = y + image->height + page->end_row;
+	if (page->image->height < new_height) {
+	    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1,
+		"growing page buffer to %d rows "
+		"to accomodate new stripe", new_height);
+	    jbig2_image_resize(ctx, page->image,
+		page->image->width, new_height);
+	}
+    }    
+
+    jbig2_image_compose(ctx, page->image, image,
+                        x, y + page->end_row, JBIG2_COMPOSE_OR);
 
     return 0;
 }
--- a/jbig2_priv.h
+++ b/jbig2_priv.h
@@ -115,6 +115,7 @@
              y_resolution;	/* in pixels per meter */
     uint16_t stripe_size;
     bool striped;
+    int end_row;
     uint8_t flags;
     Jbig2Image *image;
 };
@@ -131,6 +132,7 @@
 } Jbig2ComposeOp;
 
 int jbig2_image_compose(Jbig2Ctx *ctx, Jbig2Image *dst, Jbig2Image *src, int x, int y, Jbig2ComposeOp op);
+int jbig2_page_add_result(Jbig2Ctx *ctx, Jbig2Page *page, Jbig2Image *src, int x, int y, Jbig2ComposeOp op);
 
 /* region segment info */
 
--- a/jbig2_refinement.c
+++ b/jbig2_refinement.c
@@ -435,7 +435,7 @@
         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,
+	jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page],
           image, rsi.x, rsi.y, JBIG2_COMPOSE_OR);
         jbig2_image_release(ctx, image);
     }
--- a/jbig2_segment.c
+++ b/jbig2_segment.c
@@ -264,8 +264,7 @@
     case 49:
       return jbig2_parse_end_of_page(ctx, segment, segment_data);
     case 50:
-      return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
-        "unhandled segment type 'end of stripe'");
+      return jbig2_parse_end_of_stripe(ctx, segment, segment_data);
     case 51:
       ctx->state = JBIG2_FILE_EOF;
       return jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,