ref: 0a396e48949d90a8cd1a91c685af09a165a1f5d9
parent: d8294b25104e9033408c18b68567281ae8e9d5e0
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Nov 23 18:07:35 EST 2020
plan 9 port
--- a/README
+++ /dev/null
@@ -1,32 +1,0 @@
-jbig2dec is a decoder library and example utility implementing the JBIG2
-bi-level image compression spec. Also known as ITU T.88 and ISO IEC
-14492, and included by reference in Adobe's PDF version 1.4 and later.
-
-The basic invocation is:
-
- jbig2dec [-o <output file>] file.jbig2
-
-It also supports separate 'global' and 'page' streams, generally
-extracted from some embedded format:
-
- jbig2dec [-o <output file>] <global_stream> <page_stream>
-
-The program is only partially functional at this time, but should be
-useful in some limited contexts. We welcome files that the decoder can't
-handle, or renders incorrectly.
-
-More information about jbig2dec and updated versions are available from:
-https://jbig2dec.com/
-
-A set of example files is available from
-https://jbig2dec.com/tests/
-
-Development source code is kept in a git repository at:
-http://git.ghostscript.com/?p=jbig2dec.git
-
-Report bugs at https://bugs.ghostscript.com
-For security issues please use the "Security - Other" product,
-and for normal bugs the "jbig2dec" product.
-
-Contact the developers at the IRC channel #ghostscript at freenode.net
-or via the mailing list <gs-devel@ghostscript.com>.
--- /dev/null
+++ b/README.md
@@ -1,0 +1,3 @@
+# jbig2
+
+JBIG2 decoder for Plan 9.
--- /dev/null
+++ b/jb2.c
@@ -1,0 +1,106 @@
+#include "config.h"
+#include "jbig2.h"
+#include "jbig2_priv.h"
+#include "jbig2_image.h"
+#include "jbig2_image_rw.h"
+#include <draw.h>
+#include <memdraw.h>
+
+static void
+usage(void)
+{
+ fprint(2, "usage: %s [-p PAGE]\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ /* this header is inserted in case the input stream doesn't have one (when extracted from a PDF) */
+ uchar header[] = { 0x97, 0x4a, 0x42, 0x32, 0x0d, 0x0a, 0x1a, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x01 };
+ int n, w, h, x, y, page;
+ uchar *rgb, d[8192];
+ Jbig2Image *j;
+ Jbig2Ctx *ctx;
+ Memimage *m;
+
+ page = 0;
+ ARGBEGIN{
+ case 'p':
+ page = atoi(EARGF(usage()));
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(argc != 0)
+ usage();
+
+ memimageinit();
+
+ if((ctx = jbig2_ctx_new(nil, 0, nil, nil, nil)) == nil){
+ werrstr("ctx_new");
+ goto error;
+ }
+ for(x = 0;; x += n){
+ if((n = read(0, d, sizeof(d))) == 0)
+ break;
+ if(n < 0)
+ goto error;
+ if(x == 0 && n >= 8 && memcmp(d, header, 8) != 0)
+ jbig2_data_in(ctx, header, sizeof(header));
+ if(jbig2_data_in(ctx, d, n) < 0){
+ werrstr("data_in");
+ goto error;
+ }
+ }
+ if(jbig2_complete_page(ctx) < 0){
+ werrstr("unable to complete page");
+ goto error;
+ }
+
+ n = page;
+ while((j = jbig2_page_out(ctx)) != nil){
+ if(n > 1){
+ n--;
+ jbig2_release_page(ctx, j);
+ continue;
+ }
+
+ w = j->width;
+ h = j->height;
+ if((rgb = malloc(j->stride*h)) == nil){
+ werrstr("memory");
+ goto error;
+ }
+ for(y = 0; y < h; y++){
+ memmove(rgb+y*j->stride, j->data+y*j->stride, j->stride);
+ for(x = 0; x < j->stride; x++)
+ rgb[y*j->stride+x] = ~rgb[y*j->stride+x];
+ }
+ jbig2_release_page(ctx, j);
+
+ if((m = allocmemimage(Rect(0,0,w,h), GREY1)) == nil){
+ werrstr("memory");
+ goto error;
+ }
+ loadmemimage(m, m->r, rgb, w*h);
+ free(rgb);
+ writememimage(1, m);
+ freememimage(m);
+
+ if(n == 1){
+ n--;
+ break;
+ }
+ }
+ if(n > 0){
+ werrstr("no page %d", page);
+ goto error;
+ }
+
+ exits(nil);
+error:
+ fprint(2, "%r\n");
+ exits("error");
+}
--- a/jbig2.c
+++ b/jbig2.c
@@ -37,6 +37,7 @@
static void *
jbig2_default_alloc(Jbig2Allocator *allocator, size_t size)
{
+ USED(allocator);
return malloc(size);
}
@@ -43,6 +44,7 @@
static void
jbig2_default_free(Jbig2Allocator *allocator, void *p)
{
+ USED(allocator);
free(p);
}
@@ -49,6 +51,7 @@
static void *
jbig2_default_realloc(Jbig2Allocator *allocator, void *p, size_t size)
{
+ USED(allocator);
return realloc(p, size);
}
@@ -73,6 +76,7 @@
static void
jbig2_default_error(void *data, const char *msg, Jbig2Severity severity, uint32_t seg_idx)
{
+ USED(data);
/* report only fatal errors by default */
if (severity == JBIG2_SEVERITY_FATAL) {
fprintf(stderr, "jbig2 decoder FATAL ERROR: %s", msg);
@@ -116,7 +120,7 @@
if (allocator == NULL)
allocator = &jbig2_default_allocator;
if (error_callback == NULL)
- error_callback = &jbig2_default_error;
+ error_callback = jbig2_default_error;
result = (Jbig2Ctx *) jbig2_alloc(allocator, sizeof(Jbig2Ctx), 1);
if (result == NULL) {
--- a/jbig2.h
+++ b/jbig2.h
@@ -43,6 +43,7 @@
/* forward public structure declarations */
typedef struct _Jbig2Allocator Jbig2Allocator;
typedef struct _Jbig2Ctx Jbig2Ctx;
+#pragma incomplete Jbig2Ctx
typedef struct _Jbig2GlobalCtx Jbig2GlobalCtx;
/*
--- a/jbig2_arith.h
+++ b/jbig2_arith.h
@@ -21,6 +21,7 @@
#define _JBIG2_ARITH_H
typedef struct _Jbig2ArithState Jbig2ArithState;
+#pragma incomplete Jbig2ArithState
/* An arithmetic coding context is stored as a single byte, with the
index in the low order 7 bits (actually only 6 are used), and the
--- a/jbig2_arith_iaid.h
+++ b/jbig2_arith_iaid.h
@@ -21,6 +21,7 @@
#define _JBIG2_ARITH_IAID_H
typedef struct _Jbig2ArithIaidCtx Jbig2ArithIaidCtx;
+#pragma incomplete Jbig2ArithIaidCtx
Jbig2ArithIaidCtx *jbig2_arith_iaid_ctx_new(Jbig2Ctx *ctx, uint8_t SBSYMCODELEN);
--- a/jbig2_arith_int.h
+++ b/jbig2_arith_int.h
@@ -21,6 +21,7 @@
#define _JBIG2_ARITH_INT_H
typedef struct _Jbig2ArithIntCtx Jbig2ArithIntCtx;
+#pragma incomplete Jbig2ArithIntCtx
Jbig2ArithIntCtx *jbig2_arith_int_ctx_new(Jbig2Ctx *ctx);
--- a/jbig2_generic.c
+++ b/jbig2_generic.c
@@ -358,6 +358,7 @@
{
int stats_size = template == 0 ? 1 << 16 : template == 1 ? 1 << 13 : 1 << 10;
+ USED(ctx);
return stats_size;
}
@@ -375,6 +376,7 @@
byte *line1 = NULL;
byte *gbreg_line = (byte *) image->data;
+ USED(params);
#ifdef OUTPUT_PBM
printf("P4\n%d %d\n", GBW, GBH);
#endif
@@ -428,7 +430,7 @@
}
#define pixel_outside_field(x, y) \
- ((y) < -128 || (y) > 0 || (x) < -128 || ((y) < 0 && (x) > 127) || ((y) == 0 && (x) >= 0))
+ ((y) > 0 || ((y) == 0 && (x) >= 0))
static int
jbig2_decode_generic_template0_unopt(Jbig2Ctx *ctx,
@@ -581,6 +583,7 @@
byte *line1 = NULL;
byte *gbreg_line = (byte *) image->data;
+ USED(params);
#ifdef OUTPUT_PBM
printf("P4\n%d %d\n", GBW, GBH);
#endif
@@ -713,6 +716,7 @@
byte *line1 = NULL;
byte *gbreg_line = (byte *) image->data;
+ USED(params);
#ifdef OUTPUT_PBM
printf("P4\n%d %d\n", GBW, GBH);
#endif
@@ -777,6 +781,7 @@
byte *gbreg_line = (byte *) image->data;
uint32_t x, y;
+ USED(params);
#ifdef OUTPUT_PBM
printf("P4\n%d %d\n", GBW, GBH);
#endif
@@ -1394,8 +1399,8 @@
int offset;
uint32_t gbat_bytes = 0;
Jbig2GenericRegionParams params;
- int code = 0;
- Jbig2Image *image = NULL;
+ int code;
+ Jbig2Image *image;
Jbig2WordStream *ws = NULL;
Jbig2ArithState *as = NULL;
Jbig2ArithCx *GB_stats = NULL;
--- a/jbig2_halftone.c
+++ b/jbig2_halftone.c
@@ -135,9 +135,9 @@
const Jbig2PatternDictParams *params, const byte *data, const size_t size, Jbig2ArithCx *GB_stats)
{
Jbig2PatternDict *hd = NULL;
- Jbig2Image *image = NULL;
+ Jbig2Image *image;
Jbig2GenericRegionParams rparams;
- int code = 0;
+ int code;
/* allocate the collective image */
image = jbig2_image_new(ctx, params->HDPW * (params->GRAYMAX + 1), params->HDPH);
@@ -420,7 +420,7 @@
{
int index = 0;
Jbig2PatternDict *pattern_dict = NULL;
- Jbig2Segment *rsegment = NULL;
+ Jbig2Segment *rsegment;
/* loop through all referred segments */
while (!pattern_dict && segment->referred_to_segment_count > index) {
@@ -556,9 +556,9 @@
int offset = 0;
Jbig2RegionSegmentInfo region_info;
Jbig2HalftoneRegionParams params;
- Jbig2Image *image = NULL;
+ Jbig2Image *image;
Jbig2ArithCx *GB_stats = NULL;
- int code = 0;
+ int code;
/* 7.4.5.1 */
if (segment->data_length < 17)
--- a/jbig2_huffman.c
+++ b/jbig2_huffman.c
@@ -67,7 +67,7 @@
Jbig2HuffmanState *
jbig2_huffman_new(Jbig2Ctx *ctx, Jbig2WordStream *ws)
{
- Jbig2HuffmanState *result = NULL;
+ Jbig2HuffmanState *result;
int code;
result = jbig2_new(ctx, Jbig2HuffmanState, 1);
--- a/jbig2_huffman.h
+++ b/jbig2_huffman.h
@@ -26,6 +26,7 @@
typedef struct _Jbig2HuffmanState Jbig2HuffmanState;
typedef struct _Jbig2HuffmanTable Jbig2HuffmanTable;
typedef struct _Jbig2HuffmanParams Jbig2HuffmanParams;
+#pragma incomplete Jbig2HuffmanState
struct _Jbig2HuffmanEntry {
union {
--- a/jbig2_image.c
+++ b/jbig2_image.c
@@ -75,6 +75,7 @@
Jbig2Image *
jbig2_image_reference(Jbig2Ctx *ctx, Jbig2Image *image)
{
+ USED(ctx);
if (image)
image->refcount++;
return image;
@@ -344,6 +345,7 @@
uint32_t bytewidth;
uint32_t syoffset = 0;
+ USED(ctx);
if (src == NULL)
return 0;
@@ -460,6 +462,7 @@
{
const uint8_t fill = value ? 0xFF : 0x00;
+ USED(ctx);
memset(image->data, fill, image->stride * image->height);
}
--- a/jbig2_mmr.c
+++ b/jbig2_mmr.c
@@ -1200,6 +1200,7 @@
int code = 0;
int eofb = 0;
+ USED(params);
jbig2_decode_mmr_init(&mmr, image->width, image->height, data, size);
for (y = 0; !eofb && y < image->height; y++) {
@@ -1244,6 +1245,7 @@
const uint32_t EOFB = 0x001001;
int eofb = 0;
+ USED(params);
jbig2_decode_mmr_init(&mmr, image->width, image->height, data, size);
for (y = 0; !eofb && y < image->height; y++) {
--- a/jbig2_page.c
+++ b/jbig2_page.c
@@ -239,6 +239,7 @@
uint32_t page_number = ctx->pages[ctx->current_page].number;
int code;
+ USED(segment_data);
if (segment->page_association != page_number) {
jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
"end of page marker for page %d doesn't match current page number %d", segment->page_association, page_number);
@@ -286,7 +287,7 @@
new_height = y + image->height;
if (page->image->height < new_height) {
- Jbig2Image *resized_image = NULL;
+ Jbig2Image *resized_image;
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, JBIG2_UNKNOWN_SEGMENT_NUMBER, "growing page buffer to %u rows to accommodate new stripe", new_height);
resized_image = jbig2_image_resize(ctx, page->image, page->image->width, new_height, page->flags & 4);
--- a/jbig2_priv.h
+++ b/jbig2_priv.h
@@ -67,6 +67,7 @@
typedef struct _Jbig2Page Jbig2Page;
typedef struct _Jbig2Segment Jbig2Segment;
+#pragma incomplete Jbig2Segment
typedef enum {
JBIG2_FILE_HEADER,
@@ -137,6 +138,7 @@
32 bit word. The offset argument is provided as a convenience. It
begins at 0 and increments by 4 for each successive invocation. */
typedef struct _Jbig2WordStream Jbig2WordStream;
+#pragma incomplete Jbig2WordStream
struct _Jbig2WordStream {
int (*get_next_word)(Jbig2Ctx *ctx, Jbig2WordStream *self, size_t offset, uint32_t *word);
--- a/jbig2_refinement.c
+++ b/jbig2_refinement.c
@@ -41,9 +41,9 @@
#include "jbig2_segment.h"
#define pixel_outside_field(x, y) \
- ((y) < -128 || (y) > 0 || (x) < -128 || ((y) < 0 && (x) > 127) || ((y) == 0 && (x) >= 0))
+ ((y) > 0 || ((y) == 0 && (x) >= 0))
#define refpixel_outside_field(x, y) \
- ((y) < -128 || (y) > 127 || (x) < -128 || (x) > 127)
+ (0)
static int
jbig2_decode_refinement_template0_unopt(Jbig2Ctx *ctx,
@@ -244,6 +244,7 @@
int j = y - params->GRREFERENCEDY;
int m = jbig2_image_get_pixel(ref, i, j);
+ USED(image);
return ((jbig2_image_get_pixel(ref, i - 1, j - 1) == m) &&
(jbig2_image_get_pixel(ref, i, j - 1) == m) &&
(jbig2_image_get_pixel(ref, i + 1, j - 1) == m) &&
@@ -422,7 +423,7 @@
Jbig2RegionSegmentInfo rsi;
int offset = 0;
byte seg_flags;
- int code = 0;
+ int code;
/* 7.4.7 */
if (segment->data_length < 18)
@@ -488,7 +489,7 @@
Jbig2ArithState *as = NULL;
Jbig2ArithCx *GR_stats = NULL;
int stats_size;
- Jbig2Image *image = NULL;
+ Jbig2Image *image;
image = jbig2_image_new(ctx, rsi.width, rsi.height);
if (image == NULL) {
--- a/jbig2_symbol_dict.c
+++ b/jbig2_symbol_dict.c
@@ -95,7 +95,7 @@
Jbig2SymbolDict *
jbig2_sd_new(Jbig2Ctx *ctx, uint32_t n_symbols)
{
- Jbig2SymbolDict *new_dict = NULL;
+ Jbig2SymbolDict *new_dict;
new_dict = jbig2_new(ctx, Jbig2SymbolDict, 1);
if (new_dict != NULL) {
@@ -200,7 +200,7 @@
jbig2_sd_cat(Jbig2Ctx *ctx, uint32_t n_dicts, Jbig2SymbolDict **dicts)
{
uint32_t i, j, k, symbols;
- Jbig2SymbolDict *new_dict = NULL;
+ Jbig2SymbolDict *new_dict;
/* count the imported symbols and allocate a new array */
symbols = 0;
@@ -236,10 +236,10 @@
uint32_t SYMWIDTH, TOTWIDTH;
uint32_t HCFIRSTSYM;
uint32_t *SDNEWSYMWIDTHS = NULL;
- uint8_t SBSYMCODELEN = 0;
- Jbig2WordStream *ws = NULL;
+ uint8_t SBSYMCODELEN;
+ Jbig2WordStream *ws;
Jbig2HuffmanState *hs = NULL;
- Jbig2ArithState *as = NULL;
+ Jbig2ArithState *as;
Jbig2ArithIntCtx *IADH = NULL;
Jbig2ArithIntCtx *IADW = NULL;
Jbig2ArithIntCtx *IAEX = NULL;
@@ -863,8 +863,8 @@
uint16_t flags;
uint32_t sdat_bytes;
uint32_t offset;
- Jbig2ArithCx *GB_stats = NULL;
- Jbig2ArithCx *GR_stats = NULL;
+ Jbig2ArithCx *GB_stats;
+ Jbig2ArithCx *GR_stats;
int table_index = 0;
const Jbig2HuffmanParams *huffman_params;
@@ -963,6 +963,7 @@
}
params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
+ USED(table_index);
} else {
/* Table B.1 */
params.SDHUFFAGGINST = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
@@ -1014,7 +1015,7 @@
/* 7.4.2.2 (2) */
{
uint32_t n_dicts = jbig2_sd_count_referred(ctx, segment);
- Jbig2SymbolDict **dicts = NULL;
+ Jbig2SymbolDict **dicts;
if (n_dicts > 0) {
dicts = jbig2_sd_list_referred(ctx, segment);
--- a/jbig2_text.c
+++ b/jbig2_text.c
@@ -70,7 +70,7 @@
int32_t DT;
int32_t DFS;
int32_t IDS;
- int32_t CURS;
+ int32_t CURS = 0;
int32_t CURT;
int S, T;
int x, y;
@@ -84,6 +84,7 @@
int code = 0;
int RI;
+ USED(size, data);
SBNUMSYMS = 0;
for (index = 0; index < n_dicts; index++) {
SBNUMSYMS += dicts[index]->n_symbols;
@@ -96,7 +97,7 @@
Jbig2HuffmanLine runcodelengths[35];
Jbig2HuffmanLine *symcodelengths = NULL;
Jbig2HuffmanParams symcodeparams;
- int err, len, range, r;
+ int err, len, range = 0, r;
jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "huffman coded text region");
hs = jbig2_huffman_new(ctx, ws);
@@ -583,15 +584,15 @@
Jbig2TextRegionParams params;
Jbig2Image *image = NULL;
Jbig2SymbolDict **dicts = NULL;
- uint32_t n_dicts = 0;
- uint16_t flags = 0;
+ uint32_t n_dicts;
+ uint16_t flags;
uint16_t huffman_flags = 0;
Jbig2ArithCx *GR_stats = NULL;
- int code = 0;
- Jbig2WordStream *ws = NULL;
- Jbig2ArithState *as = NULL;
+ int code;
+ Jbig2WordStream *ws;
+ Jbig2ArithState *as;
uint32_t table_index = 0;
- const Jbig2HuffmanParams *huffman_params = NULL;
+ const Jbig2HuffmanParams *huffman_params;
/* zero params to ease cleanup later */
memset(¶ms, 0, sizeof(Jbig2TextRegionParams));
@@ -872,6 +873,7 @@
}
params.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, huffman_params);
++table_index;
+ USED(table_index);
break;
}
if (params.SBHUFFRSIZE == NULL) {
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,18 @@
+</$objtype/mkfile
+
+BIN=/$objtype/bin
+TARG=jbig2
+CFLAGS=$CFLAGS -p -Iplan9
+CLEANFILES=libjbig2.a
+
+OFILES=\
+ jb2.$O\
+
+default:V: all
+
+</sys/src/cmd/mkone
+
+jb2.$O: libjbig2.a
+
+libjbig2.a:
+ mk -f mklib
--- /dev/null
+++ b/mklib
@@ -1,0 +1,43 @@
+</$objtype/mkfile
+LIB=libjbig2.a
+CFLAGS=$CFLAGS -p -Iplan9 -DHAVE_CONFIG_H
+
+OFILES=\
+ jbig2.$O\
+ jbig2_arith.$O\
+ jbig2_arith_iaid.$O\
+ jbig2_arith_int.$O\
+ jbig2_generic.$O\
+ jbig2_halftone.$O\
+ jbig2_huffman.$O\
+ jbig2_hufftab.$O\
+ jbig2_image.$O\
+ jbig2_mmr.$O\
+ jbig2_page.$O\
+ jbig2_refinement.$O\
+ jbig2_segment.$O\
+ jbig2_symbol_dict.$O\
+ jbig2_text.$O\
+
+HFILES=\
+ plan9/config.h\
+ jbig2.h\
+ jbig2_arith.h\
+ jbig2_arith_iaid.h\
+ jbig2_arith_int.h\
+ jbig2_generic.h\
+ jbig2_halftone.h\
+ jbig2_huffman.h\
+ jbig2_hufftab.h\
+ jbig2_image.h\
+ jbig2_image_rw.h\
+ jbig2_mmr.h\
+ jbig2_page.h\
+ jbig2_priv.h\
+ jbig2_refinement.h\
+ jbig2_segment.h\
+ jbig2_symbol_dict.h\
+ jbig2_text.h\
+ os_types.h\
+
+</sys/src/cmd/mklib
--- /dev/null
+++ b/plan9/config.h
@@ -1,0 +1,26 @@
+/* configuration header file for compiling under Plan 9 */
+
+#ifndef __CONFIG_H__
+#define __CONFIG_H__
+
+#include <u.h>
+#include <libc.h>
+#include </sys/include/stdio.h>
+
+#pragma lib "./libjbig2.a"
+
+typedef s8int int8_t;
+typedef s16int int16_t;
+typedef s32int int32_t;
+typedef s64int int64_t;
+
+typedef u8int uint8_t;
+typedef u16int uint16_t;
+typedef u32int uint32_t;
+typedef u64int uint64_t;
+
+typedef ulong size_t;
+
+#define SIZE_MAX (~((size_t)0))
+
+#endif