Coverage Report

Created: 2024-05-20 06:23

/src/mupdf/source/fitz/load-jbig2.c
Line
Count
Source (jump to first uncovered line)
1
// Copyright (C) 2004-2021 Artifex Software, Inc.
2
//
3
// This file is part of MuPDF.
4
//
5
// MuPDF is free software: you can redistribute it and/or modify it under the
6
// terms of the GNU Affero General Public License as published by the Free
7
// Software Foundation, either version 3 of the License, or (at your option)
8
// any later version.
9
//
10
// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
// details.
14
//
15
// You should have received a copy of the GNU Affero General Public License
16
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17
//
18
// Alternative licensing terms are available from the licensor.
19
// For commercial licensing, see <https://www.artifex.com/> or contact
20
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21
// CA 94129, USA, for further information.
22
23
#include "mupdf/fitz.h"
24
25
#include "pixmap-imp.h"
26
27
#include <jbig2.h>
28
29
struct info
30
{
31
  int width, height;
32
  int xres, yres;
33
  int pages;
34
  fz_colorspace *cspace;
35
};
36
37
struct fz_jbig2_allocator
38
{
39
  Jbig2Allocator super;
40
  fz_context *ctx;
41
};
42
43
static void
44
error_callback(void *data, const char *msg, Jbig2Severity severity, uint32_t seg_idx)
45
3.25k
{
46
3.25k
  fz_context *ctx = data;
47
3.25k
  if (severity == JBIG2_SEVERITY_FATAL)
48
31
    fz_warn(ctx, "jbig2dec error: %s (segment %u)", msg, seg_idx);
49
3.22k
  else if (severity == JBIG2_SEVERITY_WARNING)
50
21
    fz_warn(ctx, "jbig2dec warning: %s (segment %u)", msg, seg_idx);
51
#ifdef JBIG2_DEBUG
52
  else if (severity == JBIG2_SEVERITY_INFO)
53
    fz_warn(ctx, "jbig2dec info: %s (segment %u)", msg, seg_idx);
54
  else if (severity == JBIG2_SEVERITY_DEBUG)
55
    fz_warn(ctx, "jbig2dec debug: %s (segment %u)", msg, seg_idx);
56
#endif
57
3.25k
}
58
59
static void *fz_jbig2_alloc(Jbig2Allocator *allocator, size_t size)
60
3.09k
{
61
3.09k
  fz_context *ctx = ((struct fz_jbig2_allocator *) allocator)->ctx;
62
3.09k
  return fz_malloc_no_throw(ctx, size);
63
3.09k
}
64
65
static void fz_jbig2_free(Jbig2Allocator *allocator, void *p)
66
5.63k
{
67
5.63k
  fz_context *ctx = ((struct fz_jbig2_allocator *) allocator)->ctx;
68
5.63k
  fz_free(ctx, p);
69
5.63k
}
70
71
static void *fz_jbig2_realloc(Jbig2Allocator *allocator, void *p, size_t size)
72
28
{
73
28
  fz_context *ctx = ((struct fz_jbig2_allocator *) allocator)->ctx;
74
28
  if (size == 0)
75
0
  {
76
0
    fz_free(ctx, p);
77
0
    return NULL;
78
0
  }
79
28
  if (p == NULL)
80
0
    return Memento_label(fz_malloc(ctx, size), "jbig2_realloc");
81
28
  return Memento_label(fz_realloc_no_throw(ctx, p, size), "jbig2_realloc");
82
28
}
83
84
static fz_pixmap *
85
jbig2_read_image(fz_context *ctx, struct info *jbig2, const unsigned char *buf, size_t len, int only_metadata, int subimage)
86
29
{
87
29
  Jbig2Ctx *jctx = NULL;
88
29
  Jbig2Image *page = NULL;
89
29
  struct fz_jbig2_allocator allocator;
90
29
  fz_pixmap *pix = NULL;
91
92
29
  allocator.super.alloc = fz_jbig2_alloc;
93
29
  allocator.super.free = fz_jbig2_free;
94
29
  allocator.super.realloc = fz_jbig2_realloc;
95
29
  allocator.ctx = ctx;
96
97
29
  fz_var(jctx);
98
29
  fz_var(page);
99
29
  fz_var(pix);
100
101
58
  fz_try(ctx)
102
58
  {
103
29
    jctx = jbig2_ctx_new((Jbig2Allocator *) &allocator, 0, NULL, error_callback, ctx);
104
29
    if (jctx == NULL)
105
0
      fz_throw(ctx, FZ_ERROR_LIBRARY, "cannot create jbig2 context");
106
29
    if (jbig2_data_in(jctx, buf, len) < 0)
107
3
      fz_throw(ctx, FZ_ERROR_LIBRARY, "cannot decode jbig2 image");
108
26
    if (jbig2_complete_page(jctx) < 0)
109
26
      fz_throw(ctx, FZ_ERROR_LIBRARY, "cannot complete jbig2 image");
110
111
0
    if (only_metadata && subimage < 0)
112
0
    {
113
0
      while ((page = jbig2_page_out(jctx)) != NULL)
114
0
      {
115
0
        jbig2_release_page(jctx, page);
116
0
        jbig2->pages++;
117
0
      }
118
0
    }
119
0
    else if (only_metadata && subimage >= 0)
120
0
    {
121
0
      while ((page = jbig2_page_out(jctx)) != NULL && subimage > 0)
122
0
      {
123
0
        jbig2_release_page(jctx, page);
124
0
        subimage--;
125
0
      }
126
127
0
      if (page == NULL)
128
0
        fz_throw(ctx, FZ_ERROR_LIBRARY, "no jbig2 image decoded");
129
130
0
      jbig2->cspace = fz_device_gray(ctx);
131
0
      jbig2->width = page->width;
132
0
      jbig2->height = page->height;
133
0
      jbig2->xres = 72;
134
0
      jbig2->yres = 72;
135
0
    }
136
0
    else if (subimage >= 0)
137
0
    {
138
0
      while ((page = jbig2_page_out(jctx)) != NULL && subimage > 0)
139
0
      {
140
0
        jbig2_release_page(jctx, page);
141
0
        subimage--;
142
0
      }
143
144
0
      if (page == NULL)
145
0
        fz_throw(ctx, FZ_ERROR_LIBRARY, "no jbig2 image decoded");
146
147
0
      jbig2->cspace = fz_device_gray(ctx);
148
0
      jbig2->width = page->width;
149
0
      jbig2->height = page->height;
150
0
      jbig2->xres = 72;
151
0
      jbig2->yres = 72;
152
153
0
      pix = fz_new_pixmap(ctx, jbig2->cspace, jbig2->width, jbig2->height, NULL, 0);
154
0
      fz_unpack_tile(ctx, pix, page->data, 1, 1, page->stride, 0);
155
0
      fz_invert_pixmap(ctx, pix);
156
0
    }
157
0
  }
158
58
  fz_always(ctx)
159
29
  {
160
29
    jbig2_release_page(jctx, page);
161
29
    jbig2_ctx_free(jctx);
162
29
  }
163
29
  fz_catch(ctx)
164
29
  {
165
29
    fz_drop_pixmap(ctx, pix);
166
29
    fz_rethrow(ctx);
167
29
  }
168
169
18.4E
  return pix;
170
0
}
171
172
int
173
fz_load_jbig2_subimage_count(fz_context *ctx, const unsigned char *buf, size_t len)
174
29
{
175
29
  struct info jbig2 = { 0 };
176
29
  int subimage_count = 0;
177
178
58
  fz_try(ctx)
179
58
  {
180
29
    jbig2_read_image(ctx, &jbig2, buf, len, 1, -1);
181
29
    subimage_count = jbig2.pages;
182
29
  }
183
58
  fz_catch(ctx)
184
29
    fz_rethrow(ctx);
185
186
0
  return subimage_count;
187
29
}
188
189
void
190
fz_load_jbig2_info_subimage(fz_context *ctx, const unsigned char *buf, size_t len, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep, int subimage)
191
0
{
192
0
  struct info jbig2 = { 0 };
193
194
0
  jbig2_read_image(ctx, &jbig2, buf, len, 1, subimage);
195
0
  *cspacep = fz_keep_colorspace(ctx, jbig2.cspace);
196
0
  *wp = jbig2.width;
197
0
  *hp = jbig2.height;
198
0
  *xresp = jbig2.xres;
199
0
  *yresp = jbig2.yres;
200
0
}
201
202
fz_pixmap *
203
fz_load_jbig2_subimage(fz_context *ctx, const unsigned char *buf, size_t len, int subimage)
204
0
{
205
0
  struct info jbig2 = { 0 };
206
0
  return jbig2_read_image(ctx, &jbig2, buf, len, 0, subimage);
207
0
}
208
209
fz_pixmap *
210
fz_load_jbig2(fz_context *ctx, const unsigned char *buf, size_t len)
211
0
{
212
0
  return fz_load_jbig2_subimage(ctx, buf, len, 0);
213
0
}
214
215
void
216
fz_load_jbig2_info(fz_context *ctx, const unsigned char *buf, size_t len, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep)
217
0
{
218
0
  fz_load_jbig2_info_subimage(ctx, buf, len, wp, hp, xresp, yresp, cspacep, 0);
219
0
}