Moved g4 encoding functions from pdf library to bitblt library.
This commit is contained in:
21
Makefile
21
Makefile
@@ -1,6 +1,6 @@
|
||||
# t2p: build a PDF file out of one or more TIFF Class F Group 4 files
|
||||
# Makefile
|
||||
# $Id: Makefile,v 1.20 2003/03/08 02:02:13 eric Exp $
|
||||
# $Id: Makefile,v 1.21 2003/03/10 01:49:49 eric Exp $
|
||||
# Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
@@ -62,9 +62,8 @@ PACKAGE = t2p
|
||||
TARGETS = t2p
|
||||
|
||||
CSRCS = t2p.c semantics.c \
|
||||
bitblt.c bitblt_table_gen.c \
|
||||
pdf_g4.c pdf_g4_table_gen.c \
|
||||
pdf.c pdf_util.c pdf_prim.c pdf_bookmark.c pdf_name_tree.c
|
||||
bitblt.c bitblt_table_gen.c bitblt_g4.c g4_table_gen.c \
|
||||
pdf.c pdf_util.c pdf_prim.c pdf_bookmark.c pdf_name_tree.c pdf_g4.c
|
||||
OSRCS = scanner.l parser.y
|
||||
HDRS = t2p.h semantics.h bitblt.h \
|
||||
pdf.h pdf_private.h pdf_util.h pdf_prim.h pdf_name_tree.h
|
||||
@@ -75,7 +74,7 @@ DISTNAME = $(PACKAGE)-$(VERSION)
|
||||
|
||||
|
||||
AUTO_CSRCS = scanner.c parser.tab.c
|
||||
AUTO_HDRS = parser.tab.h bitblt_tables.h pdf_g4_tables.h
|
||||
AUTO_HDRS = parser.tab.h bitblt_tables.h g4_tables.h
|
||||
AUTO_MISC = parser.output
|
||||
|
||||
|
||||
@@ -85,9 +84,9 @@ AUTO_MISC = parser.output
|
||||
all: $(TARGETS) $(TEST_TARGETS)
|
||||
|
||||
|
||||
t2p: t2p.o scanner.o semantics.o parser.tab.o bitblt.o \
|
||||
pdf_g4.o \
|
||||
pdf.o pdf_util.o pdf_prim.o pdf_bookmark.o pdf_name_tree.o
|
||||
t2p: t2p.o scanner.o semantics.o parser.tab.o bitblt.o bitblt_g4.o \
|
||||
pdf.o pdf_util.o pdf_prim.o pdf_bookmark.o pdf_name_tree.o \
|
||||
pdf_g4.o
|
||||
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
|
||||
ifndef DEBUG
|
||||
strip $@
|
||||
@@ -99,10 +98,10 @@ bitblt_tables.h: bitblt_table_gen
|
||||
|
||||
bitblt_table_gen: bitblt_table_gen.o
|
||||
|
||||
pdf_g4_tables.h: pdf_g4_table_gen
|
||||
./pdf_g4_table_gen >pdf_g4_tables.h
|
||||
g4_tables.h: g4_table_gen
|
||||
./g4_table_gen >g4_tables.h
|
||||
|
||||
pdf_g4_table_gen: pdf_g4_table_gen.o
|
||||
g4_table_gen: g4_table_gen.o
|
||||
|
||||
|
||||
dist: $(DISTFILES)
|
||||
|
||||
5
bitblt.h
5
bitblt.h
@@ -4,7 +4,7 @@
|
||||
* will be compressed using ITU-T T.6 (G4) fax encoding.
|
||||
*
|
||||
* bitblt routines
|
||||
* $Id: bitblt.h,v 1.12 2003/02/23 09:40:41 eric Exp $
|
||||
* $Id: bitblt.h,v 1.13 2003/03/10 01:49:50 eric Exp $
|
||||
* Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -128,3 +128,6 @@ int32_t get_row_run_lengths (Bitmap *src,
|
||||
int32_t min_x, int32_t max_x,
|
||||
int32_t max_runs,
|
||||
run_t *runs);
|
||||
|
||||
|
||||
void bitblt_write_g4 (Bitmap *bitmap, FILE *f);
|
||||
|
||||
278
bitblt_g4.c
278
bitblt_g4.c
@@ -3,8 +3,8 @@
|
||||
* bilevel image files. The images in the resulting PDF file
|
||||
* will be compressed using ITU-T T.6 (G4) fax encoding.
|
||||
*
|
||||
* PDF routines
|
||||
* $Id: bitblt_g4.c,v 1.8 2003/03/05 12:44:33 eric Exp $
|
||||
* G4 compression
|
||||
* $Id: bitblt_g4.c,v 1.9 2003/03/10 01:49:50 eric Exp $
|
||||
* Copyright 2003 Eric Smith <eric@brouhaha.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -32,108 +32,111 @@
|
||||
|
||||
|
||||
#include "bitblt.h"
|
||||
#include "pdf.h"
|
||||
#include "pdf_util.h"
|
||||
#include "pdf_prim.h"
|
||||
#include "pdf_private.h"
|
||||
|
||||
|
||||
#include "pdf_g4_tables.h"
|
||||
#include "g4_tables.h"
|
||||
|
||||
|
||||
#define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
|
||||
#define BIT_BUF_SIZE 4096
|
||||
|
||||
|
||||
struct pdf_g4_image
|
||||
struct bit_buffer
|
||||
{
|
||||
double width, height;
|
||||
double x, y;
|
||||
double r, g, b; /* fill color, only for ImageMask */
|
||||
unsigned long Columns;
|
||||
unsigned long Rows;
|
||||
bool ImageMask;
|
||||
bool BlackIs1;
|
||||
Bitmap *bitmap;
|
||||
char XObject_name [4];
|
||||
FILE *f;
|
||||
uint32_t byte_idx; /* index to next byte position in data buffer */
|
||||
uint32_t bit_idx; /* index to next bit position in data buffer,
|
||||
0 = MSB, 7 = LSB */
|
||||
uint8_t data [BIT_BUF_SIZE];
|
||||
};
|
||||
|
||||
|
||||
char pdf_new_XObject (pdf_page_handle pdf_page, struct pdf_obj *ind_ref)
|
||||
static void flush_bits (struct bit_buffer *buf)
|
||||
{
|
||||
char XObject_name [4] = "Im ";
|
||||
|
||||
XObject_name [2] = ++pdf_page->last_XObject_name;
|
||||
|
||||
if (! pdf_page->XObject_dict)
|
||||
size_t s;
|
||||
if (buf->bit_idx)
|
||||
{
|
||||
pdf_page->XObject_dict = pdf_new_obj (PT_DICTIONARY);
|
||||
pdf_set_dict_entry (pdf_page->resources, "XObject", pdf_page->XObject_dict);
|
||||
/* zero remaining bits in last byte */
|
||||
buf->data [buf->byte_idx] &= ~ ((1 << (8 - buf->bit_idx)) - 1);
|
||||
buf->byte_idx++;
|
||||
buf->bit_idx = 0;
|
||||
}
|
||||
|
||||
pdf_set_dict_entry (pdf_page->XObject_dict, & XObject_name [0], ind_ref);
|
||||
|
||||
return (pdf_page->last_XObject_name);
|
||||
s = fwrite (& buf->data [0], 1, buf->byte_idx, buf->f);
|
||||
/* $$$ should check result */
|
||||
buf->byte_idx = 0;
|
||||
}
|
||||
|
||||
|
||||
void pdf_write_g4_content_callback (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream,
|
||||
void *app_data)
|
||||
static void advance_byte (struct bit_buffer *buf)
|
||||
{
|
||||
struct pdf_g4_image *image = app_data;
|
||||
|
||||
/* transformation matrix is: width 0 0 height x y cm */
|
||||
pdf_stream_printf (pdf_file, stream, "q %g 0 0 %g %g %g cm ",
|
||||
image->width, image->height,
|
||||
image->x, image->y);
|
||||
if (image->ImageMask)
|
||||
pdf_stream_printf (pdf_file, stream, "%g %g %g rg ",
|
||||
image->r, image->g, image->b);
|
||||
|
||||
pdf_stream_printf (pdf_file, stream, "/%s Do Q\r\n",
|
||||
image->XObject_name);
|
||||
buf->byte_idx++;
|
||||
buf->bit_idx = 0;
|
||||
if (buf->byte_idx == BIT_BUF_SIZE)
|
||||
flush_bits (buf);
|
||||
}
|
||||
|
||||
|
||||
static void pdf_g4_encode_horizontal_run (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream,
|
||||
bool black,
|
||||
uint32_t run_length)
|
||||
static void write_bits (struct bit_buffer *buf,
|
||||
uint32_t count,
|
||||
uint32_t bits)
|
||||
{
|
||||
uint32_t b2; /* how many bits will fit in byte in data buffer */
|
||||
uint32_t c2; /* how many bits to transfer on this iteration */
|
||||
uint32_t d2; /* bits to transfer on this iteration */
|
||||
|
||||
while (count)
|
||||
{
|
||||
b2 = 8 - buf->bit_idx;
|
||||
if (b2 >= count)
|
||||
c2 = count;
|
||||
else
|
||||
c2 = b2;
|
||||
d2 = bits >> (count - c2);
|
||||
buf->data [buf->byte_idx] |= (d2 << (b2 + c2));
|
||||
buf->bit_idx += c2;
|
||||
if (buf->bit_idx > 7)
|
||||
advance_byte (buf);
|
||||
count -= c2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void g4_encode_horizontal_run (struct bit_buffer *buf,
|
||||
bool black,
|
||||
uint32_t run_length)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
while (run_length >= 2560)
|
||||
{
|
||||
pdf_stream_write_bits (pdf_file, stream, 12, 0x01f);
|
||||
write_bits (buf, 12, 0x01f);
|
||||
run_length -= 2560;
|
||||
}
|
||||
|
||||
if (run_length >= 1792)
|
||||
{
|
||||
i = (run_length - 1792) >> 6;
|
||||
pdf_stream_write_bits (pdf_file, stream,
|
||||
g4_long_makeup_code [i].count,
|
||||
g4_long_makeup_code [i].bits);
|
||||
write_bits (buf,
|
||||
g4_long_makeup_code [i].count,
|
||||
g4_long_makeup_code [i].bits);
|
||||
run_length -= (1792 + (i << 6));
|
||||
}
|
||||
else if (run_length >= 64)
|
||||
{
|
||||
i = (run_length >> 6) - 1;
|
||||
pdf_stream_write_bits (pdf_file, stream,
|
||||
g4_makeup_code [black] [i].count,
|
||||
g4_makeup_code [black] [i].bits);
|
||||
write_bits (buf,
|
||||
g4_makeup_code [black] [i].count,
|
||||
g4_makeup_code [black] [i].bits);
|
||||
run_length -= (i + 1) << 6;
|
||||
}
|
||||
|
||||
pdf_stream_write_bits (pdf_file, stream,
|
||||
g4_h_code [black] [run_length].count,
|
||||
g4_h_code [black] [run_length].bits);
|
||||
write_bits (buf,
|
||||
g4_h_code [black] [run_length].count,
|
||||
g4_h_code [black] [run_length].bits);
|
||||
}
|
||||
|
||||
|
||||
uint32_t find_transition (uint8_t *data,
|
||||
uint32_t pos,
|
||||
uint32_t width)
|
||||
static uint32_t find_transition (uint8_t *data,
|
||||
uint32_t pos,
|
||||
uint32_t width)
|
||||
{
|
||||
if (! data)
|
||||
return (width);
|
||||
@@ -141,11 +144,10 @@ uint32_t find_transition (uint8_t *data,
|
||||
}
|
||||
|
||||
|
||||
static void pdf_g4_encode_row (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream,
|
||||
uint32_t width,
|
||||
uint8_t *ref,
|
||||
uint8_t *row)
|
||||
static void g4_encode_row (struct bit_buffer *buf,
|
||||
uint32_t width,
|
||||
uint8_t *ref,
|
||||
uint8_t *row)
|
||||
{
|
||||
int a0, a1, a2;
|
||||
int b1, b2;
|
||||
@@ -167,152 +169,58 @@ static void pdf_g4_encode_row (pdf_file_handle pdf_file,
|
||||
if (b2 < a1)
|
||||
{
|
||||
/* pass mode - 0001 */
|
||||
pdf_stream_write_bits (pdf_file, stream, 4, 0x1);
|
||||
write_bits (buf, 4, 0x1);
|
||||
a0 = b2;
|
||||
}
|
||||
else if (abs (a1 - b1) <= 3)
|
||||
{
|
||||
/* vertical mode */
|
||||
pdf_stream_write_bits (pdf_file, stream,
|
||||
g4_vert_code [3 + a1 - b1].count,
|
||||
g4_vert_code [3 + a1 - b1].bits);
|
||||
write_bits (buf,
|
||||
g4_vert_code [3 + a1 - b1].count,
|
||||
g4_vert_code [3 + a1 - b1].bits);
|
||||
a0 = a1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* horizontal mode - 001 */
|
||||
pdf_stream_write_bits (pdf_file, stream, 3, 0x1);
|
||||
pdf_g4_encode_horizontal_run (pdf_file, stream,
|
||||
0 /* $$$ color (a0) */, a1 - a0);
|
||||
pdf_g4_encode_horizontal_run (pdf_file, stream,
|
||||
1 /* $$$ color (a1) */, a2 - a1);
|
||||
write_bits (buf, 3, 0x1);
|
||||
g4_encode_horizontal_run (buf, 0 /* $$$ color (a0) */, a1 - a0);
|
||||
g4_encode_horizontal_run (buf, 1 /* $$$ color (a1) */, a2 - a1);
|
||||
a0 = a2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void pdf_write_g4_fax_image_callback (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream,
|
||||
void *app_data)
|
||||
void bitblt_write_g4 (Bitmap *bitmap, FILE *f)
|
||||
{
|
||||
struct pdf_g4_image *image = app_data;
|
||||
|
||||
uint32_t row;
|
||||
struct bit_buffer bb;
|
||||
|
||||
word_type *ref_line = NULL; /* reference (previous) row */
|
||||
word_type *line = image->bitmap->bits;
|
||||
word_type *line = bitmap->bits;
|
||||
|
||||
for (row = image->bitmap->rect.min.y;
|
||||
row < image->bitmap->rect.max.y;
|
||||
memset (& bb, 0, sizeof (bb));
|
||||
|
||||
bb.f = f;
|
||||
|
||||
for (row = bitmap->rect.min.y;
|
||||
row < bitmap->rect.max.y;
|
||||
row++)
|
||||
{
|
||||
pdf_g4_encode_row (pdf_file, stream, image->Columns,
|
||||
(uint8_t *) ref_line,
|
||||
(uint8_t *) line);
|
||||
g4_encode_row (& bb,
|
||||
(bitmap->rect.max.x - bitmap->rect.min.x) + 1,
|
||||
(uint8_t *) ref_line,
|
||||
(uint8_t *) line);
|
||||
ref_line = line;
|
||||
line += image->bitmap->row_words;
|
||||
line += bitmap->row_words;
|
||||
}
|
||||
|
||||
|
||||
/* write EOFB code */
|
||||
pdf_stream_write_bits (pdf_file, stream, 24, 0x001001);
|
||||
write_bits (& bb, 24, 0x001001);
|
||||
|
||||
pdf_stream_flush_bits (pdf_file, stream);
|
||||
flush_bits (& bb);
|
||||
}
|
||||
|
||||
|
||||
void pdf_write_g4_fax_image (pdf_page_handle pdf_page,
|
||||
double x,
|
||||
double y,
|
||||
double width,
|
||||
double height,
|
||||
Bitmap *bitmap,
|
||||
bool ImageMask,
|
||||
double r, /* RGB fill color, only for ImageMask */
|
||||
double g,
|
||||
double b,
|
||||
bool BlackIs1) /* boolean, typ. false */
|
||||
{
|
||||
struct pdf_g4_image *image;
|
||||
|
||||
struct pdf_obj *stream;
|
||||
struct pdf_obj *stream_dict;
|
||||
struct pdf_obj *decode_parms;
|
||||
|
||||
struct pdf_obj *content_stream;
|
||||
|
||||
image = pdf_calloc (1, sizeof (struct pdf_g4_image));
|
||||
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
image->x = x;
|
||||
image->y = y;
|
||||
image->r = r;
|
||||
image->g = g;
|
||||
image->b = b;
|
||||
|
||||
image->bitmap = bitmap;
|
||||
image->Columns = bitmap->rect.max.x - bitmap->rect.min.x;
|
||||
image->Rows = bitmap->rect.max.y - bitmap->rect.min.y;
|
||||
image->ImageMask = ImageMask;
|
||||
image->BlackIs1 = BlackIs1;
|
||||
|
||||
stream_dict = pdf_new_obj (PT_DICTIONARY);
|
||||
|
||||
stream = pdf_new_ind_ref (pdf_page->pdf_file,
|
||||
pdf_new_stream (pdf_page->pdf_file,
|
||||
stream_dict,
|
||||
& pdf_write_g4_fax_image_callback,
|
||||
image));
|
||||
|
||||
strcpy (& image->XObject_name [0], "Im ");
|
||||
image->XObject_name [2] = pdf_new_XObject (pdf_page, stream);
|
||||
|
||||
pdf_set_dict_entry (stream_dict, "Type", pdf_new_name ("XObject"));
|
||||
pdf_set_dict_entry (stream_dict, "Subtype", pdf_new_name ("Image"));
|
||||
pdf_set_dict_entry (stream_dict, "Name", pdf_new_name (& image->XObject_name [0]));
|
||||
pdf_set_dict_entry (stream_dict, "Width", pdf_new_integer (image->Columns));
|
||||
pdf_set_dict_entry (stream_dict, "Height", pdf_new_integer (image->Rows));
|
||||
pdf_set_dict_entry (stream_dict, "BitsPerComponent", pdf_new_integer (1));
|
||||
if (ImageMask)
|
||||
pdf_set_dict_entry (stream_dict, "ImageMask", pdf_new_bool (ImageMask));
|
||||
else
|
||||
pdf_set_dict_entry (stream_dict, "ColorSpace", pdf_new_name ("DeviceGray"));
|
||||
|
||||
decode_parms = pdf_new_obj (PT_DICTIONARY);
|
||||
|
||||
pdf_set_dict_entry (decode_parms,
|
||||
"K",
|
||||
pdf_new_integer (-1));
|
||||
|
||||
pdf_set_dict_entry (decode_parms,
|
||||
"Columns",
|
||||
pdf_new_integer (image->Columns));
|
||||
|
||||
pdf_set_dict_entry (decode_parms,
|
||||
"Rows",
|
||||
pdf_new_integer (image->Rows));
|
||||
|
||||
if (BlackIs1)
|
||||
pdf_set_dict_entry (decode_parms,
|
||||
"BlackIs1",
|
||||
pdf_new_bool (BlackIs1));
|
||||
|
||||
pdf_stream_add_filter (stream, "CCITTFaxDecode", decode_parms);
|
||||
|
||||
/* the following will write the stream, using our callback function to
|
||||
get the actual data */
|
||||
pdf_write_ind_obj (pdf_page->pdf_file, stream);
|
||||
|
||||
content_stream = pdf_new_ind_ref (pdf_page->pdf_file,
|
||||
pdf_new_stream (pdf_page->pdf_file,
|
||||
pdf_new_obj (PT_DICTIONARY),
|
||||
& pdf_write_g4_content_callback,
|
||||
image));
|
||||
|
||||
pdf_set_dict_entry (pdf_page->page_dict, "Contents", content_stream);
|
||||
|
||||
pdf_write_ind_obj (pdf_page->pdf_file, content_stream);
|
||||
}
|
||||
|
||||
|
||||
124
pdf_g4.c
124
pdf_g4.c
@@ -4,7 +4,7 @@
|
||||
* will be compressed using ITU-T T.6 (G4) fax encoding.
|
||||
*
|
||||
* PDF routines
|
||||
* $Id: pdf_g4.c,v 1.8 2003/03/05 12:44:33 eric Exp $
|
||||
* $Id: pdf_g4.c,v 1.9 2003/03/10 01:49:50 eric Exp $
|
||||
* Copyright 2003 Eric Smith <eric@brouhaha.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -38,9 +38,6 @@
|
||||
#include "pdf_private.h"
|
||||
|
||||
|
||||
#include "pdf_g4_tables.h"
|
||||
|
||||
|
||||
#define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
|
||||
|
||||
|
||||
@@ -95,130 +92,13 @@ void pdf_write_g4_content_callback (pdf_file_handle pdf_file,
|
||||
}
|
||||
|
||||
|
||||
static void pdf_g4_encode_horizontal_run (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream,
|
||||
bool black,
|
||||
uint32_t run_length)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
while (run_length >= 2560)
|
||||
{
|
||||
pdf_stream_write_bits (pdf_file, stream, 12, 0x01f);
|
||||
run_length -= 2560;
|
||||
}
|
||||
|
||||
if (run_length >= 1792)
|
||||
{
|
||||
i = (run_length - 1792) >> 6;
|
||||
pdf_stream_write_bits (pdf_file, stream,
|
||||
g4_long_makeup_code [i].count,
|
||||
g4_long_makeup_code [i].bits);
|
||||
run_length -= (1792 + (i << 6));
|
||||
}
|
||||
else if (run_length >= 64)
|
||||
{
|
||||
i = (run_length >> 6) - 1;
|
||||
pdf_stream_write_bits (pdf_file, stream,
|
||||
g4_makeup_code [black] [i].count,
|
||||
g4_makeup_code [black] [i].bits);
|
||||
run_length -= (i + 1) << 6;
|
||||
}
|
||||
|
||||
pdf_stream_write_bits (pdf_file, stream,
|
||||
g4_h_code [black] [run_length].count,
|
||||
g4_h_code [black] [run_length].bits);
|
||||
}
|
||||
|
||||
|
||||
uint32_t find_transition (uint8_t *data,
|
||||
uint32_t pos,
|
||||
uint32_t width)
|
||||
{
|
||||
if (! data)
|
||||
return (width);
|
||||
return (0); /* $$$ */
|
||||
}
|
||||
|
||||
|
||||
static void pdf_g4_encode_row (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream,
|
||||
uint32_t width,
|
||||
uint8_t *ref,
|
||||
uint8_t *row)
|
||||
{
|
||||
int a0, a1, a2;
|
||||
int b1, b2;
|
||||
|
||||
a0 = -1;
|
||||
|
||||
while (a0 < width)
|
||||
{
|
||||
/* find a1, a2 */
|
||||
a1 = find_transition (row, a0, width);
|
||||
a2 = find_transition (row, a1, width);
|
||||
|
||||
/* find b1, b2 */
|
||||
b1 = find_transition (ref, a0, width);
|
||||
if (0) /* $$$ b1 color = a0 color */
|
||||
b1 = find_transition (ref, b1, width);
|
||||
b2 = find_transition (ref, b2, width);
|
||||
|
||||
if (b2 < a1)
|
||||
{
|
||||
/* pass mode - 0001 */
|
||||
pdf_stream_write_bits (pdf_file, stream, 4, 0x1);
|
||||
a0 = b2;
|
||||
}
|
||||
else if (abs (a1 - b1) <= 3)
|
||||
{
|
||||
/* vertical mode */
|
||||
pdf_stream_write_bits (pdf_file, stream,
|
||||
g4_vert_code [3 + a1 - b1].count,
|
||||
g4_vert_code [3 + a1 - b1].bits);
|
||||
a0 = a1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* horizontal mode - 001 */
|
||||
pdf_stream_write_bits (pdf_file, stream, 3, 0x1);
|
||||
pdf_g4_encode_horizontal_run (pdf_file, stream,
|
||||
0 /* $$$ color (a0) */, a1 - a0);
|
||||
pdf_g4_encode_horizontal_run (pdf_file, stream,
|
||||
1 /* $$$ color (a1) */, a2 - a1);
|
||||
a0 = a2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void pdf_write_g4_fax_image_callback (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream,
|
||||
void *app_data)
|
||||
{
|
||||
struct pdf_g4_image *image = app_data;
|
||||
|
||||
uint32_t row;
|
||||
|
||||
word_type *ref_line = NULL; /* reference (previous) row */
|
||||
word_type *line = image->bitmap->bits;
|
||||
|
||||
for (row = image->bitmap->rect.min.y;
|
||||
row < image->bitmap->rect.max.y;
|
||||
row++)
|
||||
{
|
||||
pdf_g4_encode_row (pdf_file, stream, image->Columns,
|
||||
(uint8_t *) ref_line,
|
||||
(uint8_t *) line);
|
||||
ref_line = line;
|
||||
line += image->bitmap->row_words;
|
||||
}
|
||||
|
||||
|
||||
/* write EOFB code */
|
||||
pdf_stream_write_bits (pdf_file, stream, 24, 0x001001);
|
||||
|
||||
pdf_stream_flush_bits (pdf_file, stream);
|
||||
bitblt_write_g4 (image->bitmap, pdf_file->f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* t2p: Create a PDF file from the contents of one or more TIFF
|
||||
* bilevel image files. The images in the resulting PDF file
|
||||
* will be compressed using ITU-T T.6 (G4) fax encoding.
|
||||
*
|
||||
* G4 table generator
|
||||
* $Id: pdf_g4_table_gen.c,v 1.2 2003/03/05 12:44:33 eric Exp $
|
||||
* Copyright 2003 Eric Smith <eric@brouhaha.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation. Note that permission is
|
||||
* not granted to redistribute this program under the terms of any
|
||||
* other version of the General Public License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
void emit_code (int indent, char *code, int last, bool comment, int cval)
|
||||
{
|
||||
int i;
|
||||
int count = 0;
|
||||
uint32_t val = 0;
|
||||
|
||||
printf ("%*s{ ", indent, "");
|
||||
|
||||
printf ("%d, ", strlen (code));
|
||||
|
||||
for (i = 0; i < strlen (code); i++)
|
||||
switch (code [i])
|
||||
{
|
||||
case '0': val = (val << 1); count++; break;
|
||||
case '1': val = (val << 1) + 1; count++; break;
|
||||
case ' ': break;
|
||||
default:
|
||||
fprintf (stderr, "internal error\n");
|
||||
exit (2);
|
||||
}
|
||||
|
||||
printf ("0x%0*x", (count + 3)/4, val);
|
||||
|
||||
printf (" }");
|
||||
if (! last)
|
||||
printf (",");
|
||||
if (comment)
|
||||
printf (" /* %d */", cval);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
|
||||
char *long_makeup_code [12] =
|
||||
{
|
||||
/* 1792 */ "00000001000",
|
||||
/* 1856 */ "00000001100",
|
||||
/* 1920 */ "00000001101",
|
||||
/* 1984 */ "000000010010",
|
||||
/* 2048 */ "000000010011",
|
||||
/* 2112 */ "000000010100",
|
||||
/* 2176 */ "000000010101",
|
||||
/* 2240 */ "000000010110",
|
||||
/* 2304 */ "000000010111",
|
||||
/* 2368 */ "000000011100",
|
||||
/* 2432 */ "000000011101",
|
||||
/* 2496 */ "000000011110"
|
||||
/* 2560 "000000011111" hard-coded, doesn't need to be in table */
|
||||
};
|
||||
|
||||
|
||||
void print_long_makeup_code (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf ("static g4_bits g4_long_makeup_code [12] =\n");
|
||||
printf (" {\n");
|
||||
for (i = 0; i < 12; i++)
|
||||
emit_code (4, long_makeup_code [i], i == 11, 1, i * 64 + 1792);
|
||||
printf (" };\n");
|
||||
}
|
||||
|
||||
|
||||
char *makeup_code [64][2] =
|
||||
{
|
||||
{ /* 64 */ "11011", "0000001111" },
|
||||
{ /* 128 */ "10010", "000011001000" },
|
||||
{ /* 192 */ "010111", "000011001001" },
|
||||
{ /* 256 */ "0110111", "000001011011" },
|
||||
{ /* 320 */ "00110110", "000000110011" },
|
||||
{ /* 384 */ "00110111", "000000110100" },
|
||||
{ /* 448 */ "01100100", "000000110101" },
|
||||
{ /* 512 */ "01100101", "0000001101100" },
|
||||
{ /* 576 */ "01101000", "0000001101101" },
|
||||
{ /* 640 */ "01100111", "0000001001010" },
|
||||
{ /* 704 */ "011001100", "0000001001011" },
|
||||
{ /* 768 */ "011001101", "0000001001100" },
|
||||
{ /* 832 */ "011010010", "0000001001101" },
|
||||
{ /* 896 */ "011010011", "0000001110010" },
|
||||
{ /* 960 */ "011010100", "0000001110011" },
|
||||
{ /* 1024 */ "011010101", "0000001110100" },
|
||||
{ /* 1088 */ "011010110", "0000001110101" },
|
||||
{ /* 1152 */ "011010111", "0000001110110" },
|
||||
{ /* 1216 */ "011011000", "0000001110111" },
|
||||
{ /* 1280 */ "011011001", "0000001010010" },
|
||||
{ /* 1344 */ "011011010", "0000001010011" },
|
||||
{ /* 1408 */ "011011011", "0000001010100" },
|
||||
{ /* 1472 */ "010011000", "0000001010101" },
|
||||
{ /* 1536 */ "010011001", "0000001011010" },
|
||||
{ /* 1600 */ "010011010", "0000001011011" },
|
||||
{ /* 1664 */ "011000", "0000001100100" },
|
||||
{ /* 1728 */ "010011011", "0000001100101" }
|
||||
};
|
||||
|
||||
|
||||
void print_makeup_code (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf ("static g4_bits g4_makeup_code [2] [27] =\n");
|
||||
printf (" {\n");
|
||||
printf (" {\n");
|
||||
printf (" /* white */\n");
|
||||
for (i = 0; i <= 26; i++)
|
||||
emit_code (6, makeup_code [i][0], i == 26, 1, (i + 1) * 64);
|
||||
printf (" },\n");
|
||||
printf (" {\n");
|
||||
printf (" /* black */\n");
|
||||
for (i = 0; i <= 26; i++)
|
||||
emit_code (6, makeup_code [i][1], i == 26, 1, (i + 1) * 64);
|
||||
printf (" }\n");
|
||||
printf (" };\n");
|
||||
}
|
||||
|
||||
|
||||
char *h_code [64][2] =
|
||||
{
|
||||
{ /* 0 */ "00110101", "0000110111" },
|
||||
{ /* 1 */ "000111", "010" },
|
||||
{ /* 2 */ "0111", "11" },
|
||||
{ /* 3 */ "1000", "10" },
|
||||
{ /* 4 */ "1011", "011" },
|
||||
{ /* 5 */ "1100", "0011" },
|
||||
{ /* 6 */ "1110", "0010" },
|
||||
{ /* 7 */ "1111", "00011" },
|
||||
{ /* 8 */ "10011", "000101" },
|
||||
{ /* 9 */ "10100", "000100" },
|
||||
{ /* 10 */ "00111", "0000100" },
|
||||
{ /* 11 */ "01000", "0000101" },
|
||||
{ /* 12 */ "001000", "0000111" },
|
||||
{ /* 13 */ "000011", "00000100" },
|
||||
{ /* 14 */ "110100", "00000111" },
|
||||
{ /* 15 */ "110101", "000011000" },
|
||||
{ /* 16 */ "101010", "0000010111" },
|
||||
{ /* 17 */ "101011", "0000011000" },
|
||||
{ /* 18 */ "0100111", "0000001000" },
|
||||
{ /* 19 */ "0001100", "00001100111" },
|
||||
{ /* 20 */ "0001000", "00001101000" },
|
||||
{ /* 21 */ "0010111", "00001101100" },
|
||||
{ /* 22 */ "0000011", "00000110111" },
|
||||
{ /* 23 */ "0000100", "00000101000" },
|
||||
{ /* 24 */ "0101000", "00000010111" },
|
||||
{ /* 25 */ "0101011", "00000011000" },
|
||||
{ /* 26 */ "0010011", "000011001010" },
|
||||
{ /* 27 */ "0100100", "000011001011" },
|
||||
{ /* 28 */ "0011000", "000011001100" },
|
||||
{ /* 29 */ "00000010", "000011001101" },
|
||||
{ /* 30 */ "00000011", "000001101000" },
|
||||
{ /* 31 */ "00011010", "000001101001" },
|
||||
{ /* 32 */ "00011011", "000001101010" },
|
||||
{ /* 33 */ "00010010", "000001101011" },
|
||||
{ /* 34 */ "00010011", "000011010010" },
|
||||
{ /* 35 */ "00010100", "000011010011" },
|
||||
{ /* 36 */ "00010101", "000011010100" },
|
||||
{ /* 37 */ "00010110", "000011010101" },
|
||||
{ /* 38 */ "00010111", "000011010110" },
|
||||
{ /* 39 */ "00101000", "000011010111" },
|
||||
{ /* 40 */ "00101001", "000001101100" },
|
||||
{ /* 41 */ "00101010", "000001101101" },
|
||||
{ /* 42 */ "00101011", "000011011010" },
|
||||
{ /* 43 */ "00101100", "000011011011" },
|
||||
{ /* 44 */ "00101101", "000001010100" },
|
||||
{ /* 45 */ "00000100", "000001010101" },
|
||||
{ /* 46 */ "00000101", "000001010110" },
|
||||
{ /* 47 */ "00001010", "000001010111" },
|
||||
{ /* 48 */ "00001011", "000001100100" },
|
||||
{ /* 49 */ "01010010", "000001100101" },
|
||||
{ /* 50 */ "01010011", "000001010010" },
|
||||
{ /* 51 */ "01010100", "000001010011" },
|
||||
{ /* 52 */ "01010101", "000000100100" },
|
||||
{ /* 53 */ "00100100", "000000110111" },
|
||||
{ /* 54 */ "00100101", "000000111000" },
|
||||
{ /* 55 */ "01011000", "000000100111" },
|
||||
{ /* 56 */ "01011001", "000000101000" },
|
||||
{ /* 57 */ "01011010", "000001011000" },
|
||||
{ /* 58 */ "01011011", "000001011001" },
|
||||
{ /* 59 */ "01001010", "000000101011" },
|
||||
{ /* 60 */ "01001011", "000000101100" },
|
||||
{ /* 61 */ "00110010", "000001011010" },
|
||||
{ /* 62 */ "00110011", "000001100110" },
|
||||
{ /* 63 */ "00110100", "000001100111" }
|
||||
};
|
||||
|
||||
|
||||
void print_h_code (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf ("static g4_bits g4_h_code [2] [64] =\n");
|
||||
printf (" {\n");
|
||||
printf (" {\n");
|
||||
printf (" /* white */\n");
|
||||
for (i = 0; i <= 63; i++)
|
||||
emit_code (6, h_code [i][0], i == 63, 1, i);
|
||||
printf (" },\n");
|
||||
printf (" {\n");
|
||||
printf (" /* black */\n");
|
||||
for (i = 0; i <= 63; i++)
|
||||
emit_code (6, h_code [i][1], i == 63, 1, i);
|
||||
printf (" }\n");
|
||||
printf (" };\n");
|
||||
}
|
||||
|
||||
|
||||
char *v_code [7] =
|
||||
{
|
||||
/* -3 */ "0000010",
|
||||
/* -2 */ "000010",
|
||||
/* -1 */ "010",
|
||||
/* 0 */ "1",
|
||||
/* 1 */ "011",
|
||||
/* 2 */ "000011",
|
||||
/* 3 */ "0000011"
|
||||
};
|
||||
|
||||
|
||||
void print_v_code (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf ("static g4_bits g4_vert_code [7] =\n");
|
||||
printf (" {\n");
|
||||
for (i = 0; i <= 6; i++)
|
||||
emit_code (4, v_code [i], i == 6, 1, i - 3);
|
||||
printf (" };\n");
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv [])
|
||||
{
|
||||
printf ("/* This file is automatically generated; do not edit */\n");
|
||||
printf ("\n");
|
||||
printf ("typedef struct\n");
|
||||
printf ("{\n");
|
||||
printf (" uint32_t count;\n");
|
||||
printf (" uint32_t bits;\n");
|
||||
printf ("} g4_bits;\n");
|
||||
printf ("\n");
|
||||
|
||||
print_long_makeup_code ();
|
||||
printf ("\n");
|
||||
|
||||
print_makeup_code ();
|
||||
printf ("\n");
|
||||
|
||||
print_h_code ();
|
||||
printf ("\n");
|
||||
|
||||
print_v_code ();
|
||||
|
||||
exit (0);
|
||||
}
|
||||
70
pdf_prim.c
70
pdf_prim.c
@@ -4,7 +4,7 @@
|
||||
* will be compressed using ITU-T T.6 (G4) fax encoding.
|
||||
*
|
||||
* PDF routines
|
||||
* $Id: pdf_prim.c,v 1.7 2003/03/07 03:02:31 eric Exp $
|
||||
* $Id: pdf_prim.c,v 1.8 2003/03/10 01:49:50 eric Exp $
|
||||
* Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -66,8 +66,6 @@ struct pdf_dict
|
||||
};
|
||||
|
||||
|
||||
#define STREAM_BUF_SIZE 4096
|
||||
|
||||
struct pdf_stream
|
||||
{
|
||||
struct pdf_obj *stream_dict;
|
||||
@@ -76,13 +74,6 @@ struct pdf_stream
|
||||
void *app_data; /* arg to pass to callback */
|
||||
struct pdf_obj *filters; /* name or array of names */
|
||||
struct pdf_obj *decode_parms;
|
||||
|
||||
/* The following fields are used by pdf_stream_write_bits() and
|
||||
pdf_stream_flush_bits(). */
|
||||
uint32_t byte_idx; /* index to next byte position in data buffer */
|
||||
uint32_t bit_idx; /* index to next bit position in data buffer,
|
||||
0 = MSB, 7 = LSB */
|
||||
uint8_t data [STREAM_BUF_SIZE];
|
||||
};
|
||||
|
||||
|
||||
@@ -494,65 +485,6 @@ void pdf_stream_write_data (pdf_file_handle pdf_file,
|
||||
}
|
||||
|
||||
|
||||
void pdf_stream_flush_bits (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream)
|
||||
{
|
||||
struct pdf_stream *s = & stream->val.stream;
|
||||
|
||||
if (s->bit_idx)
|
||||
{
|
||||
/* zero remaining bits in last byte */
|
||||
s->data [s->byte_idx] &= ~ ((1 << (8 - s->bit_idx)) - 1);
|
||||
s->byte_idx++;
|
||||
s->bit_idx = 0;
|
||||
}
|
||||
pdf_stream_write_data (pdf_file, stream,
|
||||
(char *) & s->data [0],
|
||||
s->byte_idx);
|
||||
s->byte_idx = 0;
|
||||
}
|
||||
|
||||
|
||||
static void pdf_stream_advance_byte (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream)
|
||||
{
|
||||
struct pdf_stream *s = & stream->val.stream;
|
||||
|
||||
s->byte_idx++;
|
||||
s->bit_idx = 0;
|
||||
if (s->byte_idx == STREAM_BUF_SIZE)
|
||||
pdf_stream_flush_bits (pdf_file, stream);
|
||||
}
|
||||
|
||||
|
||||
void pdf_stream_write_bits (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream,
|
||||
uint32_t count,
|
||||
uint32_t bits)
|
||||
{
|
||||
struct pdf_stream *s = & stream->val.stream;
|
||||
|
||||
uint32_t b2; /* how many bits will fit in byte in data buffer */
|
||||
uint32_t c2; /* how many bits to transfer on this iteration */
|
||||
uint32_t d2; /* bits to transfer on this iteration */
|
||||
|
||||
while (count)
|
||||
{
|
||||
b2 = 8 - s->bit_idx;
|
||||
if (b2 >= count)
|
||||
c2 = count;
|
||||
else
|
||||
c2 = b2;
|
||||
d2 = bits >> (count - c2);
|
||||
s->data [s->byte_idx] |= (d2 << (b2 + c2));
|
||||
s->bit_idx += c2;
|
||||
if (s->bit_idx > 7)
|
||||
pdf_stream_advance_byte (pdf_file, stream);
|
||||
count -= c2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void pdf_stream_printf (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream,
|
||||
char *fmt, ...)
|
||||
|
||||
13
pdf_prim.h
13
pdf_prim.h
@@ -4,7 +4,7 @@
|
||||
* will be compressed using ITU-T T.6 (G4) fax encoding.
|
||||
*
|
||||
* PDF routines
|
||||
* $Id: pdf_prim.h,v 1.6 2003/03/07 03:02:31 eric Exp $
|
||||
* $Id: pdf_prim.h,v 1.7 2003/03/10 01:49:50 eric Exp $
|
||||
* Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -99,15 +99,8 @@ struct pdf_obj *pdf_new_stream (pdf_file_handle pdf_file,
|
||||
pdf_stream_write_callback callback,
|
||||
void *app_data);
|
||||
|
||||
/* The callback should call pdf_stream_write_bits(), pdf_stream_write_data(),
|
||||
or pdf_stream_printf() to write the actual stream data. If
|
||||
pdf_stream_write_bits() is used, pdf_stream_flush_bits() should be
|
||||
called after all the bits are written. */
|
||||
|
||||
void pdf_stream_write_bits (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream,
|
||||
uint32_t count,
|
||||
uint32_t bits);
|
||||
/* The callback should call pdf_stream_write_data() or pdf_stream_printf()
|
||||
to write the actual stream data. */
|
||||
|
||||
void pdf_stream_flush_bits (pdf_file_handle pdf_file,
|
||||
struct pdf_obj *stream);
|
||||
|
||||
Reference in New Issue
Block a user