Coverage Report

Created: 2024-05-20 06:23

/src/mupdf/source/pdf/pdf-image.c
Line
Count
Source (jump to first uncovered line)
1
// Copyright (C) 2004-2023 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
#include "mupdf/pdf.h"
25
26
#include <string.h>
27
28
static fz_image *pdf_load_jpx(fz_context *ctx, pdf_document *doc, pdf_obj *dict, int forcemask);
29
30
static fz_image *
31
pdf_load_jpx_imp(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *dict, fz_stream *cstm, int forcemask)
32
3.60k
{
33
3.60k
  fz_image *image = pdf_load_jpx(ctx, doc, dict, forcemask);
34
35
3.60k
  if (forcemask)
36
13
  {
37
13
    fz_pixmap_image *cimg = (fz_pixmap_image *)image;
38
13
    fz_pixmap *mask_pixmap;
39
13
    fz_pixmap *tile = fz_pixmap_image_tile(ctx, cimg);
40
41
13
    if (tile->n != 1)
42
0
    {
43
0
      fz_pixmap *gray = fz_convert_pixmap(ctx, tile, fz_device_gray(ctx), NULL, NULL, fz_default_color_params, 0);
44
0
      fz_drop_pixmap(ctx, tile);
45
0
      tile = gray;
46
0
    }
47
48
13
    mask_pixmap = fz_alpha_from_gray(ctx, tile);
49
13
    fz_drop_pixmap(ctx, tile);
50
13
    fz_set_pixmap_image_tile(ctx, cimg, mask_pixmap);
51
13
  }
52
53
3.60k
  return image;
54
3.60k
}
55
56
static fz_image *
57
pdf_load_image_imp(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *dict, fz_stream *cstm, int forcemask)
58
39.3k
{
59
39.3k
  fz_image *image = NULL;
60
39.3k
  pdf_obj *obj, *res;
61
62
39.3k
  int w, h, bpc, n;
63
39.3k
  int imagemask;
64
39.3k
  int interpolate;
65
39.3k
  int indexed;
66
39.3k
  fz_image *mask = NULL; /* explicit mask/soft mask image */
67
39.3k
  int use_colorkey = 0;
68
39.3k
  fz_colorspace *colorspace = NULL;
69
39.3k
  float decode[FZ_MAX_COLORS * 2];
70
39.3k
  int colorkey[FZ_MAX_COLORS * 2];
71
39.3k
  int stride;
72
73
39.3k
  int i;
74
39.3k
  fz_compressed_buffer *buffer;
75
76
  /* special case for JPEG2000 images */
77
39.3k
  if (pdf_is_jpx_image(ctx, dict))
78
3.60k
    return pdf_load_jpx_imp(ctx, doc, rdb, dict, cstm, forcemask);
79
80
35.6k
  w = pdf_to_int(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(Width), PDF_NAME(W)));
81
35.6k
  h = pdf_to_int(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(Height), PDF_NAME(H)));
82
35.6k
  bpc = pdf_to_int(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(BitsPerComponent), PDF_NAME(BPC)));
83
35.6k
  if (bpc == 0)
84
1.44k
    bpc = 8;
85
35.6k
  imagemask = pdf_to_bool(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(ImageMask), PDF_NAME(IM)));
86
35.6k
  interpolate = pdf_to_bool(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(Interpolate), PDF_NAME(I)));
87
88
35.6k
  indexed = 0;
89
35.6k
  use_colorkey = 0;
90
91
35.6k
  if (imagemask)
92
25.4k
    bpc = 1;
93
94
35.6k
  if (w <= 0)
95
243
    fz_throw(ctx, FZ_ERROR_SYNTAX, "image width is zero (or less)");
96
35.4k
  if (h <= 0)
97
262
    fz_throw(ctx, FZ_ERROR_SYNTAX, "image height is zero (or less)");
98
35.1k
  if (bpc <= 0)
99
10
    fz_throw(ctx, FZ_ERROR_SYNTAX, "image depth is zero (or less)");
100
35.1k
  if (bpc > 16)
101
52
    fz_throw(ctx, FZ_ERROR_SYNTAX, "image depth is too large: %d", bpc);
102
35.1k
  if (SIZE_MAX / w < (size_t)(bpc+7)/8)
103
0
    fz_throw(ctx, FZ_ERROR_SYNTAX, "image is too large");
104
35.1k
  if (SIZE_MAX / h < w * (size_t)((bpc+7)/8))
105
0
    fz_throw(ctx, FZ_ERROR_SYNTAX, "image is too large");
106
107
35.1k
  fz_var(mask);
108
35.1k
  fz_var(image);
109
35.1k
  fz_var(colorspace);
110
111
70.2k
  fz_try(ctx)
112
70.2k
  {
113
35.1k
    obj = pdf_dict_geta(ctx, dict, PDF_NAME(ColorSpace), PDF_NAME(CS));
114
35.1k
    if (obj && !imagemask && !forcemask)
115
7.94k
    {
116
      /* colorspace resource lookup is only done for inline images */
117
7.94k
      if (pdf_is_name(ctx, obj))
118
6.48k
      {
119
6.48k
        res = pdf_dict_get(ctx, pdf_dict_get(ctx, rdb, PDF_NAME(ColorSpace)), obj);
120
6.48k
        if (res)
121
0
          obj = res;
122
6.48k
      }
123
124
7.94k
      colorspace = pdf_load_colorspace(ctx, obj);
125
7.94k
      indexed = fz_colorspace_is_indexed(ctx, colorspace);
126
127
7.94k
      n = fz_colorspace_n(ctx, colorspace);
128
7.94k
    }
129
27.1k
    else
130
27.1k
    {
131
27.1k
      n = 1;
132
27.1k
    }
133
134
35.1k
    if (SIZE_MAX / n < h * ((size_t)w) * ((bpc+7)/8))
135
0
      fz_throw(ctx, FZ_ERROR_SYNTAX, "image is too large");
136
137
35.1k
    obj = pdf_dict_geta(ctx, dict, PDF_NAME(Decode), PDF_NAME(D));
138
35.1k
    if (obj)
139
18.9k
    {
140
58.1k
      for (i = 0; i < n * 2; i++)
141
39.1k
        decode[i] = pdf_array_get_real(ctx, obj, i);
142
18.9k
    }
143
16.1k
    else if (fz_colorspace_is_lab(ctx, colorspace))
144
0
    {
145
0
      decode[0] = 0;
146
0
      decode[1] = 100;
147
0
      decode[2] = -128;
148
0
      decode[3] = 127;
149
0
      decode[4] = -128;
150
0
      decode[5] = 127;
151
0
    }
152
16.1k
    else
153
16.1k
    {
154
16.1k
      float maxval = indexed ? (1 << bpc) - 1 : 1;
155
58.9k
      for (i = 0; i < n * 2; i++)
156
42.8k
        decode[i] = i & 1 ? maxval : 0;
157
16.1k
    }
158
159
35.1k
    obj = pdf_dict_geta(ctx, dict, PDF_NAME(SMask), PDF_NAME(Mask));
160
35.1k
    if (pdf_is_dict(ctx, obj))
161
1.30k
    {
162
      /* Not allowed for inline images or soft masks */
163
1.30k
      if (cstm)
164
2
        fz_warn(ctx, "Ignoring invalid inline image soft mask");
165
1.30k
      else if (forcemask)
166
0
        fz_warn(ctx, "Ignoring recursive image soft mask");
167
1.30k
      else
168
1.30k
      {
169
1.30k
        mask = pdf_load_image_imp(ctx, doc, rdb, obj, NULL, 1);
170
1.30k
        obj = pdf_dict_get(ctx, obj, PDF_NAME(Matte));
171
1.30k
        if (pdf_is_array(ctx, obj))
172
7
        {
173
7
          use_colorkey = 1;
174
28
          for (i = 0; i < n; i++)
175
21
            colorkey[i] = fz_clamp(pdf_array_get_real(ctx, obj, i), 0, 1) * 255;
176
7
        }
177
1.30k
      }
178
1.30k
    }
179
33.8k
    else if (pdf_is_array(ctx, obj))
180
18
    {
181
18
      use_colorkey = 1;
182
86
      for (i = 0; i < n * 2; i++)
183
68
      {
184
68
        if (!pdf_is_int(ctx, pdf_array_get(ctx, obj, i)))
185
0
        {
186
0
          fz_warn(ctx, "invalid value in color key mask");
187
0
          use_colorkey = 0;
188
0
        }
189
68
        colorkey[i] = pdf_array_get_int(ctx, obj, i);
190
68
      }
191
18
    }
192
193
    /* Do we load from a ref, or do we load an inline stream? */
194
35.1k
    if (cstm == NULL)
195
4.12k
    {
196
      /* Just load the compressed image data now and we can decode it on demand. */
197
4.12k
      size_t worst_case = w * (size_t)h;
198
4.12k
      worst_case = (worst_case * bpc + 7) >> 3;
199
4.12k
      if (colorspace)
200
2.43k
        worst_case *= colorspace->n;
201
4.12k
      buffer = pdf_load_compressed_stream(ctx, doc, pdf_to_num(ctx, dict), worst_case);
202
4.12k
      image = fz_new_image_from_compressed_buffer(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, use_colorkey ? colorkey : NULL, buffer, mask);
203
4.12k
    }
204
31.0k
    else
205
31.0k
    {
206
      /* Inline stream */
207
31.0k
      stride = (w * n * bpc + 7) / 8;
208
31.0k
      image = fz_new_image_from_compressed_buffer(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, use_colorkey ? colorkey : NULL, NULL, mask);
209
31.0k
      pdf_load_compressed_inline_image(ctx, doc, dict, stride * h, cstm, indexed, (fz_compressed_image *)image);
210
31.0k
    }
211
35.1k
  }
212
70.2k
  fz_always(ctx)
213
35.1k
  {
214
35.1k
    fz_drop_colorspace(ctx, colorspace);
215
35.1k
    fz_drop_image(ctx, mask);
216
35.1k
  }
217
35.1k
  fz_catch(ctx)
218
375
  {
219
375
    fz_drop_image(ctx, image);
220
375
    fz_rethrow(ctx);
221
375
  }
222
34.7k
  return image;
223
35.1k
}
224
225
fz_image *
226
pdf_load_inline_image(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *dict, fz_stream *file)
227
31.0k
{
228
31.0k
  return pdf_load_image_imp(ctx, doc, rdb, dict, file, 0);
229
31.0k
}
230
231
int
232
pdf_is_jpx_image(fz_context *ctx, pdf_obj *dict)
233
39.3k
{
234
39.3k
  pdf_obj *filter;
235
39.3k
  int i, n;
236
237
39.3k
  filter = pdf_dict_get(ctx, dict, PDF_NAME(Filter));
238
39.3k
  if (pdf_name_eq(ctx, filter, PDF_NAME(JPXDecode)))
239
3.60k
    return 1;
240
35.6k
  n = pdf_array_len(ctx, filter);
241
37.9k
  for (i = 0; i < n; i++)
242
2.20k
    if (pdf_name_eq(ctx, pdf_array_get(ctx, filter, i), PDF_NAME(JPXDecode)))
243
0
      return 1;
244
35.6k
  return 0;
245
35.6k
}
246
247
static fz_image *
248
pdf_load_jpx(fz_context *ctx, pdf_document *doc, pdf_obj *dict, int forcemask)
249
3.60k
{
250
3.60k
  fz_buffer *buf = NULL;
251
3.60k
  fz_colorspace *colorspace = NULL;
252
3.60k
  fz_pixmap *pix = NULL;
253
3.60k
  pdf_obj *obj;
254
3.60k
  fz_image *mask = NULL;
255
3.60k
  fz_image *img = NULL;
256
257
3.60k
  fz_var(pix);
258
3.60k
  fz_var(buf);
259
3.60k
  fz_var(colorspace);
260
3.60k
  fz_var(mask);
261
262
3.60k
  buf = pdf_load_stream(ctx, dict);
263
264
  /* FIXME: We can't handle decode arrays for indexed images currently */
265
7.20k
  fz_try(ctx)
266
7.20k
  {
267
3.60k
    unsigned char *data;
268
3.60k
    size_t len;
269
270
3.60k
    obj = pdf_dict_get(ctx, dict, PDF_NAME(ColorSpace));
271
3.60k
    if (obj)
272
56
      colorspace = pdf_load_colorspace(ctx, obj);
273
274
3.60k
    len = fz_buffer_storage(ctx, buf, &data);
275
3.60k
    pix = fz_load_jpx(ctx, data, len, colorspace);
276
277
3.60k
    obj = pdf_dict_geta(ctx, dict, PDF_NAME(SMask), PDF_NAME(Mask));
278
3.60k
    if (pdf_is_dict(ctx, obj))
279
11
    {
280
11
      if (forcemask)
281
0
        fz_warn(ctx, "Ignoring recursive JPX soft mask");
282
11
      else
283
11
        mask = pdf_load_image_imp(ctx, doc, NULL, obj, NULL, 1);
284
11
    }
285
286
3.60k
    obj = pdf_dict_geta(ctx, dict, PDF_NAME(Decode), PDF_NAME(D));
287
3.60k
    if (obj && !fz_colorspace_is_indexed(ctx, colorspace))
288
0
    {
289
0
      float decode[FZ_MAX_COLORS * 2];
290
0
      int i;
291
292
0
      for (i = 0; i < pix->n * 2; i++)
293
0
        decode[i] = pdf_array_get_real(ctx, obj, i);
294
295
0
      fz_decode_tile(ctx, pix, decode);
296
0
    }
297
298
3.60k
    img = fz_new_image_from_pixmap(ctx, pix, mask);
299
3.60k
  }
300
7.20k
  fz_always(ctx)
301
3.60k
  {
302
3.60k
    fz_drop_image(ctx, mask);
303
3.60k
    fz_drop_pixmap(ctx, pix);
304
3.60k
    fz_drop_colorspace(ctx, colorspace);
305
3.60k
    fz_drop_buffer(ctx, buf);
306
3.60k
  }
307
3.60k
  fz_catch(ctx)
308
3.56k
  {
309
3.56k
    fz_morph_error(ctx, FZ_ERROR_FORMAT, FZ_ERROR_SYNTAX);
310
3.56k
    fz_morph_error(ctx, FZ_ERROR_LIBRARY, FZ_ERROR_SYNTAX);
311
3.56k
    fz_rethrow(ctx);
312
3.56k
  }
313
314
38
  return img;
315
3.60k
}
316
317
fz_image *
318
pdf_load_image(fz_context *ctx, pdf_document *doc, pdf_obj *dict)
319
25.8k
{
320
25.8k
  fz_image *image;
321
322
25.8k
  if ((image = pdf_find_item(ctx, fz_drop_image_imp, dict)) != NULL)
323
18.9k
    return image;
324
325
6.90k
  image = pdf_load_image_imp(ctx, doc, NULL, dict, NULL, 0);
326
6.90k
  pdf_store_item(ctx, dict, image, fz_image_size(ctx, image));
327
6.90k
  return image;
328
25.8k
}
329
330
struct jbig2_segment_header {
331
  int number;
332
  int flags;
333
  /* referred-to-segment numbers */
334
  int page;
335
  int length;
336
};
337
338
/* coverity[-tainted_data_return] */
339
static uint32_t getu32(const unsigned char *data)
340
0
{
341
0
  return ((uint32_t)data[0]<<24) | ((uint32_t)data[1]<<16) | ((uint32_t)data[2]<<8) | (uint32_t)data[3];
342
0
}
343
344
static size_t
345
pdf_parse_jbig2_segment_header(fz_context *ctx,
346
  const unsigned char *data, const unsigned char *end,
347
  struct jbig2_segment_header *info)
348
0
{
349
0
  uint32_t rts;
350
0
  size_t n = 5;
351
352
0
  if (data + 11 > end) return 0;
353
354
0
  info->number = getu32(data);
355
0
  info->flags = data[4];
356
357
0
  rts = (data[5] >> 5) & 0x7;
358
0
  if (rts == 7)
359
0
  {
360
0
    rts = getu32(data+5) & 0x1FFFFFFF;
361
0
    n += 4 + (rts + 1) / 8;
362
0
  }
363
0
  else
364
0
  {
365
0
    n += 1;
366
0
  }
367
368
0
  if (info->number <= 256)
369
0
    n += rts;
370
0
  else if (info->number <= 65536)
371
0
    n += rts * 2;
372
0
  else
373
0
    n += rts * 4;
374
375
0
  if (info->flags & 0x40)
376
0
  {
377
0
    if (data + n + 4 > end) return 0;
378
0
    info->page = getu32(data+n);
379
0
    n += 4;
380
0
  }
381
0
  else
382
0
  {
383
0
    if (data + n + 1 > end) return 0;
384
0
    info->page = data[n];
385
0
    n += 1;
386
0
  }
387
388
0
  if (data + n + 4 > end) return 0;
389
0
  info->length = getu32(data+n);
390
0
  return n + 4;
391
0
}
392
393
static void
394
pdf_copy_jbig2_segments(fz_context *ctx, fz_buffer *output, const unsigned char *data, size_t size, int page)
395
0
{
396
0
  struct jbig2_segment_header info;
397
0
  const unsigned char *end = data + size;
398
0
  size_t n;
399
0
  int type;
400
401
0
  while (data < end)
402
0
  {
403
0
    n = pdf_parse_jbig2_segment_header(ctx, data, end, &info);
404
0
    if (n == 0)
405
0
      fz_throw(ctx, FZ_ERROR_FORMAT, "truncated jbig2 segment header");
406
407
    /* omit end of page, end of file, and segments for other pages */
408
0
    type = (info.flags & 63);
409
0
    if (type == 49 || type == 51 || (info.page > 0 && info.page != page))
410
0
    {
411
0
      data += n;
412
0
      data += info.length;
413
0
    }
414
0
    else
415
0
    {
416
0
      fz_append_data(ctx, output, data, n);
417
0
      data += n;
418
0
      if (data + info.length > end)
419
0
        fz_throw(ctx, FZ_ERROR_FORMAT, "truncated jbig2 segment data");
420
0
      fz_append_data(ctx, output, data, info.length);
421
0
      data += info.length;
422
0
    }
423
0
  }
424
0
}
425
426
static void
427
pdf_copy_jbig2_random_segments(fz_context *ctx, fz_buffer *output, const unsigned char *data, size_t size, int page)
428
0
{
429
0
  struct jbig2_segment_header info;
430
0
  const unsigned char *header = data;
431
0
  const unsigned char *header_end;
432
0
  const unsigned char *end = data + size;
433
0
  size_t n;
434
0
  int type;
435
436
  /* Skip headers until end-of-file segment is found. */
437
0
  while (data < end)
438
0
  {
439
0
    n = pdf_parse_jbig2_segment_header(ctx, data, end, &info);
440
0
    if (n == 0)
441
0
      fz_throw(ctx, FZ_ERROR_FORMAT, "truncated jbig2 segment header");
442
0
    data += n;
443
0
    if ((info.flags & 63) == 51)
444
0
      break;
445
0
  }
446
0
  if (data >= end)
447
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "truncated jbig2 segment header");
448
449
  /* Copy segment headers and segment data */
450
0
  header_end = data;
451
0
  while (data < end && header < header_end)
452
0
  {
453
0
    n = pdf_parse_jbig2_segment_header(ctx, header, header_end, &info);
454
0
    if (n == 0)
455
0
      fz_throw(ctx, FZ_ERROR_FORMAT, "truncated jbig2 segment header");
456
457
    /* omit end of page, end of file, and segments for other pages */
458
0
    type = (info.flags & 63);
459
0
    if (type == 49 || type == 51 || (info.page > 0 && info.page != page))
460
0
    {
461
0
      header += n;
462
0
      data += info.length;
463
0
    }
464
0
    else
465
0
    {
466
0
      fz_append_data(ctx, output, header, n);
467
0
      header += n;
468
0
      if (data + info.length > end)
469
0
        fz_throw(ctx, FZ_ERROR_FORMAT, "truncated jbig2 segment data");
470
0
      fz_append_data(ctx, output, data, info.length);
471
0
      data += info.length;
472
0
    }
473
0
  }
474
0
}
475
476
static fz_buffer *
477
pdf_jbig2_stream_from_file(fz_context *ctx, fz_buffer *input, fz_jbig2_globals *globals_, int page)
478
0
{
479
0
  fz_buffer *globals = fz_jbig2_globals_data(ctx, globals_);
480
0
  size_t globals_size = globals ? globals->len : 0;
481
0
  fz_buffer *output;
482
0
  int flags;
483
0
  size_t header = 9;
484
485
0
  if (input->len < 9)
486
0
    return NULL; /* not enough data! */
487
0
  flags = input->data[8];
488
0
  if ((flags & 2) == 0)
489
0
  {
490
0
    if (input->len < 13)
491
0
      return NULL; /* not enough data! */
492
0
    header = 13;
493
0
  }
494
495
0
  output = fz_new_buffer(ctx, input->len + globals_size);
496
0
  fz_try(ctx)
497
0
  {
498
0
    if (globals_size > 0)
499
0
      fz_append_buffer(ctx, output, globals);
500
0
    if ((flags & 1) == 0)
501
0
      pdf_copy_jbig2_random_segments(ctx, output, input->data + header, input->len - header, page);
502
0
    else
503
0
      pdf_copy_jbig2_segments(ctx, output, input->data + header, input->len - header, page);
504
0
  }
505
0
  fz_catch(ctx)
506
0
  {
507
0
    fz_drop_buffer(ctx, output);
508
0
    fz_rethrow(ctx);
509
0
  }
510
511
0
  return output;
512
0
}
513
514
pdf_obj *
515
pdf_add_image(fz_context *ctx, pdf_document *doc, fz_image *image)
516
0
{
517
0
  fz_pixmap *pixmap = NULL;
518
0
  pdf_obj *imobj = NULL;
519
0
  pdf_obj *dp;
520
0
  fz_buffer *buffer = NULL;
521
0
  fz_compressed_buffer *cbuffer;
522
0
  fz_pixmap *smask_pixmap = NULL;
523
0
  fz_image *smask_image = NULL;
524
0
  int i, n;
525
526
0
  fz_var(pixmap);
527
0
  fz_var(buffer);
528
0
  fz_var(imobj);
529
0
  fz_var(smask_pixmap);
530
0
  fz_var(smask_image);
531
532
0
  pdf_begin_operation(ctx, doc, "Add image");
533
534
0
  fz_try(ctx)
535
0
  {
536
    /* If we can maintain compression, do so */
537
0
    cbuffer = fz_compressed_image_buffer(ctx, image);
538
539
0
    imobj = pdf_add_new_dict(ctx, doc, 3);
540
541
0
    dp = pdf_dict_put_dict(ctx, imobj, PDF_NAME(DecodeParms), 3);
542
0
    pdf_dict_put(ctx, imobj, PDF_NAME(Type), PDF_NAME(XObject));
543
0
    pdf_dict_put(ctx, imobj, PDF_NAME(Subtype), PDF_NAME(Image));
544
545
0
    if (cbuffer)
546
0
    {
547
0
      fz_compression_params *cp = &cbuffer->params;
548
0
      switch (cp->type)
549
0
      {
550
0
      default:
551
0
        goto unknown_compression;
552
0
      case FZ_IMAGE_RAW:
553
0
        break;
554
0
      case FZ_IMAGE_JPEG:
555
0
        pdf_dict_put(ctx, imobj, PDF_NAME(Filter), PDF_NAME(DCTDecode));
556
0
        if (cp->u.jpeg.color_transform >= 0)
557
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(ColorTransform), cp->u.jpeg.color_transform);
558
0
        if (cp->u.jpeg.invert_cmyk && image->n == 4)
559
0
        {
560
0
          pdf_obj *arr;
561
0
          arr = pdf_dict_put_array(ctx, imobj, PDF_NAME(Decode), 8);
562
0
          pdf_array_push_int(ctx, arr, 1);
563
0
          pdf_array_push_int(ctx, arr, 0);
564
0
          pdf_array_push_int(ctx, arr, 1);
565
0
          pdf_array_push_int(ctx, arr, 0);
566
0
          pdf_array_push_int(ctx, arr, 1);
567
0
          pdf_array_push_int(ctx, arr, 0);
568
0
          pdf_array_push_int(ctx, arr, 1);
569
0
          pdf_array_push_int(ctx, arr, 0);
570
0
        }
571
0
        break;
572
0
      case FZ_IMAGE_JPX:
573
0
        if (cp->u.jpx.smask_in_data)
574
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(SMaskInData), cp->u.jpx.smask_in_data);
575
0
        pdf_dict_put(ctx, imobj, PDF_NAME(Filter), PDF_NAME(JPXDecode));
576
0
        break;
577
0
      case FZ_IMAGE_JBIG2:
578
0
        if (cp->u.jbig2.embedded && cp->u.jbig2.globals)
579
0
        {
580
0
          pdf_obj *globals_ref = pdf_add_new_dict(ctx, doc, 1);
581
0
          pdf_update_stream(ctx, doc, globals_ref, fz_jbig2_globals_data(ctx, cp->u.jbig2.globals), 0);
582
0
          pdf_dict_put(ctx, dp, PDF_NAME(JBIG2Globals), globals_ref);
583
0
        }
584
0
        else
585
0
          buffer = pdf_jbig2_stream_from_file(ctx, cbuffer->buffer,
586
0
            cp->u.jbig2.globals,
587
0
            1);
588
0
        if (!buffer)
589
0
          goto unknown_compression;
590
0
        pdf_dict_put(ctx, imobj, PDF_NAME(Filter), PDF_NAME(JBIG2Decode));
591
0
        break;
592
0
      case FZ_IMAGE_FAX:
593
0
        if (cp->u.fax.columns)
594
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(Columns), cp->u.fax.columns);
595
0
        if (cp->u.fax.rows)
596
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(Rows), cp->u.fax.rows);
597
0
        if (cp->u.fax.k)
598
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(K), cp->u.fax.k);
599
0
        if (cp->u.fax.end_of_line)
600
0
          pdf_dict_put_bool(ctx, dp, PDF_NAME(EndOfLine), cp->u.fax.end_of_line);
601
0
        if (cp->u.fax.encoded_byte_align)
602
0
          pdf_dict_put_bool(ctx, dp, PDF_NAME(EncodedByteAlign), cp->u.fax.encoded_byte_align);
603
0
        if (cp->u.fax.end_of_block)
604
0
          pdf_dict_put_bool(ctx, dp, PDF_NAME(EndOfBlock), cp->u.fax.end_of_block);
605
0
        if (cp->u.fax.black_is_1)
606
0
          pdf_dict_put_bool(ctx, dp, PDF_NAME(BlackIs1), cp->u.fax.black_is_1);
607
0
        if (cp->u.fax.damaged_rows_before_error)
608
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(DamagedRowsBeforeError), cp->u.fax.damaged_rows_before_error);
609
0
        pdf_dict_put(ctx, imobj, PDF_NAME(Filter), PDF_NAME(CCITTFaxDecode));
610
0
        break;
611
0
      case FZ_IMAGE_FLATE:
612
0
        if (cp->u.flate.columns)
613
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(Columns), cp->u.flate.columns);
614
0
        if (cp->u.flate.colors)
615
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(Colors), cp->u.flate.colors);
616
0
        if (cp->u.flate.predictor)
617
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(Predictor), cp->u.flate.predictor);
618
0
        if (cp->u.flate.bpc)
619
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(BitsPerComponent), cp->u.flate.bpc);
620
0
        pdf_dict_put(ctx, imobj, PDF_NAME(Filter), PDF_NAME(FlateDecode));
621
0
        break;
622
0
      case FZ_IMAGE_LZW:
623
0
        if (cp->u.lzw.columns)
624
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(Columns), cp->u.lzw.columns);
625
0
        if (cp->u.lzw.colors)
626
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(Colors), cp->u.lzw.colors);
627
0
        if (cp->u.lzw.predictor)
628
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(Predictor), cp->u.lzw.predictor);
629
0
        if (cp->u.lzw.early_change)
630
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(EarlyChange), cp->u.lzw.early_change);
631
0
        if (cp->u.lzw.bpc)
632
0
          pdf_dict_put_int(ctx, dp, PDF_NAME(BitsPerComponent), cp->u.lzw.bpc);
633
0
        pdf_dict_put(ctx, imobj, PDF_NAME(Filter), PDF_NAME(LZWDecode));
634
0
        break;
635
0
      case FZ_IMAGE_RLD:
636
0
        pdf_dict_put(ctx, imobj, PDF_NAME(Filter), PDF_NAME(RunLengthDecode));
637
0
        break;
638
0
      }
639
640
0
      if (!pdf_dict_len(ctx, dp))
641
0
        pdf_dict_del(ctx, imobj, PDF_NAME(DecodeParms));
642
643
0
      pdf_dict_put_int(ctx, imobj, PDF_NAME(BitsPerComponent), image->bpc);
644
0
      pdf_dict_put_int(ctx, imobj, PDF_NAME(Width), image->w);
645
0
      pdf_dict_put_int(ctx, imobj, PDF_NAME(Height), image->h);
646
647
0
      if (!buffer)
648
0
        buffer = fz_keep_buffer(ctx, cbuffer->buffer);
649
650
0
      if (image->use_decode)
651
0
      {
652
0
        pdf_obj *ary = pdf_dict_put_array(ctx, imobj, PDF_NAME(Decode), image->n * 2);
653
0
        for (i = 0; i < image->n * 2; ++i)
654
0
          pdf_array_push_real(ctx, ary, image->decode[i]);
655
0
      }
656
0
    }
657
0
    else
658
0
    {
659
0
unknown_compression:
660
661
0
      pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL);
662
0
      n = pixmap->n - pixmap->alpha - pixmap->s; /* number of colorants */
663
0
      if (n == 0)
664
0
        n = 1; /* treat pixmaps with only alpha or spots as grayscale */
665
666
0
      pdf_dict_put_int(ctx, imobj, PDF_NAME(Width), pixmap->w);
667
0
      pdf_dict_put_int(ctx, imobj, PDF_NAME(Height), pixmap->h);
668
669
0
      if (fz_is_pixmap_monochrome(ctx, pixmap))
670
0
      {
671
0
        int stride = (image->w + 7) / 8;
672
0
        int h = pixmap->h;
673
0
        int w = pixmap->w;
674
0
        unsigned char *s = pixmap->samples;
675
0
        unsigned char *d = fz_calloc(ctx, h, stride);
676
0
        buffer = fz_new_buffer_from_data(ctx, d, (size_t)h * stride);
677
678
0
        pdf_dict_put_int(ctx, imobj, PDF_NAME(BitsPerComponent), 1);
679
680
0
        while (h--)
681
0
        {
682
0
          int x;
683
0
          for (x = 0; x < w; ++x)
684
0
            if (s[x] > 0)
685
0
              d[x>>3] |= 1 << (7 - (x & 7));
686
0
          s += pixmap->stride;
687
0
          d += stride;
688
0
        }
689
0
      }
690
0
      else
691
0
      {
692
0
        size_t size = (size_t)pixmap->w * n;
693
0
        int h = pixmap->h;
694
0
        unsigned char *s = pixmap->samples;
695
0
        unsigned char *d = Memento_label(fz_malloc(ctx, size * h), "pdf_image_samples");
696
0
        buffer = fz_new_buffer_from_data(ctx, d, size * h);
697
698
0
        pdf_dict_put_int(ctx, imobj, PDF_NAME(BitsPerComponent), 8);
699
700
0
        if (n == pixmap->n)
701
0
        {
702
          /* If we use all channels, we can copy the data as is. */
703
0
          while (h--)
704
0
          {
705
0
            memcpy(d, s, size);
706
0
            d += size;
707
0
            s += pixmap->stride;
708
0
          }
709
0
        }
710
0
        else
711
0
        {
712
0
          size_t line_skip;
713
0
          int skip;
714
715
          /* Need to extract the alpha into a SMask and remove spot planes. */
716
          /* TODO: convert spots to colors. */
717
718
0
          if (pixmap->alpha && !image->mask)
719
0
          {
720
0
            smask_pixmap = fz_new_pixmap_from_alpha_channel(ctx, pixmap);
721
0
            smask_image = fz_new_image_from_pixmap(ctx, smask_pixmap, NULL);
722
0
            pdf_dict_put_drop(ctx, imobj, PDF_NAME(SMask), pdf_add_image(ctx, doc, smask_image));
723
0
            fz_drop_image(ctx, smask_image);
724
0
            smask_image = NULL;
725
0
            fz_drop_pixmap(ctx, smask_pixmap);
726
0
            smask_pixmap = NULL;
727
0
          }
728
729
0
          line_skip = pixmap->stride - pixmap->w * (size_t)pixmap->n;
730
0
          skip = pixmap->n - n;
731
0
          if (pixmap->alpha)
732
0
          {
733
0
            int n1 = pixmap->n-1;
734
0
            while (h--)
735
0
            {
736
0
              int w = pixmap->w;
737
0
              while (w--)
738
0
              {
739
0
                int a = s[n1];
740
0
                int inva = a ? 255 * 256 / a : 0;
741
0
                int k;
742
0
                for (k = 0; k < n; k++)
743
0
                  *d++ = (*s++ * inva) >> 8;
744
0
                s += skip;
745
0
              }
746
0
              s += line_skip;
747
0
            }
748
0
          }
749
0
          else
750
0
          {
751
0
            while (h--)
752
0
            {
753
0
              int w = pixmap->w;
754
0
              while (w--)
755
0
              {
756
0
                int k;
757
0
                for (k = 0; k < n; ++k)
758
0
                  *d++ = *s++;
759
0
                s += skip;
760
0
              }
761
0
              s += line_skip;
762
0
            }
763
0
          }
764
0
        }
765
0
      }
766
0
    }
767
768
0
    if (image->imagemask)
769
0
    {
770
0
      pdf_dict_put_bool(ctx, imobj, PDF_NAME(ImageMask), 1);
771
0
    }
772
0
    else
773
0
    {
774
0
      fz_colorspace *cs;
775
776
0
      cs = pixmap ? pixmap->colorspace : image->colorspace;
777
0
      switch (fz_colorspace_type(ctx, cs))
778
0
      {
779
0
      case FZ_COLORSPACE_INDEXED:
780
0
        {
781
0
          fz_colorspace *basecs;
782
0
          unsigned char *lookup = NULL;
783
0
          int high = 0;
784
0
          int basen;
785
0
          pdf_obj *arr;
786
787
0
          basecs = cs->u.indexed.base;
788
0
          high = cs->u.indexed.high;
789
0
          lookup = cs->u.indexed.lookup;
790
0
          basen = basecs->n;
791
792
0
          arr = pdf_dict_put_array(ctx, imobj, PDF_NAME(ColorSpace), 4);
793
794
0
          pdf_array_push(ctx, arr, PDF_NAME(Indexed));
795
0
          switch (fz_colorspace_type(ctx, basecs))
796
0
          {
797
0
          case FZ_COLORSPACE_GRAY:
798
0
            pdf_array_push(ctx, arr, PDF_NAME(DeviceGray));
799
0
            break;
800
0
          case FZ_COLORSPACE_RGB:
801
0
            pdf_array_push(ctx, arr, PDF_NAME(DeviceRGB));
802
0
            break;
803
0
          case FZ_COLORSPACE_CMYK:
804
0
            pdf_array_push(ctx, arr, PDF_NAME(DeviceCMYK));
805
0
            break;
806
0
          default:
807
            // TODO: convert to RGB!
808
0
            fz_throw(ctx, FZ_ERROR_ARGUMENT, "only indexed Gray, RGB, and CMYK colorspaces supported");
809
0
            break;
810
0
          }
811
812
0
          pdf_array_push_int(ctx, arr, high);
813
0
          pdf_array_push_string(ctx, arr, (char *) lookup, (size_t)basen * (high + 1));
814
0
        }
815
0
        break;
816
0
      case FZ_COLORSPACE_NONE:
817
0
      case FZ_COLORSPACE_GRAY:
818
0
        pdf_dict_put(ctx, imobj, PDF_NAME(ColorSpace), PDF_NAME(DeviceGray));
819
0
        break;
820
0
      case FZ_COLORSPACE_RGB:
821
0
        pdf_dict_put(ctx, imobj, PDF_NAME(ColorSpace), PDF_NAME(DeviceRGB));
822
0
        break;
823
0
      case FZ_COLORSPACE_CMYK:
824
0
        pdf_dict_put(ctx, imobj, PDF_NAME(ColorSpace), PDF_NAME(DeviceCMYK));
825
0
        break;
826
0
      case FZ_COLORSPACE_LAB:
827
0
        pdf_dict_put(ctx, imobj, PDF_NAME(ColorSpace), PDF_NAME(Lab));
828
0
        break;
829
0
      default:
830
        // TODO: convert to RGB!
831
0
        fz_throw(ctx, FZ_ERROR_ARGUMENT, "only Gray, RGB, and CMYK colorspaces supported");
832
0
        break;
833
0
      }
834
0
    }
835
836
0
    if (image->mask)
837
0
    {
838
0
      if (image->mask->imagemask)
839
0
        pdf_dict_put_drop(ctx, imobj, PDF_NAME(Mask), pdf_add_image(ctx, doc, image->mask));
840
0
      else
841
0
        pdf_dict_put_drop(ctx, imobj, PDF_NAME(SMask), pdf_add_image(ctx, doc, image->mask));
842
0
    }
843
844
0
    pdf_update_stream(ctx, doc, imobj, buffer, 1);
845
0
    pdf_end_operation(ctx, doc);
846
0
  }
847
0
  fz_always(ctx)
848
0
  {
849
0
    fz_drop_image(ctx, smask_image);
850
0
    fz_drop_pixmap(ctx, smask_pixmap);
851
0
    fz_drop_pixmap(ctx, pixmap);
852
0
    fz_drop_buffer(ctx, buffer);
853
0
  }
854
0
  fz_catch(ctx)
855
0
  {
856
0
    pdf_drop_obj(ctx, imobj);
857
0
    pdf_abandon_operation(ctx, doc);
858
0
    fz_rethrow(ctx);
859
0
  }
860
0
  return imobj;
861
0
}