shithub: jbig2

Download patch

ref: 123697184141b211dfd599a1fb2eb94e8079ce5e
parent: ed23b26857f9d5324a52730e7504c1a14a2d3161
author: giles <giles@ded80894-8fb9-0310-811b-c03f3676ab4d>
date: Fri Jun 21 15:10:02 EDT 2002

Generic regions decode into Jbig2Image structures, which are then (trivially)
composited with the page buffer as the final step in handling the segment.
We now write the page data out at out.png or out.pbm. Compile with -DOUTPUT_PBM
for the old behavior.


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

--- a/jbig2.h
+++ b/jbig2.h
@@ -8,7 +8,7 @@
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
         
-    $Id: jbig2.h,v 1.7 2002/06/18 13:40:29 giles Exp $
+    $Id: jbig2.h,v 1.8 2002/06/21 19:10:02 giles Exp $
 */
 
 #ifdef __cplusplus
@@ -85,6 +85,8 @@
 
 /* get the next available decoded page image */
 Jbig2Image *jbig2_get_page(Jbig2Ctx *ctx);
+/* mark a returned page image as read */
+int jbig2_release_page(Jbig2Ctx *ctx, Jbig2Image *image);
 
 /* segment header routines */
 
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -8,7 +8,7 @@
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
         
-    $Id: jbig2_generic.c,v 1.5 2002/06/20 15:42:47 giles Exp $
+    $Id: jbig2_generic.c,v 1.6 2002/06/21 19:10:02 giles Exp $
 */
 
 /**
@@ -15,8 +15,6 @@
  * Generic region handlers.
  **/
 
-#define OUTPUT_PBM
-
 #include <stdint.h>
 #include <stddef.h>
 #ifdef OUTPUT_PBM
@@ -33,22 +31,23 @@
 			       int32_t seg_number,
 			       const Jbig2GenericRegionParams *params,
 			       Jbig2ArithState *as,
-			       byte *gbreg,
+			       Jbig2Image *image,
 			       Jbig2ArithCx *GB_stats)
 {
-  int GBW = params->GBW;
-  int rowstride = (GBW + 7) >> 3;
+  const int GBW = image->width;
+  const int GBH = image->height;
+  const int rowstride = image->stride;
   int x, y;
-  byte *gbreg_line = gbreg;
+  byte *gbreg_line = (byte *)image->data;
   bool LTP = 0;
 
   /* todo: currently we only handle the nominal gbat location */
 
 #ifdef OUTPUT_PBM
-  printf("P4\n%d %d\n", GBW, params->GBH);
+  printf("P4\n%d %d\n", GBW, GBH);
 #endif
 
-  for (y = 0; y < params->GBH; y++)
+  for (y = 0; y < GBH; y++)
     {
       uint32_t CONTEXT;
       uint32_t line_m1;
@@ -101,22 +100,23 @@
 			       int32_t seg_number,
 			       const Jbig2GenericRegionParams *params,
 			       Jbig2ArithState *as,
-			       byte *gbreg,
+			       Jbig2Image *image,
 			       Jbig2ArithCx *GB_stats)
 {
-  int GBW = params->GBW;
-  int rowstride = (GBW + 7) >> 3;
+  const int GBW = image->width;
+  const int GBH = image->height;
+  const int rowstride = image->stride;
   int x, y;
-  byte *gbreg_line = gbreg;
+  byte *gbreg_line = (byte *)image->data;
   bool LTP = 0;
 
   /* todo: currently we only handle the nominal gbat location */
 
 #ifdef OUTPUT_PBM
-  printf("P4\n%d %d\n", GBW, params->GBH);
+  printf("P4\n%d %d\n", GBW, GBH);
 #endif
 
-  for (y = 0; y < params->GBH; y++)
+  for (y = 0; y < GBH; y++)
     {
       uint32_t CONTEXT;
       uint32_t line_m1;
@@ -169,22 +169,23 @@
 			       int32_t seg_number,
 			       const Jbig2GenericRegionParams *params,
 			       Jbig2ArithState *as,
-			       byte *gbreg,
+			       Jbig2Image *image,
 			       Jbig2ArithCx *GB_stats)
 {
-  int GBW = params->GBW;
-  int rowstride = (GBW + 7) >> 3;
+  const int GBW = image->width;
+  const int GBH = image->height;
+  const int rowstride = image->stride;
   int x, y;
-  byte *gbreg_line = gbreg;
+  byte *gbreg_line = (byte *)image->data;
   bool LTP = 0;
 
   /* todo: currently we only handle the nominal gbat location */
 
 #ifdef OUTPUT_PBM
-  printf("P4\n%d %d\n", GBW, params->GBH);
+  printf("P4\n%d %d\n", GBW, GBH);
 #endif
 
-  for (y = 0; y < params->GBH; y++)
+  for (y = 0; y < GBH; y++)
     {
       uint32_t CONTEXT;
       uint32_t line_m1;
@@ -237,22 +238,23 @@
 			       int32_t seg_number,
 			       const Jbig2GenericRegionParams *params,
 			       Jbig2ArithState *as,
-			       byte *gbreg,
+			       Jbig2Image *image,
 			       Jbig2ArithCx *GB_stats)
 {
-  int GBW = params->GBW;
-  int rowstride = (GBW + 7) >> 3;
+  const int GBW = image->width;
+  const int GBH = image->height;
+  const int rowstride = image->stride;
   int x, y;
-  byte *gbreg_line = gbreg;
+  byte *gbreg_line = (byte *)image->data;
   bool LTP = 0;
 
   /* This is a special case for GBATX1 = 3, GBATY1 = -1 */
 
 #ifdef OUTPUT_PBM
-  printf("P4\n%d %d\n", GBW, params->GBH);
+  printf("P4\n%d %d\n", GBW, GBH);
 #endif
 
-  for (y = 0; y < params->GBH; y++)
+  for (y = 0; y < GBH; y++)
     {
       uint32_t CONTEXT;
       uint32_t line_m1;
@@ -323,23 +325,23 @@
 			    int32_t seg_number,
 			    const Jbig2GenericRegionParams *params,
 			    Jbig2ArithState *as,
-			    byte *gbreg,
+			    Jbig2Image *image,
 			    Jbig2ArithCx *GB_stats)
 {
   if (!params->MMR && params->GBTEMPLATE == 0)
     return jbig2_decode_generic_template0(ctx, seg_number,
-					  params, as, gbreg, GB_stats);
+					  params, as, image, GB_stats);
   else if (!params->MMR && params->GBTEMPLATE == 1)
     return jbig2_decode_generic_template1(ctx, seg_number,
-					  params, as, gbreg, GB_stats);
+					  params, as, image, GB_stats);
   else if (!params->MMR && params->GBTEMPLATE == 2)
     {
       if (params->gbat[0] == 3 && params->gbat[1] == 255)
 	return jbig2_decode_generic_template2a(ctx, seg_number,
-					       params, as, gbreg, GB_stats);
+					       params, as, image, GB_stats);
       else
 	return jbig2_decode_generic_template2(ctx, seg_number,
-					       params, as, gbreg, GB_stats);
+					       params, as, image, GB_stats);
     }
   {
     int i;
@@ -363,7 +365,7 @@
   int gbat_bytes = 0;
   Jbig2GenericRegionParams params;
   int code;
-  byte *gbreg;
+  Jbig2Image *image;
   Jbig2WordStream *ws;
   Jbig2ArithState *as;
   Jbig2ArithCx *GB_stats = NULL;
@@ -410,14 +412,16 @@
   params.GBH = rsi.height;
   memcpy (params.gbat, gbat, gbat_bytes);
 
-  gbreg = jbig2_alloc(ctx->allocator, ((rsi.width + 7) >> 3) * rsi.height);
-
-
+  image = jbig2_image_new(ctx, rsi.width, rsi.height);
+  jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, sh->segment_number,
+    "allocated %d x %d image buffer for region decode results",
+        rsi.width, rsi.height);
+    
   if (params.MMR)
     {
       code = jbig2_decode_generic_mmr(ctx, sh->segment_number, &params,
 				      segment_data + offset, sh->data_length - offset,
-				      gbreg);
+				      image);
     }
   else
     {
@@ -431,12 +435,14 @@
 				     sh->data_length - offset);
       as = jbig2_arith_new(ctx, ws);
       code = jbig2_decode_generic_region(ctx, sh->segment_number, &params,
-					 as, gbreg, GB_stats);
+					 as, image, GB_stats);
     }
 
-  /* todo: stash gbreg as segment result */
   /* todo: free ws, as */
-
+  
+  jbig2_image_compose(ctx, ctx->pages[ctx->current_page].image, image, rsi.x, rsi.y);
+  jbig2_image_free(ctx, image);
+  
   jbig2_free(ctx->allocator, GB_stats);
 
   return code;
--- a/jbig2_generic.h
+++ b/jbig2_generic.h
@@ -8,7 +8,7 @@
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
         
-    $Id: jbig2_generic.h,v 1.3 2002/02/19 07:09:16 giles Exp $
+    $Id: jbig2_generic.h,v 1.4 2002/06/21 19:10:02 giles Exp $
 */
 
 /* Table 2 */
@@ -29,7 +29,7 @@
 			    int32_t seg_number,
 			    const Jbig2GenericRegionParams *params,
 			    Jbig2ArithState *as,
-			    byte *gbreg,
+			    Jbig2Image *image,
 			    Jbig2ArithCx *GB_stats);
 
 /* 7.4 */
--- a/jbig2_image.c
+++ b/jbig2_image.c
@@ -8,7 +8,7 @@
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
 
-    $Id: jbig2_image.c,v 1.5 2002/06/17 16:30:20 giles Exp $
+    $Id: jbig2_image.c,v 1.6 2002/06/21 19:10:02 giles Exp $
 */
 
 #include <stdio.h>
@@ -55,4 +55,19 @@
 {
 	jbig2_free(ctx->allocator, image->data);
 	jbig2_free(ctx->allocator, image);
+}
+
+/* composite one jbig2_image onto another */
+// FIXME: need to add a drawing mode argument
+int jbig2_image_compose(Jbig2Ctx *ctx, Jbig2Image *dst, Jbig2Image *src, int x, int y)
+{
+    /* special case complete replacement */
+    if ((x == 0) && (y == 0) && (src->width == dst->width) && (src->height == dst->height)) {
+        memcpy(dst->data, src->data, src->height*src->stride);
+        return 0;
+    }
+    
+    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1,
+        "non-aligned image composition NYI");
+    return 1;
 }
--- a/jbig2_image_pbm.c
+++ b/jbig2_image_pbm.c
@@ -8,13 +8,12 @@
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
 
-    $Id: jbig2_image_pbm.c,v 1.4 2002/06/17 16:30:20 giles Exp $
+    $Id: jbig2_image_pbm.c,v 1.5 2002/06/21 19:10:02 giles Exp $
 */
 
 #include <stdio.h>
 
 #include "jbig2.h"
-#include "jbig2_priv.h"
 #include "jbig2_image.h"
 
 /* take an image structure and write it to a file in pbm format */
@@ -25,8 +24,8 @@
     int	error;
     
     if ((out = fopen(filename, "wb")) == NULL) {
-		fprintf(stderr, "unable to open '%s' for writing\n", filename);
-		return 1;
+        fprintf(stderr, "unable to open '%s' for writing", filename);
+        return 1;
     }
     
     error = jbig2_image_write_pbm(image, out);
@@ -40,7 +39,7 @@
 int jbig2_image_write_pbm(Jbig2Image *image, FILE *out)
 {
         int i, short_stride, extra_bits;
-        byte *p = (byte *)image->data;
+        char *p = (char *)image->data;
         
         // pbm header
         fprintf(out, "P4\n%d %d\n", image->width, image->height);
@@ -53,8 +52,8 @@
             image->width, image->height, short_stride, extra_bits);
         // write out each row
         for(i = 0; i < image->height; i++) {
-            fwrite(p, sizeof(byte), short_stride, out);
-            if (extra_bits) fwrite(p + short_stride, sizeof(byte), 1, out);
+            fwrite(p, sizeof(*p), short_stride, out);
+            if (extra_bits) fwrite(p + short_stride, sizeof(*p), 1, out);
             p += image->stride;
         }
         
@@ -86,7 +85,7 @@
     int done;
     Jbig2Image *image;
     char c,buf[32];
-    byte *data;
+    char *data;
     
     // look for 'P4' magic
     while ((c = fgetc(in)) != 'P') {
@@ -134,9 +133,9 @@
     // the pbm data is byte-aligned, and our image struct is word-aligned,
     // so we have to index each line separately
     pbm_stride = (dim[0] + 1) >> 3;
-    data = (byte *)image->data;
+    data = (char *)image->data;
     for (i = 0; i < dim[1]; i++) {
-        fread(data, sizeof(byte), pbm_stride, in);
+        fread(data, sizeof(*data), pbm_stride, in);
         if (feof(in)) {
             fprintf(stderr, "unexpected end of pbm file.\n");
             jbig2_image_free(ctx, image);
--- a/jbig2_mmr.c
+++ b/jbig2_mmr.c
@@ -795,16 +795,16 @@
 			 int32_t seg_number,
 			 const Jbig2GenericRegionParams *params,
 			 const byte *data, size_t size,
-			 byte *gbreg)
+			 Jbig2Image *image)
 {
   Jbig2MmrCtx mmr;
-  int rowstride = (params->GBW + 7) >> 3;
-  const byte *gbreg_line = gbreg;
+  const int rowstride = image->stride;
+  const byte *gbreg_line = (const byte *)image->data;
   int y;
 
-  jbig2_decode_mmr_init(&mmr, params->GBW, params->GBH, data, size);
+  jbig2_decode_mmr_init(&mmr, image->width, image->height, data, size);
 
-  for (y = 0; y < params->GBH; y++)
+  for (y = 0; y < image->height; y++)
     {
       jbig2_decode_mmr_line(&mmr, gbreg_line, NULL);
       gbreg_line += rowstride;
--- a/jbig2_mmr.h
+++ b/jbig2_mmr.h
@@ -3,5 +3,5 @@
 			 int32_t seg_number,
 			 const Jbig2GenericRegionParams *params,
 			 const byte *data, size_t size,
-			 byte *gbreg);
+			 Jbig2Image *image);
 
--- a/jbig2_page.c
+++ b/jbig2_page.c
@@ -8,7 +8,7 @@
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
 
-    $Id: jbig2_page.c,v 1.4 2002/06/20 15:40:36 giles Exp $
+    $Id: jbig2_page.c,v 1.5 2002/06/21 19:10:02 giles Exp $
 */
 
 #include <stdio.h>
@@ -17,6 +17,10 @@
 #include "jbig2.h"
 #include "jbig2_priv.h"
 
+#ifdef OUTPUT_PBM
+#include "jbig2_image.h"
+#endif
+
 /* dump the page struct info */
 static void
 dump_page_info(Jbig2Ctx *ctx, Jbig2SegmentHeader *sh, Jbig2Page *page)
@@ -170,7 +174,63 @@
     jbig2_error(ctx, JBIG2_SEVERITY_INFO, sh->segment_number,
         "end of page %d", page_number);
 
-    // FIXME: write out the page image
-    
+#ifdef OUTPUT_PBM
+    jbig2_image_write_pbm(ctx->pages[ctx->current_page].image, stdout);
+#endif
+
     return 0;
+}
+
+/**
+ * jbig2_get_page: return the next available page image buffer
+ *
+ * the client can call this at any time to check if any pages
+ * have been decoded. If so, it returns the first available
+ * one. The client should then call jbig2_release_page() when
+ * it no longer needs to refer to the image buffer.
+ *
+ * since this is a public routine for the library clients, we
+ * return an image structure pointer, even though the function
+ * name refers to a page; the page structure is private.
+ **/
+Jbig2Image *jbig2_get_page(Jbig2Ctx *ctx)
+{
+    int index;
+    Jbig2Image *image;
+
+    /* search for a completed page */
+    for (index=0; index < ctx->max_page_index; index++) {
+        if (ctx->pages[index].state == JBIG2_PAGE_COMPLETE) {
+            ctx->pages[index].state = JBIG2_PAGE_RETURNED;
+            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1,
+                "page %d returned to the client", ctx->pages[index].number);
+            return ctx->pages[index].image;
+        }
+    }
+    
+    /* no pages available */
+    return NULL;
+}
+
+/**
+ * jbig2_release_page: tell the library a page can be freed
+ **/
+int jbig2_release_page(Jbig2Ctx *ctx, Jbig2Image *image)
+{
+    int index;
+    
+    /* find the matching page struct and mark it released */
+    for (index = 0; index < ctx->max_page_index; index++) {
+        if (ctx->pages[index].image == image) {
+            ctx->pages[index].state = JBIG2_PAGE_RELEASED;
+            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, -1,
+                "page %d released by the client", ctx->pages[index].number);
+            return 0;
+        }
+    }
+    
+    /* no matching pages */
+    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, -1,
+        "jbig2_release_page called on unknown page");
+    return 1;
 }
\ No newline at end of file
--- a/jbig2_priv.h
+++ b/jbig2_priv.h
@@ -90,7 +90,8 @@
     JBIG2_PAGE_FREE,
     JBIG2_PAGE_NEW,
     JBIG2_PAGE_COMPLETE,
-    JBIG2_PAGE_RETURNED
+    JBIG2_PAGE_RETURNED,
+    JBIG2_PAGE_RELEASED
 } Jbig2PageState;
 
 struct _Jbig2Page {
@@ -107,6 +108,8 @@
 
 int jbig2_read_page_info (Jbig2Ctx *ctx, Jbig2SegmentHeader *sh, const byte *segment_data);
 int jbig2_complete_page (Jbig2Ctx *ctx, Jbig2SegmentHeader *sh, const byte *segment_data);
+
+int jbig2_image_compose(Jbig2Ctx *ctx, Jbig2Image *dst, Jbig2Image *src, int x, int y);
 
 /* region segment info */
 
--- 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.21 2002/06/18 13:40:29 giles Exp $
+    $Id: jbig2dec.c,v 1.22 2002/06/21 19:10:02 giles Exp $
 */
 
 #include <stdio.h>
@@ -27,6 +27,7 @@
 #endif
 
 #include "jbig2.h"
+#include "jbig2_image.h"
 
 typedef enum {
     usage,dump,render
@@ -257,6 +258,15 @@
 
   filearg = parse_options(argc, argv, &params);
 
+  if (params.output_file == NULL)
+    {
+#ifdef HAVE_LIBPNG
+      params.output_file = "out.png";
+#else
+      params.output_file = "out.pbm";
+#endif
+    }
+    
   if ((argc - filearg) == 1)
   // only one argument--open as a jbig2 file
     {
@@ -324,6 +334,21 @@
       jbig2_global_ctx_free(global_ctx);
     }
 
+  // retrieve and output the returned pages
+  {
+    Jbig2Image *image;
+    
+    while ((image = jbig2_get_page(ctx)) != NULL) {
+        fprintf(stderr, "saving decoded page as '%s'\n", params.output_file);
+#ifdef HAVE_LIBPNG
+        jbig2_image_write_png_file(image, params.output_file);
+#else
+        jbig2_image_write_pbm_file(image, params.output_file);
+#endif
+        jbig2_release_page(ctx, image);
+    }
+  }
+  
   jbig2_ctx_free(ctx);
 
   // fin