| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- // Copyright (C) 2004-2021 Artifex Software, Inc.
- //
- // This file is part of MuPDF.
- //
- // MuPDF is free software: you can redistribute it and/or modify it under the
- // terms of the GNU Affero General Public License as published by the Free
- // Software Foundation, either version 3 of the License, or (at your option)
- // any later version.
- //
- // MuPDF 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 Affero General Public License for more
- // details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
- //
- // Alternative licensing terms are available from the licensor.
- // For commercial licensing, see <https://www.artifex.com/> or contact
- // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
- // CA 94129, USA, for further information.
- #include "mupdf/fitz.h"
- /* Fax G3/G4 tables */
- typedef struct
- {
- unsigned short code;
- unsigned short nbits;
- } cfe_code;
- typedef struct {
- cfe_code termination[64];
- cfe_code makeup[41];
- } cf_runs;
- /* Define the end-of-line code. */
- static const cfe_code cf_run_eol = {1, 12};
- /* Define the 2-D run codes. */
- static const cfe_code cf2_run_pass = {0x1, 4};
- static const cfe_code cf2_run_vertical[7] =
- {
- {0x3, 7},
- {0x3, 6},
- {0x3, 3},
- {0x1, 1},
- {0x2, 3},
- {0x2, 6},
- {0x2, 7}
- };
- static const cfe_code cf2_run_horizontal = {1, 3};
- /* White run codes. */
- static const cf_runs cf_white_runs =
- {
- /* Termination codes */
- {
- {0x35, 8}, {0x7, 6}, {0x7, 4}, {0x8, 4},
- {0xb, 4}, {0xc, 4}, {0xe, 4}, {0xf, 4},
- {0x13, 5}, {0x14, 5}, {0x7, 5}, {0x8, 5},
- {0x8, 6}, {0x3, 6}, {0x34, 6}, {0x35, 6},
- {0x2a, 6}, {0x2b, 6}, {0x27, 7}, {0xc, 7},
- {0x8, 7}, {0x17, 7}, {0x3, 7}, {0x4, 7},
- {0x28, 7}, {0x2b, 7}, {0x13, 7}, {0x24, 7},
- {0x18, 7}, {0x2, 8}, {0x3, 8}, {0x1a, 8},
- {0x1b, 8}, {0x12, 8}, {0x13, 8}, {0x14, 8},
- {0x15, 8}, {0x16, 8}, {0x17, 8}, {0x28, 8},
- {0x29, 8}, {0x2a, 8}, {0x2b, 8}, {0x2c, 8},
- {0x2d, 8}, {0x4, 8}, {0x5, 8}, {0xa, 8},
- {0xb, 8}, {0x52, 8}, {0x53, 8}, {0x54, 8},
- {0x55, 8}, {0x24, 8}, {0x25, 8}, {0x58, 8},
- {0x59, 8}, {0x5a, 8}, {0x5b, 8}, {0x4a, 8},
- {0x4b, 8}, {0x32, 8}, {0x33, 8}, {0x34, 8}
- },
- /* Make-up codes */
- {
- {0, 0} /* dummy */ , {0x1b, 5}, {0x12, 5}, {0x17, 6},
- {0x37, 7}, {0x36, 8}, {0x37, 8}, {0x64, 8},
- {0x65, 8}, {0x68, 8}, {0x67, 8}, {0xcc, 9},
- {0xcd, 9}, {0xd2, 9}, {0xd3, 9}, {0xd4, 9},
- {0xd5, 9}, {0xd6, 9}, {0xd7, 9}, {0xd8, 9},
- {0xd9, 9}, {0xda, 9}, {0xdb, 9}, {0x98, 9},
- {0x99, 9}, {0x9a, 9}, {0x18, 6}, {0x9b, 9},
- {0x8, 11}, {0xc, 11}, {0xd, 11}, {0x12, 12},
- {0x13, 12}, {0x14, 12}, {0x15, 12}, {0x16, 12},
- {0x17, 12}, {0x1c, 12}, {0x1d, 12}, {0x1e, 12},
- {0x1f, 12}
- }
- };
- /* Black run codes. */
- static const cf_runs cf_black_runs =
- {
- /* Termination codes */
- {
- {0x37, 10}, {0x2, 3}, {0x3, 2}, {0x2, 2},
- {0x3, 3}, {0x3, 4}, {0x2, 4}, {0x3, 5},
- {0x5, 6}, {0x4, 6}, {0x4, 7}, {0x5, 7},
- {0x7, 7}, {0x4, 8}, {0x7, 8}, {0x18, 9},
- {0x17, 10}, {0x18, 10}, {0x8, 10}, {0x67, 11},
- {0x68, 11}, {0x6c, 11}, {0x37, 11}, {0x28, 11},
- {0x17, 11}, {0x18, 11}, {0xca, 12}, {0xcb, 12},
- {0xcc, 12}, {0xcd, 12}, {0x68, 12}, {0x69, 12},
- {0x6a, 12}, {0x6b, 12}, {0xd2, 12}, {0xd3, 12},
- {0xd4, 12}, {0xd5, 12}, {0xd6, 12}, {0xd7, 12},
- {0x6c, 12}, {0x6d, 12}, {0xda, 12}, {0xdb, 12},
- {0x54, 12}, {0x55, 12}, {0x56, 12}, {0x57, 12},
- {0x64, 12}, {0x65, 12}, {0x52, 12}, {0x53, 12},
- {0x24, 12}, {0x37, 12}, {0x38, 12}, {0x27, 12},
- {0x28, 12}, {0x58, 12}, {0x59, 12}, {0x2b, 12},
- {0x2c, 12}, {0x5a, 12}, {0x66, 12}, {0x67, 12}
- },
- /* Make-up codes. */
- {
- {0, 0} /* dummy */ , {0xf, 10}, {0xc8, 12}, {0xc9, 12},
- {0x5b, 12}, {0x33, 12}, {0x34, 12}, {0x35, 12},
- {0x6c, 13}, {0x6d, 13}, {0x4a, 13}, {0x4b, 13},
- {0x4c, 13}, {0x4d, 13}, {0x72, 13}, {0x73, 13},
- {0x74, 13}, {0x75, 13}, {0x76, 13}, {0x77, 13},
- {0x52, 13}, {0x53, 13}, {0x54, 13}, {0x55, 13},
- {0x5a, 13}, {0x5b, 13}, {0x64, 13}, {0x65, 13},
- {0x8, 11}, {0xc, 11}, {0xd, 11}, {0x12, 12},
- {0x13, 12}, {0x14, 12}, {0x15, 12}, {0x16, 12},
- {0x17, 12}, {0x1c, 12}, {0x1d, 12}, {0x1e, 12},
- {0x1f, 12}
- }
- };
- static inline int
- getbit(const unsigned char *buf, int x)
- {
- /* Invert bit to handle BlackIs1=false */
- return ( ( buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1 ) ^ 1;
- }
- static inline int
- find_changing(const unsigned char *line, int x, int w)
- {
- int a, b;
- if (!line || x >= w)
- return w;
- if (x == -1)
- {
- a = 0;
- x = 0;
- }
- else
- {
- a = getbit(line, x);
- x++;
- }
- while (x < w)
- {
- b = getbit(line, x);
- if (a != b)
- break;
- x++;
- }
- return x;
- }
- static inline int
- find_changing_color(const unsigned char *line, int x, int w, int color)
- {
- if (!line || x >= w)
- return w;
- x = find_changing(line, x, w);
- if (x < w && getbit(line, x) != color)
- x = find_changing(line, x, w);
- return x;
- }
- static inline int
- getrun(const unsigned char *line, int x, int w, int c)
- {
- int z = x;
- while (z < w)
- {
- int b = getbit(line, z);
- if (c != b)
- break;
- ++z;
- }
- return z - x;
- }
- static inline void
- putcode(fz_context *ctx, fz_buffer *out, const cfe_code *run)
- {
- fz_append_bits(ctx, out, run->code, run->nbits);
- }
- static void
- putrun(fz_context *ctx, fz_buffer *out, int run, int c)
- {
- const cf_runs *codetable = c ? &cf_black_runs : &cf_white_runs;
- if (run > 63)
- {
- int m = run >> 6;
- while (m > 40)
- {
- putcode(ctx, out, &codetable->makeup[40]);
- m -= 40;
- }
- if (m > 0)
- putcode(ctx, out, &codetable->makeup[m]);
- putcode(ctx, out, &codetable->termination[run & 63]);
- }
- else
- {
- putcode(ctx, out, &codetable->termination[run]);
- }
- }
- fz_buffer *
- fz_compress_ccitt_fax_g4(fz_context *ctx, const unsigned char *src, int columns, int rows, ptrdiff_t stride)
- {
- fz_buffer *out = fz_new_buffer(ctx, (stride * rows) >> 3);
- const unsigned char *ref = NULL;
- fz_try(ctx)
- {
- while (rows-- > 0)
- {
- int a0 = -1;
- int c = 0;
- while (a0 < columns)
- {
- int a1 = find_changing(src, a0, columns);
- int b1 = find_changing_color(ref, a0, columns, c^1);
- int b2 = find_changing(ref, b1, columns);
- int diff = b1 - a1;
- if (a0 < 0)
- a0 = 0;
- /* pass mode */
- if (b2 < a1)
- {
- putcode(ctx, out, &cf2_run_pass);
- a0 = b2;
- }
- /* vertical mode */
- else if (diff >= -3 && diff <= 3)
- {
- putcode(ctx, out, &cf2_run_vertical[diff + 3]);
- a0 = a1;
- c = c^1;
- }
- /* horizontal mode */
- else
- {
- int a2 = find_changing(src, a1, columns);
- putcode(ctx, out, &cf2_run_horizontal);
- putrun(ctx, out, a1 - a0, c);
- putrun(ctx, out, a2 - a1, c^1);
- a0 = a2;
- }
- }
- ref = src;
- src += stride;
- }
- putcode(ctx, out, &cf_run_eol);
- putcode(ctx, out, &cf_run_eol);
- }
- fz_catch(ctx)
- {
- fz_drop_buffer(ctx, out);
- fz_rethrow(ctx);
- }
- return out;
- }
- fz_buffer *
- fz_compress_ccitt_fax_g3(fz_context *ctx, const unsigned char *src, int columns, int rows, ptrdiff_t stride)
- {
- fz_buffer *out = fz_new_buffer(ctx, (stride * rows) >> 3);
- int i;
- fz_try(ctx)
- {
- while (rows-- > 0)
- {
- int a0 = 0;
- int c = 0;
- while (a0 < columns)
- {
- int run = getrun(src, a0, columns, c);
- putrun(ctx, out, run, c);
- a0 += run;
- c = c^1;
- }
- src += stride;
- }
- for (i = 0; i < 6; ++i)
- putcode(ctx, out, &cf_run_eol);
- }
- fz_catch(ctx)
- {
- fz_drop_buffer(ctx, out);
- fz_rethrow(ctx);
- }
- return out;
- }
|