Coverage Report

Created: 2025-11-07 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mupdf/source/fitz/image.c
Line
Count
Source
1
// Copyright (C) 2004-2025 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 "context-imp.h"
26
#include "image-imp.h"
27
#include "pixmap-imp.h"
28
29
#include <string.h>
30
#include <math.h>
31
#include <assert.h>
32
33
/* TODO: here or public? */
34
static int
35
fz_key_storable_needs_reaping(fz_context *ctx, const fz_key_storable *ks)
36
2
{
37
2
  return ks == NULL ? 0 : (ks->store_key_refs == ks->storable.refs);
38
2
}
39
40
64
#define SANE_DPI 72.0f
41
48
#define INSANE_DPI 4800.0f
42
43
0
#define SCALABLE_IMAGE_DPI 96
44
45
struct fz_compressed_image
46
{
47
  fz_image super;
48
  fz_compressed_buffer *buffer;
49
};
50
51
struct fz_pixmap_image
52
{
53
  fz_image super;
54
  fz_pixmap *tile;
55
};
56
57
typedef struct
58
{
59
  int refs;
60
  fz_image *image;
61
  int l2factor;
62
  fz_irect rect;
63
} fz_image_key;
64
65
fz_image *
66
fz_keep_image(fz_context *ctx, fz_image *image)
67
16
{
68
16
  return fz_keep_key_storable(ctx, &image->key_storable);
69
16
}
70
71
fz_image *
72
fz_keep_image_store_key(fz_context *ctx, fz_image *image)
73
2
{
74
2
  return fz_keep_key_storable_key(ctx, &image->key_storable);
75
2
}
76
77
void
78
fz_drop_image_store_key(fz_context *ctx, fz_image *image)
79
2
{
80
2
  fz_drop_key_storable_key(ctx, &image->key_storable);
81
2
}
82
83
static int
84
fz_make_hash_image_key(fz_context *ctx, fz_store_hash *hash, void *key_)
85
20
{
86
20
  fz_image_key *key = (fz_image_key *)key_;
87
20
  hash->u.pir.ptr = key->image;
88
20
  hash->u.pir.i = key->l2factor;
89
20
  hash->u.pir.r = key->rect;
90
20
  return 1;
91
20
}
92
93
static void *
94
fz_keep_image_key(fz_context *ctx, void *key_)
95
2
{
96
2
  fz_image_key *key = (fz_image_key *)key_;
97
2
  return fz_keep_imp(ctx, key, &key->refs);
98
2
}
99
100
static void
101
fz_drop_image_key(fz_context *ctx, void *key_)
102
4
{
103
4
  fz_image_key *key = (fz_image_key *)key_;
104
4
  if (fz_drop_imp(ctx, key, &key->refs))
105
2
  {
106
2
    fz_drop_image_store_key(ctx, key->image);
107
2
    fz_free(ctx, key);
108
2
  }
109
4
}
110
111
static int
112
fz_cmp_image_key(fz_context *ctx, void *k0_, void *k1_)
113
0
{
114
0
  fz_image_key *k0 = (fz_image_key *)k0_;
115
0
  fz_image_key *k1 = (fz_image_key *)k1_;
116
0
  return k0->image == k1->image && k0->l2factor == k1->l2factor && k0->rect.x0 == k1->rect.x0 && k0->rect.y0 == k1->rect.y0 && k0->rect.x1 == k1->rect.x1 && k0->rect.y1 == k1->rect.y1;
117
0
}
118
119
static void
120
fz_format_image_key(fz_context *ctx, char *s, size_t n, void *key_)
121
0
{
122
0
  fz_image_key *key = (fz_image_key *)key_;
123
0
  fz_snprintf(s, n, "(image %d x %d sf=%d)", key->image->w, key->image->h, key->l2factor);
124
0
}
125
126
static int
127
fz_needs_reap_image_key(fz_context *ctx, void *key_)
128
2
{
129
2
  fz_image_key *key = (fz_image_key *)key_;
130
131
2
  return fz_key_storable_needs_reaping(ctx, &key->image->key_storable);
132
2
}
133
134
static const fz_store_type fz_image_store_type =
135
{
136
  "fz_image",
137
  fz_make_hash_image_key,
138
  fz_keep_image_key,
139
  fz_drop_image_key,
140
  fz_cmp_image_key,
141
  fz_format_image_key,
142
  fz_needs_reap_image_key
143
};
144
145
void
146
fz_drop_image(fz_context *ctx, fz_image *image)
147
28
{
148
28
  fz_drop_key_storable(ctx, &image->key_storable);
149
28
}
150
151
static void
152
fz_mask_color_key(fz_context *ctx, fz_pixmap *pix, int n, int bpc, const int *colorkey_in, int indexed)
153
0
{
154
0
  unsigned char *p = pix->samples;
155
0
  int w;
156
0
  int k, t;
157
0
  int h = pix->h;
158
0
  size_t stride = pix->stride - pix->w * (size_t)pix->n;
159
0
  int colorkey[FZ_MAX_COLORS * 2];
160
0
  int scale, shift, max;
161
162
0
  if (pix->w == 0)
163
0
    return;
164
165
0
  if (indexed)
166
0
  {
167
    /* no upscaling or downshifting needed for indexed images */
168
0
    scale = 1;
169
0
    shift = 0;
170
0
  }
171
0
  else
172
0
  {
173
0
    switch (bpc)
174
0
    {
175
0
    case 1: scale = 255; shift = 0; break;
176
0
    case 2: scale = 85; shift = 0; break;
177
0
    case 4: scale = 17; shift = 0; break;
178
0
    default:
179
0
    case 8: scale = 1; shift = 0; break;
180
0
    case 16: scale = 1; shift = 8; break;
181
0
    case 24: scale = 1; shift = 16; break;
182
0
    case 32: scale = 1; shift = 24; break;
183
0
    }
184
0
  }
185
186
0
  switch (bpc)
187
0
  {
188
0
  case 1: max = 1; break;
189
0
  case 2: max = 3; break;
190
0
  case 4: max = 15; break;
191
0
  default:
192
0
  case 8: max = 0xff; break;
193
0
  case 16: max = 0xffff; break;
194
0
  case 24: max = 0xffffff; break;
195
0
  case 32: max = 0xffffffff; break;
196
0
  }
197
198
0
  for (k = 0; k < 2 * n; k++)
199
0
  {
200
0
    colorkey[k] = colorkey_in[k];
201
202
0
    if (colorkey[k] > max)
203
0
    {
204
0
      if (indexed && bpc == 1)
205
0
      {
206
0
        if (k == 0)
207
0
        {
208
0
          fz_warn(ctx, "first color key masking value out of range in 1bpc indexed image, ignoring color key masking");
209
0
          return;
210
0
        }
211
0
        fz_warn(ctx, "later color key masking value out of range in 1bpc indexed image, assumed to be 1");
212
0
        colorkey[k] = 1;
213
0
      }
214
0
      else if (bpc != 1)
215
0
      {
216
0
        fz_warn(ctx, "color key masking value out of range, masking to valid range");
217
0
        colorkey[k] &= max;
218
0
      }
219
0
    }
220
221
0
    if (colorkey[k] < 0 || colorkey[k] > max)
222
0
    {
223
0
      fz_warn(ctx, "color key masking value out of range, clamping to valid range");
224
0
      colorkey[k] = fz_clampi(colorkey[k], 0, max);
225
0
    }
226
227
0
    if (scale > 1)
228
0
    {
229
      /* scale up color key masking value so it can be compared with samples. */
230
0
      colorkey[k] *= scale;
231
0
    }
232
0
    else if (shift > 0)
233
0
    {
234
      /* shifting down color key masking value so it can be compared with samples. */
235
0
      colorkey[k] >>= shift;
236
0
    }
237
0
  }
238
239
0
  while (h--)
240
0
  {
241
0
    w = pix->w;
242
0
    do
243
0
    {
244
0
      t = 1;
245
0
      for (k = 0; k < n; k++)
246
0
        if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1])
247
0
          t = 0;
248
0
      if (t)
249
0
        for (k = 0; k < pix->n; k++)
250
0
          p[k] = 0;
251
0
      p += pix->n;
252
0
    }
253
0
    while (--w);
254
0
    p += stride;
255
0
  }
256
0
}
257
258
static void
259
fz_unblend_masked_tile(fz_context *ctx, fz_pixmap *tile, fz_image *image, const fz_irect *isa)
260
0
{
261
0
  fz_pixmap *mask;
262
0
  unsigned char *s, *d = tile->samples;
263
0
  int n = tile->n;
264
0
  int k;
265
0
  size_t sstride, dstride = tile->stride - tile->w * (size_t)tile->n;
266
0
  int h;
267
0
  fz_irect subarea;
268
269
  /* We need at least as much of the mask as there was of the tile. */
270
0
  if (isa)
271
0
    subarea = *isa;
272
0
  else
273
0
  {
274
0
    subarea.x0 = 0;
275
0
    subarea.y0 = 0;
276
0
    subarea.x1 = tile->w;
277
0
    subarea.y1 = tile->h;
278
0
  }
279
280
0
  mask = fz_get_pixmap_from_image(ctx, image->mask, &subarea, NULL, NULL, NULL);
281
0
  s = mask->samples;
282
  /* RJW: Urgh, bit of nastiness here. fz_pixmap_from_image will either return
283
   * an exact match for the subarea we asked for, or the full image, and the
284
   * normal way to know is that the matrix will be updated. That doesn't help
285
   * us here. */
286
0
  if (image->mask->w == mask->w && image->mask->h == mask->h) {
287
0
    subarea.x0 = 0;
288
0
    subarea.y0 = 0;
289
0
  }
290
0
  if (isa)
291
0
    s += (isa->x0 - subarea.x0) * (size_t)mask->n + (isa->y0 - subarea.y0) * (size_t)mask->stride;
292
0
  sstride = mask->stride - tile->w * (size_t)mask->n;
293
0
  h = tile->h;
294
295
0
  if (tile->w != 0)
296
0
  {
297
0
    while (h--)
298
0
    {
299
0
      int w = tile->w;
300
0
      do
301
0
      {
302
0
        if (*s == 0)
303
0
          for (k = 0; k < image->n; k++)
304
0
            d[k] = image->colorkey[k];
305
0
        else
306
0
          for (k = 0; k < image->n; k++)
307
0
            d[k] = fz_clampi(image->colorkey[k] + (d[k] - image->colorkey[k]) * 255 / *s, 0, 255);
308
0
        s++;
309
0
        d += n;
310
0
      }
311
0
      while (--w);
312
0
      s += sstride;
313
0
      d += dstride;
314
0
    }
315
0
  }
316
317
0
  fz_drop_pixmap(ctx, mask);
318
0
}
319
320
static void fz_adjust_image_subarea(fz_context *ctx, fz_image *image, fz_irect *subarea, int l2factor)
321
16
{
322
16
  int f = 1<<l2factor;
323
16
  int bpp = image->bpc * image->n;
324
16
  int mask;
325
326
16
  switch (bpp)
327
16
  {
328
0
  case 1: mask = 8*f; break;
329
0
  case 2: mask = 4*f; break;
330
0
  case 4: mask = 2*f; break;
331
16
  default: mask = (bpp & 7) == 0 ? f : 0; break;
332
16
  }
333
334
16
  if (mask != 0)
335
16
  {
336
16
    subarea->x0 &= ~(mask - 1);
337
16
    subarea->x1 = (subarea->x1 + mask - 1) & ~(mask - 1);
338
16
  }
339
0
  else
340
0
  {
341
    /* Awkward case - mask cannot be a power of 2. */
342
0
    mask = bpp*f;
343
0
    switch (bpp)
344
0
    {
345
0
    case 3:
346
0
    case 5:
347
0
    case 7:
348
0
    case 9:
349
0
    case 11:
350
0
    case 13:
351
0
    case 15:
352
0
    default:
353
0
      mask *= 8;
354
0
      break;
355
0
    case 6:
356
0
    case 10:
357
0
    case 14:
358
0
      mask *= 4;
359
0
      break;
360
0
    case 12:
361
0
      mask *= 2;
362
0
      break;
363
0
    }
364
0
    subarea->x0 = (subarea->x0 / mask) * mask;
365
0
    subarea->x1 = ((subarea->x1 + mask - 1) / mask) * mask;
366
0
  }
367
368
16
  subarea->y0 &= ~(f - 1);
369
16
  if (subarea->x1 > image->w)
370
0
    subarea->x1 = image->w;
371
16
  subarea->y1 = (subarea->y1 + f - 1) & ~(f - 1);
372
16
  if (subarea->y1 > image->h)
373
0
    subarea->y1 = image->h;
374
16
}
375
376
static void fz_compute_image_key(fz_context *ctx, fz_image *image, fz_matrix *ctm,
377
  fz_image_key *key, const fz_irect *subarea, int l2factor, int *w, int *h, int *dw, int *dh)
378
24
{
379
24
  key->refs = 1;
380
24
  key->image = image;
381
24
  key->l2factor = l2factor;
382
383
24
  if (subarea == NULL)
384
8
  {
385
8
    key->rect.x0 = 0;
386
8
    key->rect.y0 = 0;
387
8
    key->rect.x1 = image->w;
388
8
    key->rect.y1 = image->h;
389
8
  }
390
16
  else
391
16
  {
392
16
    key->rect = *subarea;
393
16
    ctx->tuning->image_decode(ctx->tuning->image_decode_arg, image->w, image->h, key->l2factor, &key->rect);
394
16
    fz_adjust_image_subarea(ctx, image, &key->rect, key->l2factor);
395
16
  }
396
397
  /* Based on that subarea, recalculate the extents */
398
24
  if (ctm)
399
24
  {
400
24
    float frac_w = (float) (key->rect.x1 - key->rect.x0) / image->w;
401
24
    float frac_h = (float) (key->rect.y1 - key->rect.y0) / image->h;
402
24
    float a = ctm->a * frac_w;
403
24
    float b = ctm->b * frac_w;
404
24
    float c = ctm->c * frac_h;
405
24
    float d = ctm->d * frac_h;
406
24
    *w = sqrtf(a * a + b * b);
407
24
    *h = sqrtf(c * c + d * d);
408
24
  }
409
0
  else
410
0
  {
411
0
    *w = image->w;
412
0
    *h = image->h;
413
0
  }
414
415
  /* Return the true sizes to the caller */
416
24
  if (dw)
417
24
    *dw = *w;
418
24
  if (dh)
419
24
    *dh = *h;
420
24
  if (*w > image->w)
421
0
    *w = image->w;
422
24
  if (*h > image->h)
423
0
    *h = image->h;
424
425
24
  if (*w == 0 || *h == 0)
426
0
    key->l2factor = 0;
427
24
}
428
429
typedef struct {
430
  fz_stream *src;
431
  size_t l_skip; /* Number of bytes to skip on the left. */
432
  size_t r_skip; /* Number of bytes to skip on the right. */
433
  size_t b_skip; /* Number of bytes to skip on the bottom. */
434
  int lines; /* Number of lines left to copy. */
435
  size_t stride; /* Number of bytes to read in the image. */
436
  size_t nskip; /* Number of bytes left to skip on this line. */
437
  size_t nread; /* Number of bytes left to read on this line. */
438
} subarea_state;
439
440
static int
441
subarea_next(fz_context *ctx, fz_stream *stm, size_t len)
442
0
{
443
0
  subarea_state *state = stm->state;
444
0
  size_t n;
445
446
0
  stm->wp = stm->rp = NULL;
447
448
0
  while (state->nskip > 0)
449
0
  {
450
0
    n = fz_skip(ctx, state->src, state->nskip);
451
0
    if (n == 0)
452
0
      return EOF;
453
0
    state->nskip -= n;
454
0
  }
455
0
  if (state->lines == 0)
456
0
    return EOF;
457
0
  n = fz_available(ctx, state->src, state->nread);
458
0
  if (n > state->nread)
459
0
    n = state->nread;
460
0
  if (n == 0)
461
0
    return EOF;
462
0
  stm->rp = state->src->rp;
463
0
  stm->wp = stm->rp + n;
464
0
  stm->pos += n;
465
0
  state->src->rp = stm->wp;
466
0
  state->nread -= n;
467
0
  if (state->nread == 0)
468
0
  {
469
0
    state->lines--;
470
0
    if (state->lines == 0)
471
0
      state->nskip = state->r_skip + state->b_skip;
472
0
    else
473
0
      state->nskip = state->l_skip + state->r_skip;
474
0
    state->nread = state->stride;
475
0
  }
476
0
  return *stm->rp++;
477
0
}
478
479
static void
480
subarea_drop(fz_context *ctx, void *state)
481
0
{
482
0
  fz_free(ctx, state);
483
0
}
484
485
static fz_stream *
486
subarea_stream(fz_context *ctx, fz_stream *stm, fz_image *image, const fz_irect *subarea, int l2factor)
487
0
{
488
0
  subarea_state *state;
489
0
  int f = 1<<l2factor;
490
0
  int stream_w = (image->w + f - 1)>>l2factor;
491
0
  size_t stream_stride = (stream_w * (size_t)image->n * image->bpc + 7) / 8;
492
0
  int l_margin = subarea->x0 >> l2factor;
493
0
  int t_margin = subarea->y0 >> l2factor;
494
0
  int r_margin = (image->w + f - 1 - subarea->x1) >> l2factor;
495
0
  int b_margin = (image->h + f - 1 - subarea->y1) >> l2factor;
496
0
  size_t l_skip = (l_margin * (size_t)image->n * image->bpc)/8;
497
0
  size_t r_skip = (r_margin * (size_t)image->n * image->bpc + 7)/8;
498
0
  size_t t_skip = t_margin * stream_stride;
499
0
  size_t b_skip = b_margin * stream_stride;
500
0
  int h = (subarea->y1 - subarea->y0 + f - 1) >> l2factor;
501
0
  int w = (subarea->x1 - subarea->x0 + f - 1) >> l2factor;
502
0
  size_t stride = (w * (size_t)image->n * image->bpc + 7) / 8;
503
504
0
  state = fz_malloc_struct(ctx, subarea_state);
505
0
  state->src = stm;
506
0
  state->l_skip = l_skip;
507
0
  state->r_skip = r_skip;
508
0
  state->b_skip = b_skip;
509
0
  state->lines = h;
510
0
  state->nskip = l_skip+t_skip;
511
0
  state->stride = stride;
512
0
  state->nread = stride;
513
514
0
  return fz_new_stream(ctx, state, subarea_next, subarea_drop);
515
0
}
516
517
typedef struct
518
{
519
  fz_stream *src;
520
  int w; /* Width in source pixels. */
521
  int h; /* Height (remaining) in scanlines. */
522
  int n; /* Number of components. */
523
  int f; /* Fill level (how many scanlines we've copied in). */
524
  size_t r; /* How many samples Remain to be filled in this line. */
525
  int l2; /* The amount of subsampling we're doing. */
526
  unsigned char data[1];
527
} l2sub_state;
528
529
static void
530
subsample_drop(fz_context *ctx, void *state)
531
0
{
532
0
  fz_free(ctx, state);
533
0
}
534
535
static int
536
subsample_next(fz_context *ctx, fz_stream *stm, size_t len)
537
0
{
538
0
  l2sub_state *state = (l2sub_state *)stm->state;
539
0
  size_t fill;
540
541
0
  stm->rp = stm->wp = &state->data[0];
542
0
  if (state->h == 0)
543
0
    return EOF;
544
545
  /* Copy in data */
546
0
  do
547
0
  {
548
0
    if (state->r == 0)
549
0
      state->r = state->w * (size_t)state->n;
550
551
0
    while (state->r > 0)
552
0
    {
553
0
      size_t a;
554
0
      a = fz_available(ctx, state->src, state->r);
555
0
      if (a == 0)
556
0
        return EOF;
557
0
      if (a > state->r)
558
0
        a = state->r;
559
0
      memcpy(&state->data[state->w * (size_t)state->n * (state->f+1) - state->r],
560
0
        state->src->rp, a);
561
0
      state->src->rp += a;
562
0
      state->r -= a;
563
0
    }
564
0
    state->f++;
565
0
    state->h--;
566
0
  }
567
0
  while (state->h > 0 && state->f != (1<<state->l2));
568
569
  /* Perform the subsample */
570
0
  fz_subsample_pixblock(state->data, state->w, state->f, state->n, state->l2, state->w * (size_t)state->n);
571
0
  state->f = 0;
572
573
  /* Update data pointers. */
574
0
  fill = ((state->w + (1<<state->l2) - 1)>>state->l2) * (size_t)state->n;
575
0
  stm->pos += fill;
576
0
  stm->rp = &state->data[0];
577
0
  stm->wp = &state->data[fill];
578
579
0
  return *stm->rp++;
580
0
}
581
582
static fz_stream *
583
subsample_stream(fz_context *ctx, fz_stream *src, int w, int h, int n, int l2extra)
584
0
{
585
0
  l2sub_state *state = fz_malloc(ctx, sizeof(l2sub_state) + w*(size_t)(n<<l2extra));
586
587
0
  state->src = src;
588
0
  state->w = w;
589
0
  state->h = h;
590
0
  state->n = n;
591
0
  state->f = 0;
592
0
  state->r = 0;
593
0
  state->l2 = l2extra;
594
595
0
  return fz_new_stream(ctx, state, subsample_next, subsample_drop);
596
0
}
597
598
/* l2factor is the amount of subsampling that the decoder is going to be
599
 * doing for us already. (So for JPEG 0,1,2,3 corresponding to 1, 2, 4,
600
 * 8. For other formats, probably 0.). l2extra is the additional amount
601
 * of subsampling we should perform here. */
602
fz_pixmap *
603
fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_compressed_image *cimg, fz_irect *subarea, int indexed, int l2factor, int *l2extra)
604
2
{
605
2
  fz_image *image = &cimg->super;
606
2
  fz_pixmap *tile = NULL;
607
2
  size_t stride, len, i;
608
2
  unsigned char *samples = NULL;
609
2
  int f = 1<<l2factor;
610
2
  int w = image->w;
611
2
  int h = image->h;
612
2
  int matte = image->use_colorkey && image->mask;
613
2
  fz_stream *read_stream = stm;
614
2
  fz_stream *sstream = NULL;
615
2
  fz_stream *l2stream = NULL;
616
2
  fz_stream *unpstream = NULL;
617
618
2
  if (matte)
619
0
  {
620
    /* Can't do l2factor decoding */
621
0
    if (image->w != image->mask->w || image->h != image->mask->h)
622
0
    {
623
0
      fz_warn(ctx, "mask must be of same size as image for /Matte");
624
0
      matte = 0;
625
0
    }
626
0
    assert(l2factor == 0);
627
0
  }
628
2
  if (subarea)
629
2
  {
630
2
    if (subarea->x0 == 0 && subarea->x1 == image->w &&
631
2
      subarea->y0 == 0 && subarea->y1 == image->h)
632
2
      subarea = NULL;
633
0
    else
634
0
    {
635
0
      fz_adjust_image_subarea(ctx, image, subarea, l2factor);
636
0
      w = (subarea->x1 - subarea->x0);
637
0
      h = (subarea->y1 - subarea->y0);
638
0
    }
639
2
  }
640
2
  w = (w + f - 1) >> l2factor;
641
2
  h = (h + f - 1) >> l2factor;
642
643
2
  fz_var(tile);
644
2
  fz_var(samples);
645
2
  fz_var(sstream);
646
2
  fz_var(unpstream);
647
2
  fz_var(l2stream);
648
649
4
  fz_try(ctx)
650
4
  {
651
2
    int alpha = (image->colorspace == NULL);
652
2
    if (image->use_colorkey)
653
0
      alpha = 1;
654
655
2
    if (subarea)
656
0
      read_stream = sstream = subarea_stream(ctx, stm, image, subarea, l2factor);
657
2
    if (image->bpc != 8 || image->use_colorkey)
658
0
      read_stream = unpstream = fz_unpack_stream(ctx, read_stream, image->bpc, w, h, image->n, indexed, image->use_colorkey, 0);
659
2
    if (l2extra && *l2extra && !indexed)
660
0
    {
661
0
      read_stream = l2stream = subsample_stream(ctx, read_stream, w, h, image->n + image->use_colorkey, *l2extra);
662
0
      w = (w + (1<<*l2extra) - 1)>>*l2extra;
663
0
      h = (h + (1<<*l2extra) - 1)>>*l2extra;
664
0
      *l2extra = 0;
665
0
    }
666
667
2
    tile = fz_new_pixmap(ctx, image->colorspace, w, h, NULL, alpha);
668
2
    if (image->interpolate & FZ_PIXMAP_FLAG_INTERPOLATE)
669
0
      tile->flags |= FZ_PIXMAP_FLAG_INTERPOLATE;
670
2
    else
671
2
      tile->flags &= ~FZ_PIXMAP_FLAG_INTERPOLATE;
672
673
2
    samples = tile->samples;
674
2
    stride = tile->stride;
675
676
2
    len = fz_read(ctx, read_stream, samples, h * stride);
677
678
    /* Pad truncated images */
679
2
    if (len < stride * h)
680
0
    {
681
0
      fz_warn(ctx, "padding truncated image");
682
0
      memset(samples + len, 0, stride * h - len);
683
0
    }
684
685
    /* Invert 1-bit image masks */
686
2
    if (image->imagemask)
687
0
    {
688
      /* 0=opaque and 1=transparent so we need to invert */
689
0
      unsigned char *p = samples;
690
0
      len = h * stride;
691
0
      for (i = 0; i < len; i++)
692
0
        p[i] = ~p[i];
693
0
    }
694
695
    /* color keyed transparency */
696
2
    if (image->use_colorkey && !image->mask)
697
0
      fz_mask_color_key(ctx, tile, image->n, image->bpc, image->colorkey, indexed);
698
699
2
    if (indexed)
700
0
    {
701
0
      fz_pixmap *conv;
702
0
      fz_decode_indexed_tile(ctx, tile, image->decode, (1 << image->bpc) - 1);
703
0
      conv = fz_convert_indexed_pixmap_to_base(ctx, tile);
704
0
      fz_drop_pixmap(ctx, tile);
705
0
      tile = conv;
706
0
    }
707
2
    else if (image->use_decode)
708
0
    {
709
0
      fz_decode_tile(ctx, tile, image->decode);
710
0
    }
711
712
    /* pre-blended matte color */
713
2
    if (matte)
714
0
      fz_unblend_masked_tile(ctx, tile, image, subarea);
715
2
  }
716
4
  fz_always(ctx)
717
2
  {
718
2
    fz_drop_stream(ctx, sstream);
719
2
    fz_drop_stream(ctx, unpstream);
720
2
    fz_drop_stream(ctx, l2stream);
721
2
  }
722
2
  fz_catch(ctx)
723
0
  {
724
0
    fz_drop_pixmap(ctx, tile);
725
0
    fz_rethrow(ctx);
726
0
  }
727
728
2
  return tile;
729
2
}
730
731
void
732
fz_drop_image_base(fz_context *ctx, fz_image *image)
733
8
{
734
8
  fz_drop_colorspace(ctx, image->colorspace);
735
8
  fz_drop_image(ctx, image->mask);
736
8
  fz_free(ctx, image);
737
8
}
738
739
void
740
fz_drop_image_imp(fz_context *ctx, fz_storable *image_)
741
8
{
742
8
  fz_image *image = (fz_image *)image_;
743
744
8
  image->drop_image(ctx, image);
745
8
  fz_drop_image_base(ctx, image);
746
8
}
747
748
static void
749
drop_compressed_image(fz_context *ctx, fz_image *image_)
750
8
{
751
8
  fz_compressed_image *image = (fz_compressed_image *)image_;
752
753
8
  fz_drop_compressed_buffer(ctx, image->buffer);
754
8
}
755
756
static void
757
drop_pixmap_image(fz_context *ctx, fz_image *image_)
758
0
{
759
0
  fz_pixmap_image *image = (fz_pixmap_image *)image_;
760
761
0
  fz_drop_pixmap(ctx, image->tile);
762
0
}
763
764
int
765
fz_is_lossy_image(fz_context *ctx, fz_image *image)
766
0
{
767
0
  fz_compressed_buffer *cbuf = fz_compressed_image_buffer(ctx, image);
768
0
  if (cbuf)
769
0
  {
770
0
    switch (cbuf->params.type)
771
0
    {
772
0
    case FZ_IMAGE_JPEG:
773
0
    case FZ_IMAGE_JPX:
774
0
    case FZ_IMAGE_JXR:
775
0
      return 1;
776
0
    }
777
0
  }
778
0
  return 0;
779
0
}
780
781
static fz_pixmap *
782
compressed_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
783
8
{
784
8
  fz_compressed_image *image = (fz_compressed_image *)image_;
785
8
  int native_l2factor;
786
8
  fz_stream *stm;
787
8
  int indexed;
788
8
  fz_pixmap *tile;
789
8
  int can_sub = 0;
790
8
  int local_l2factor;
791
792
  /* If we are using matte, then the decode code requires both image and tile sizes
793
   * to match. The simplest way to ensure this is to do no native l2factor decoding.
794
   */
795
8
  if (image->super.use_colorkey && image->super.mask)
796
0
  {
797
0
    local_l2factor = 0;
798
0
    l2factor = &local_l2factor;
799
0
  }
800
801
  /* We need to make a new one. */
802
  /* First check for ones that we can't decode using streams */
803
8
  switch (image->buffer->params.type)
804
8
  {
805
0
  case FZ_IMAGE_PNG:
806
0
    tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
807
0
    break;
808
1
  case FZ_IMAGE_GIF:
809
1
    tile = fz_load_gif(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
810
1
    break;
811
0
  case FZ_IMAGE_BMP:
812
0
    tile = fz_load_bmp(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
813
0
    break;
814
0
  case FZ_IMAGE_TIFF:
815
0
    tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
816
0
    break;
817
0
  case FZ_IMAGE_PNM:
818
0
    tile = fz_load_pnm(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
819
0
    break;
820
0
  case FZ_IMAGE_JXR:
821
0
    tile = fz_load_jxr(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
822
0
    break;
823
5
  case FZ_IMAGE_JPX:
824
5
    tile = fz_load_jpx(ctx, image->buffer->buffer->data, image->buffer->buffer->len, image->super.colorspace);
825
5
    break;
826
0
  case FZ_IMAGE_PSD:
827
0
    tile = fz_load_psd(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
828
0
    break;
829
2
  case FZ_IMAGE_JPEG:
830
    /* Scan JPEG stream and patch missing height values in header */
831
2
    {
832
2
      unsigned char *s = image->buffer->buffer->data;
833
2
      unsigned char *e = s + image->buffer->buffer->len;
834
2
      unsigned char *d;
835
13
      for (d = s + 2; s < d && d + 9 < e && d[0] == 0xFF; d += (d[2] << 8 | d[3]) + 2)
836
11
      {
837
11
        if (d[1] < 0xC0 || (0xC3 < d[1] && d[1] < 0xC9) || 0xCB < d[1])
838
10
          continue;
839
1
        if ((d[5] == 0 && d[6] == 0) || ((d[5] << 8) | d[6]) > image->super.h)
840
0
        {
841
0
          d[5] = (image->super.h >> 8) & 0xFF;
842
0
          d[6] = image->super.h & 0xFF;
843
0
        }
844
1
      }
845
2
    }
846
    /* fall through */
847
848
2
  default:
849
2
    native_l2factor = l2factor ? *l2factor : 0;
850
2
    stm = fz_open_image_decomp_stream_from_buffer(ctx, image->buffer, l2factor);
851
4
    fz_try(ctx)
852
4
    {
853
2
      if (l2factor)
854
2
        native_l2factor -= *l2factor;
855
2
      indexed = fz_colorspace_is_indexed(ctx, image->super.colorspace);
856
2
      can_sub = 1;
857
2
      tile = fz_decomp_image_from_stream(ctx, stm, image, subarea, indexed, native_l2factor, l2factor);
858
2
    }
859
4
    fz_always(ctx)
860
2
      fz_drop_stream(ctx, stm);
861
2
    fz_catch(ctx)
862
0
      fz_rethrow(ctx);
863
864
2
    break;
865
8
  }
866
867
2
  if (can_sub == 0 && subarea != NULL)
868
0
  {
869
0
    subarea->x0 = 0;
870
0
    subarea->y0 = 0;
871
0
    subarea->x1 = image->super.w;
872
0
    subarea->y1 = image->super.h;
873
0
  }
874
875
2
  return tile;
876
8
}
877
878
static fz_pixmap *
879
pixmap_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
880
0
{
881
0
  fz_pixmap_image *image = (fz_pixmap_image *)image_;
882
883
  /* 'Simple' images created direct from pixmaps will have no buffer
884
   * of compressed data. We cannot do any better than just returning
885
   * a pointer to the original 'tile'.
886
   */
887
0
  return fz_keep_pixmap(ctx, image->tile); /* That's all we can give you! */
888
0
}
889
890
static void
891
update_ctm_for_subarea(fz_matrix *ctm, const fz_irect *subarea, int w, int h)
892
2
{
893
2
  fz_matrix m;
894
895
2
  if (ctm == NULL || (subarea->x0 == 0 && subarea->y0 == 0 && subarea->x1 == w && subarea->y1 == h))
896
2
    return;
897
898
0
  m.a = (float) (subarea->x1 - subarea->x0) / w;
899
0
  m.b = 0;
900
0
  m.c = 0;
901
0
  m.d = (float) (subarea->y1 - subarea->y0) / h;
902
0
  m.e = (float) subarea->x0 / w;
903
0
  m.f = (float) subarea->y0 / h;
904
0
  *ctm = fz_concat(m, *ctm);
905
0
}
906
907
void fz_default_image_decode(void *arg, int w, int h, int l2factor, fz_irect *subarea)
908
16
{
909
16
  (void)arg;
910
911
16
  if ((subarea->x1-subarea->x0)*(subarea->y1-subarea->y0) >= (w*h/10)*9)
912
16
  {
913
    /* Either no subarea specified, or a subarea 90% or more of the
914
     * whole area specified. Use the whole image. */
915
16
    subarea->x0 = 0;
916
16
    subarea->y0 = 0;
917
16
    subarea->x1 = w;
918
16
    subarea->y1 = h;
919
16
  }
920
0
  else
921
0
  {
922
    /* Clip to the edges if they are within 1% */
923
0
    if (subarea->x0 <= w/100)
924
0
      subarea->x0 = 0;
925
0
    if (subarea->y0 <= h/100)
926
0
      subarea->y0 = 0;
927
0
    if (subarea->x1 >= w*99/100)
928
0
      subarea->x1 = w;
929
0
    if (subarea->y1 >= h*99/100)
930
0
      subarea->y1 = h;
931
0
  }
932
16
}
933
934
static fz_pixmap *
935
fz_find_image_tile(fz_context *ctx, fz_image *image, fz_image_key *key, fz_matrix *ctm)
936
16
{
937
16
  fz_pixmap *tile;
938
16
  do
939
16
  {
940
16
    tile = fz_find_item(ctx, fz_drop_pixmap_imp, key, &fz_image_store_type);
941
16
    if (tile)
942
0
    {
943
0
      update_ctm_for_subarea(ctm, &key->rect, image->w, image->h);
944
0
      return tile;
945
0
    }
946
16
    key->l2factor--;
947
16
  }
948
16
  while (key->l2factor >= 0);
949
16
  return NULL;
950
16
}
951
952
fz_pixmap *
953
fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, const fz_irect *subarea, fz_matrix *ctm, int *dw, int *dh)
954
8
{
955
8
  fz_pixmap *tile;
956
8
  int l2factor, l2factor_remaining;
957
8
  fz_image_key key;
958
8
  fz_image_key *keyp = NULL;
959
8
  int w;
960
8
  int h;
961
962
8
  fz_var(keyp);
963
964
8
  if (!image)
965
0
    return NULL;
966
967
  /* Figure out the extent. */
968
8
  if (ctm)
969
8
  {
970
8
    w = sqrtf(ctm->a * ctm->a + ctm->b * ctm->b);
971
8
    h = sqrtf(ctm->c * ctm->c + ctm->d * ctm->d);
972
8
  }
973
0
  else
974
0
  {
975
0
    w = image->w;
976
0
    h = image->h;
977
0
  }
978
979
8
  if (image->scalable)
980
0
  {
981
    /* If the image is scalable, we always want to re-render and never cache. */
982
0
    fz_irect subarea_copy;
983
0
    if (subarea)
984
0
      subarea_copy = *subarea;
985
0
    l2factor_remaining = 0;
986
0
    if (dw) *dw = w;
987
0
    if (dh) *dh = h;
988
0
    return image->get_pixmap(ctx, image, subarea ? &subarea_copy : NULL, image->w, image->h, &l2factor_remaining);
989
0
  }
990
991
  /* Clamp requested image size, since we never want to magnify images here. */
992
8
  if (w > image->w)
993
0
    w = image->w;
994
8
  if (h > image->h)
995
0
    h = image->h;
996
997
8
  if (image->decoded)
998
0
  {
999
    /* If the image is already decoded, then we can't offer a subarea,
1000
     * or l2factor, and we don't want to cache. */
1001
0
    l2factor_remaining = 0;
1002
0
    if (dw) *dw = w;
1003
0
    if (dh) *dh = h;
1004
0
    return image->get_pixmap(ctx, image, NULL, image->w, image->h, &l2factor_remaining);
1005
0
  }
1006
1007
  /* What is our ideal factor? We search for the largest factor where
1008
   * we can subdivide and stay larger than the required size. We add
1009
   * a fudge factor of +2 here to allow for the possibility of
1010
   * expansion due to grid fitting. */
1011
8
  l2factor = 0;
1012
8
  if (w > 0 && h > 0)
1013
8
  {
1014
8
    while (image->w>>(l2factor+1) >= w+2 && image->h>>(l2factor+1) >= h+2 && l2factor < 6)
1015
0
      l2factor++;
1016
8
  }
1017
1018
  /* First, look through the store for existing tiles */
1019
8
  if (subarea)
1020
8
  {
1021
8
    fz_compute_image_key(ctx, image, ctm, &key, subarea, l2factor, &w, &h, dw, dh);
1022
8
    tile = fz_find_image_tile(ctx, image, &key, ctm);
1023
8
    if (tile)
1024
0
      return tile;
1025
8
  }
1026
1027
  /* No subarea given, or no tile for subarea found; try entire image */
1028
8
  fz_compute_image_key(ctx, image, ctm, &key, NULL, l2factor, &w, &h, dw, dh);
1029
8
  tile = fz_find_image_tile(ctx, image, &key, ctm);
1030
8
  if (tile)
1031
0
    return tile;
1032
1033
  /* Neither subarea nor full image tile found; prepare the subarea key again */
1034
8
  if (subarea)
1035
8
    fz_compute_image_key(ctx, image, ctm, &key, subarea, l2factor, &w, &h, dw, dh);
1036
1037
  /* We'll have to decode the image; request the correct amount of downscaling. */
1038
8
  l2factor_remaining = l2factor;
1039
8
  tile = image->get_pixmap(ctx, image, &key.rect, w, h, &l2factor_remaining);
1040
1041
  /* Update the ctm to allow for subareas. */
1042
8
  update_ctm_for_subarea(ctm, &key.rect, image->w, image->h);
1043
1044
  /* l2factor_remaining is updated to the amount of subscaling left to do */
1045
8
  assert(l2factor_remaining >= 0 && l2factor_remaining <= 6);
1046
8
  if (l2factor_remaining)
1047
0
  {
1048
0
    fz_try(ctx)
1049
0
      fz_subsample_pixmap(ctx, tile, l2factor_remaining);
1050
0
    fz_catch(ctx)
1051
0
    {
1052
0
      fz_drop_pixmap(ctx, tile);
1053
0
      fz_rethrow(ctx);
1054
0
    }
1055
0
  }
1056
1057
4
  fz_try(ctx)
1058
4
  {
1059
2
    fz_pixmap *existing_tile;
1060
1061
    /* Now we try to cache the pixmap. Any failure here will just result
1062
     * in us not caching. */
1063
2
    keyp = fz_malloc_struct(ctx, fz_image_key);
1064
2
    keyp->refs = 1;
1065
2
    keyp->image = fz_keep_image_store_key(ctx, image);
1066
2
    keyp->l2factor = l2factor;
1067
2
    keyp->rect = key.rect;
1068
1069
2
    existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type);
1070
2
    if (existing_tile)
1071
0
    {
1072
      /* We already have a tile. This must have been produced by a
1073
       * racing thread. We'll throw away ours and use that one. */
1074
0
      fz_drop_pixmap(ctx, tile);
1075
0
      tile = existing_tile;
1076
0
    }
1077
2
  }
1078
4
  fz_always(ctx)
1079
2
  {
1080
2
    fz_drop_image_key(ctx, keyp);
1081
2
  }
1082
2
  fz_catch(ctx)
1083
0
  {
1084
    /* Do nothing */
1085
0
    fz_rethrow_if(ctx, FZ_ERROR_SYSTEM);
1086
0
    fz_report_error(ctx);
1087
0
  }
1088
1089
2
  return tile;
1090
2
}
1091
1092
fz_pixmap *
1093
fz_get_pixmap_mask_from_image(fz_context *ctx, fz_image *image, const fz_irect *subarea, fz_matrix *ctm, int *dw, int *dh, int in_smask)
1094
0
{
1095
0
  fz_pixmap *pix1, *pix2;
1096
1097
0
  pix1 = fz_get_pixmap_from_image(ctx, image, subarea, ctm, dw, dh);
1098
0
  if (pix1->n == 1 && pix1->alpha)
1099
0
    return pix1;
1100
1101
0
  if (pix1->n == 1)
1102
0
  {
1103
0
    fz_warn(ctx, "convert gray to alpha for image mask");
1104
0
    fz_try(ctx)
1105
0
      pix2 = fz_alpha_from_gray(ctx, pix1);
1106
0
    fz_always(ctx)
1107
0
      fz_drop_pixmap(ctx, pix1);
1108
0
    fz_catch(ctx)
1109
0
      fz_rethrow(ctx);
1110
0
    return pix2;
1111
0
  }
1112
0
  else if (pix1->n == 3)
1113
0
  {
1114
0
    fz_warn(ctx, "convert rgb to alpha for image mask");
1115
0
    fz_try(ctx)
1116
0
      pix2 = fz_alpha_from_rgb(ctx, pix1);
1117
0
    fz_always(ctx)
1118
0
      fz_drop_pixmap(ctx, pix1);
1119
0
    fz_catch(ctx)
1120
0
      fz_rethrow(ctx);
1121
0
    return pix2;
1122
0
  }
1123
0
  else
1124
0
  {
1125
0
    fz_color_params cp = fz_default_color_params;
1126
1127
0
    if (in_smask)
1128
0
      cp.ri |= FZ_RI_IN_SOFTMASK;
1129
1130
0
    fz_warn(ctx, "strange colorspace for image mask (%s)", pix1->colorspace->name);
1131
0
    fz_try(ctx)
1132
0
      pix2 = fz_convert_pixmap(ctx, pix1, fz_device_gray(ctx), NULL, NULL, cp, 0);
1133
0
    fz_always(ctx)
1134
0
      fz_drop_pixmap(ctx, pix1);
1135
0
    fz_catch(ctx)
1136
0
      fz_rethrow(ctx);
1137
0
    fz_drop_colorspace(ctx, pix2->colorspace);
1138
0
    pix2->colorspace = NULL;
1139
0
    pix2->alpha = 1;
1140
0
    return pix2;
1141
0
  }
1142
0
}
1143
1144
fz_pixmap *
1145
fz_get_unscaled_pixmap_from_image(fz_context *ctx, fz_image *image)
1146
0
{
1147
0
  return fz_get_pixmap_from_image(ctx, image, NULL /*subarea*/, NULL /*ctm*/, NULL /*dw*/, NULL /*dh*/);
1148
0
}
1149
1150
static size_t
1151
pixmap_image_get_size(fz_context *ctx, fz_image *image)
1152
0
{
1153
0
  fz_pixmap_image *im = (fz_pixmap_image *)image;
1154
1155
0
  if (image == NULL)
1156
0
    return 0;
1157
1158
0
  return sizeof(fz_pixmap_image) + fz_pixmap_size(ctx, im->tile);
1159
0
}
1160
1161
size_t fz_image_size(fz_context *ctx, fz_image *im)
1162
0
{
1163
0
  if (im == NULL)
1164
0
    return 0;
1165
1166
0
  return im->get_size(ctx, im);
1167
0
}
1168
1169
fz_image *
1170
fz_new_image_from_pixmap(fz_context *ctx, fz_pixmap *pixmap, fz_image *mask)
1171
0
{
1172
0
  fz_pixmap_image *image;
1173
1174
0
  image = fz_new_derived_image(ctx, pixmap->w, pixmap->h, 8, pixmap->colorspace,
1175
0
        pixmap->xres, pixmap->yres, 0, 0,
1176
0
        NULL, NULL, mask, fz_pixmap_image,
1177
0
        pixmap_image_get_pixmap,
1178
0
        pixmap_image_get_size,
1179
0
        drop_pixmap_image);
1180
0
  image->tile = fz_keep_pixmap(ctx, pixmap);
1181
0
  image->super.decoded = 1;
1182
1183
0
  return &image->super;
1184
0
}
1185
1186
fz_image *
1187
fz_new_image_of_size(fz_context *ctx, int w, int h, int bpc, fz_colorspace *colorspace,
1188
    int xres, int yres, int interpolate, int imagemask, const float *decode,
1189
    const int *colorkey, fz_image *mask, size_t size,
1190
    fz_image_get_pixmap_fn *get_pixmap,
1191
    fz_image_get_size_fn *get_size,
1192
    fz_drop_image_fn *drop)
1193
8
{
1194
8
  fz_image *image;
1195
8
  int i;
1196
1197
8
  assert(mask == NULL || mask->mask == NULL);
1198
8
  assert(size >= sizeof(fz_image));
1199
1200
8
  image = Memento_label(fz_calloc(ctx, 1, size), "fz_image");
1201
8
  FZ_INIT_KEY_STORABLE(image, 1, fz_drop_image_imp);
1202
8
  image->drop_image = drop;
1203
8
  image->get_pixmap = get_pixmap;
1204
8
  image->get_size = get_size;
1205
8
  image->w = w;
1206
8
  image->h = h;
1207
8
  image->xres = xres;
1208
8
  image->yres = yres;
1209
8
  image->bpc = bpc;
1210
8
  image->n = (colorspace ? fz_colorspace_n(ctx, colorspace) : 1);
1211
8
  image->colorspace = fz_keep_colorspace(ctx, colorspace);
1212
8
  image->interpolate = interpolate;
1213
8
  image->imagemask = imagemask;
1214
8
  image->intent = 0;
1215
8
  image->has_intent = 0;
1216
8
  image->use_colorkey = (colorkey != NULL);
1217
8
  if (colorkey)
1218
0
    memcpy(image->colorkey, colorkey, sizeof(int)*image->n*2);
1219
8
  image->use_decode = 0;
1220
8
  if (decode)
1221
0
  {
1222
0
    memcpy(image->decode, decode, sizeof(float)*image->n*2);
1223
0
  }
1224
8
  else
1225
8
  {
1226
8
    float maxval = fz_colorspace_is_indexed(ctx, colorspace) ? (1 << bpc) - 1 : 1;
1227
32
    for (i = 0; i < image->n; i++)
1228
24
    {
1229
24
      image->decode[2*i] = 0;
1230
24
      image->decode[2*i+1] = maxval;
1231
24
    }
1232
8
  }
1233
  /* ICC spaces have the default decode arrays pickled into them.
1234
   * For most spaces this is fine, because [ 0 1 0 1 0 1 ] is
1235
   * idempotent. For Lab, however, we need to adjust it. */
1236
8
  if (fz_colorspace_is_lab_icc(ctx, colorspace))
1237
0
  {
1238
    /* Undo the default decode array of [0 100 -128 127 -128 127] */
1239
0
    image->decode[0] = image->decode[0]/100.0f;
1240
0
    image->decode[1] = image->decode[1]/100.0f;
1241
0
    image->decode[2] = (image->decode[2]+128)/255.0f;
1242
0
    image->decode[3] = (image->decode[3]+128)/255.0f;
1243
0
    image->decode[4] = (image->decode[4]+128)/255.0f;
1244
0
    image->decode[5] = (image->decode[5]+128)/255.0f;
1245
0
  }
1246
32
  for (i = 0; i < image->n; i++)
1247
24
  {
1248
24
    if (image->decode[i * 2] != 0 || image->decode[i * 2 + 1] != 1)
1249
0
      break;
1250
24
  }
1251
8
  if (i != image->n)
1252
0
    image->use_decode = 1;
1253
8
  image->mask = fz_keep_image(ctx, mask);
1254
1255
8
  return image;
1256
8
}
1257
1258
static size_t
1259
compressed_image_get_size(fz_context *ctx, fz_image *image)
1260
0
{
1261
0
  fz_compressed_image *im = (fz_compressed_image *)image;
1262
1263
0
  if (image == NULL)
1264
0
    return 0;
1265
1266
0
  return sizeof(fz_pixmap_image) + (im->buffer && im->buffer->buffer ? im->buffer->buffer->cap : 0);
1267
0
}
1268
1269
fz_image *
1270
fz_new_image_from_compressed_buffer(fz_context *ctx, int w, int h,
1271
  int bpc, fz_colorspace *colorspace,
1272
  int xres, int yres, int interpolate, int imagemask, const float *decode,
1273
  const int *colorkey, fz_compressed_buffer *buffer, fz_image *mask)
1274
8
{
1275
8
  fz_compressed_image *image;
1276
1277
16
  fz_try(ctx)
1278
16
  {
1279
8
    image = fz_new_derived_image(ctx, w, h, bpc,
1280
8
          colorspace, xres, yres,
1281
8
          interpolate, imagemask, decode,
1282
8
          colorkey, mask, fz_compressed_image,
1283
8
          compressed_image_get_pixmap,
1284
8
          compressed_image_get_size,
1285
8
          drop_compressed_image);
1286
8
    image->buffer = buffer;
1287
8
  }
1288
16
  fz_catch(ctx)
1289
0
  {
1290
0
    fz_drop_compressed_buffer(ctx, buffer);
1291
0
    fz_rethrow(ctx);
1292
0
  }
1293
1294
8
  return &image->super;
1295
8
}
1296
1297
fz_compressed_buffer *fz_compressed_image_buffer(fz_context *ctx, fz_image *image)
1298
0
{
1299
0
  if (image == NULL || image->get_pixmap != compressed_image_get_pixmap)
1300
0
    return NULL;
1301
0
  return ((fz_compressed_image *)image)->buffer;
1302
0
}
1303
1304
void fz_set_compressed_image_buffer(fz_context *ctx, fz_compressed_image *image, fz_compressed_buffer *buf)
1305
0
{
1306
0
  assert(image != NULL && image->super.get_pixmap == compressed_image_get_pixmap);
1307
0
  ((fz_compressed_image *)image)->buffer = buf; /* Note: compressed buffers are not reference counted */
1308
0
}
1309
1310
fz_pixmap *fz_pixmap_image_tile(fz_context *ctx, fz_pixmap_image *image)
1311
0
{
1312
0
  if (image == NULL || image->super.get_pixmap != pixmap_image_get_pixmap)
1313
0
    return NULL;
1314
0
  return ((fz_pixmap_image *)image)->tile;
1315
0
}
1316
1317
void fz_set_pixmap_image_tile(fz_context *ctx, fz_pixmap_image *image, fz_pixmap *pix)
1318
0
{
1319
0
  assert(image != NULL && image->super.get_pixmap == pixmap_image_get_pixmap);
1320
0
  ((fz_pixmap_image *)image)->tile = pix;
1321
0
}
1322
1323
const char *
1324
fz_image_type_name(int type)
1325
0
{
1326
0
  switch (type)
1327
0
  {
1328
0
  default:
1329
0
  case FZ_IMAGE_UNKNOWN: return "unknown";
1330
0
  case FZ_IMAGE_RAW: return "raw";
1331
0
  case FZ_IMAGE_FAX: return "fax";
1332
0
  case FZ_IMAGE_FLATE: return "flate";
1333
0
  case FZ_IMAGE_LZW: return "lzw";
1334
0
  case FZ_IMAGE_RLD: return "rld";
1335
0
  case FZ_IMAGE_BROTLI: return "brotli";
1336
0
  case FZ_IMAGE_BMP: return "bmp";
1337
0
  case FZ_IMAGE_GIF: return "gif";
1338
0
  case FZ_IMAGE_JBIG2: return "jbig2";
1339
0
  case FZ_IMAGE_JPEG: return "jpeg";
1340
0
  case FZ_IMAGE_JPX: return "jpx";
1341
0
  case FZ_IMAGE_JXR: return "jxr";
1342
0
  case FZ_IMAGE_PNG: return "png";
1343
0
  case FZ_IMAGE_PNM: return "pnm";
1344
0
  case FZ_IMAGE_TIFF: return "tiff";
1345
0
  }
1346
0
}
1347
1348
int
1349
fz_lookup_image_type(const char *type)
1350
0
{
1351
0
  if (type == NULL) return FZ_IMAGE_UNKNOWN;
1352
0
  if (!strcmp(type, "raw")) return FZ_IMAGE_RAW;
1353
0
  if (!strcmp(type, "fax")) return FZ_IMAGE_FAX;
1354
0
  if (!strcmp(type, "flate")) return FZ_IMAGE_FLATE;
1355
0
  if (!strcmp(type, "lzw")) return FZ_IMAGE_LZW;
1356
0
  if (!strcmp(type, "rld")) return FZ_IMAGE_RLD;
1357
0
  if (!strcmp(type, "brotli")) return FZ_IMAGE_BROTLI;
1358
0
  if (!strcmp(type, "bmp")) return FZ_IMAGE_BMP;
1359
0
  if (!strcmp(type, "gif")) return FZ_IMAGE_GIF;
1360
0
  if (!strcmp(type, "jbig2")) return FZ_IMAGE_JBIG2;
1361
0
  if (!strcmp(type, "jpeg")) return FZ_IMAGE_JPEG;
1362
0
  if (!strcmp(type, "jpx")) return FZ_IMAGE_JPX;
1363
0
  if (!strcmp(type, "jxr")) return FZ_IMAGE_JXR;
1364
0
  if (!strcmp(type, "png")) return FZ_IMAGE_PNG;
1365
0
  if (!strcmp(type, "pnm")) return FZ_IMAGE_PNM;
1366
0
  if (!strcmp(type, "tiff")) return FZ_IMAGE_TIFF;
1367
0
  return FZ_IMAGE_UNKNOWN;
1368
0
}
1369
1370
int
1371
fz_recognize_image_format(fz_context *ctx, unsigned char p[8])
1372
54
{
1373
54
  if (p[0] == 'P' && p[1] >= '1' && p[1] <= '7')
1374
0
    return FZ_IMAGE_PNM;
1375
54
  if (p[0] == 'P' && (p[1] == 'F' || p[1] == 'f'))
1376
0
    return FZ_IMAGE_PNM;
1377
54
  if (p[0] == 0xff && p[1] == 0x4f)
1378
12
    return FZ_IMAGE_JPX;
1379
42
  if (p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x0c &&
1380
6
      p[4] == 0x6a && p[5] == 0x50 && p[6] == 0x20 && p[7] == 0x20)
1381
6
    return FZ_IMAGE_JPX;
1382
36
  if (p[0] == 0xff && p[1] == 0xd8)
1383
6
    return FZ_IMAGE_JPEG;
1384
30
  if (p[0] == 137 && p[1] == 80 && p[2] == 78 && p[3] == 71 &&
1385
3
      p[4] == 13 && p[5] == 10 && p[6] == 26 && p[7] == 10)
1386
3
    return FZ_IMAGE_PNG;
1387
27
  if (p[0] == 'I' && p[1] == 'I' && p[2] == 0xBC)
1388
0
    return FZ_IMAGE_JXR;
1389
27
  if (p[0] == 'I' && p[1] == 'I' && p[2] == 42 && p[3] == 0)
1390
0
    return FZ_IMAGE_TIFF;
1391
27
  if (p[0] == 'M' && p[1] == 'M' && p[2] == 0 && p[3] == 42)
1392
0
    return FZ_IMAGE_TIFF;
1393
27
  if (p[0] == 'G' && p[1] == 'I' && p[2] == 'F')
1394
3
    return FZ_IMAGE_GIF;
1395
24
  if (p[0] == 'B' && p[1] == 'M')
1396
0
    return FZ_IMAGE_BMP;
1397
24
  if (p[0] == 'B' && p[1] == 'A')
1398
0
    return FZ_IMAGE_BMP;
1399
24
  if (p[0] == 0x97 && p[1] == 'J' && p[2] == 'B' && p[3] == '2' &&
1400
0
    p[4] == '\r' && p[5] == '\n'  && p[6] == 0x1a && p[7] == '\n')
1401
0
    return FZ_IMAGE_JBIG2;
1402
24
  if (p[0] == '8' && p[1] == 'B' && p[2] == 'P' && p[3] == 'S')
1403
6
    return FZ_IMAGE_PSD;
1404
18
  return FZ_IMAGE_UNKNOWN;
1405
24
}
1406
1407
fz_image *
1408
fz_new_image_from_buffer(fz_context *ctx, fz_buffer *buffer)
1409
12
{
1410
12
  fz_compressed_buffer *bc;
1411
12
  int w, h, xres, yres;
1412
12
  fz_colorspace *cspace = NULL;
1413
12
  size_t len = buffer->len;
1414
12
  unsigned char *buf = buffer->data;
1415
12
  fz_image *image = NULL;
1416
12
  int type;
1417
12
  int bpc;
1418
12
  uint8_t orientation = 0;
1419
1420
12
  if (len < 8)
1421
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "unknown image file format");
1422
1423
12
  type = fz_recognize_image_format(ctx, buf);
1424
12
  bpc = 8;
1425
12
  switch (type)
1426
12
  {
1427
0
  case FZ_IMAGE_PNM:
1428
0
    fz_load_pnm_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1429
0
    break;
1430
6
  case FZ_IMAGE_JPX:
1431
6
    fz_load_jpx_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace, NULL);
1432
6
    break;
1433
2
  case FZ_IMAGE_JPEG:
1434
2
    fz_load_jpeg_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace, &orientation);
1435
2
    break;
1436
1
  case FZ_IMAGE_PNG:
1437
1
    fz_load_png_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1438
1
    break;
1439
2
  case FZ_IMAGE_PSD:
1440
2
    fz_load_psd_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1441
2
    break;
1442
0
  case FZ_IMAGE_JXR:
1443
0
    fz_load_jxr_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1444
0
    break;
1445
0
  case FZ_IMAGE_TIFF:
1446
0
    fz_load_tiff_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1447
0
    break;
1448
1
  case FZ_IMAGE_GIF:
1449
1
    fz_load_gif_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1450
1
    break;
1451
0
  case FZ_IMAGE_BMP:
1452
0
    fz_load_bmp_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1453
0
    break;
1454
0
  case FZ_IMAGE_JBIG2:
1455
0
    fz_load_jbig2_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1456
0
    bpc = 1;
1457
0
    break;
1458
0
  default:
1459
0
    fz_throw(ctx, FZ_ERROR_FORMAT, "unknown image file format");
1460
12
  }
1461
1462
16
  fz_try(ctx)
1463
16
  {
1464
8
    bc = fz_new_compressed_buffer(ctx);
1465
8
    bc->buffer = fz_keep_buffer(ctx, buffer);
1466
8
    bc->params.type = type;
1467
8
    if (type == FZ_IMAGE_JPEG)
1468
2
    {
1469
2
      bc->params.u.jpeg.color_transform = -1;
1470
2
      bc->params.u.jpeg.invert_cmyk = 1;
1471
2
    }
1472
8
    image = fz_new_image_from_compressed_buffer(ctx, w, h, bpc, cspace, xres, yres, 0, 0, NULL, NULL, bc, NULL);
1473
8
    image->orientation = orientation;
1474
8
  }
1475
16
  fz_always(ctx)
1476
8
    fz_drop_colorspace(ctx, cspace);
1477
8
  fz_catch(ctx)
1478
0
    fz_rethrow(ctx);
1479
1480
8
  return image;
1481
8
}
1482
1483
fz_image *
1484
fz_new_jpx_image_from_buffer(fz_context *ctx, fz_buffer *buffer, fz_colorspace *defcs)
1485
0
{
1486
0
  fz_compressed_buffer *bc;
1487
0
  fz_colorspace *cs = NULL;
1488
0
  int w, h, xres, yres;
1489
0
  fz_image *img = NULL;
1490
1491
0
  fz_load_jpx_info(ctx, buffer->data, buffer->len, &w, &h, &xres, &yres, &cs, defcs);
1492
1493
0
  fz_try(ctx)
1494
0
  {
1495
0
    bc = fz_new_compressed_buffer(ctx);
1496
0
    bc->buffer = fz_keep_buffer(ctx, buffer);
1497
0
    bc->params.type = FZ_IMAGE_JPX;
1498
1499
0
    img =  fz_new_image_from_compressed_buffer(ctx, w, h, 8, cs, xres, yres, 0, 0, NULL, NULL, bc, NULL);
1500
0
  }
1501
0
  fz_always(ctx)
1502
0
    fz_drop_colorspace(ctx, cs);
1503
0
  fz_catch(ctx)
1504
0
    fz_rethrow(ctx);
1505
1506
0
  return img;
1507
0
}
1508
1509
int
1510
fz_compressed_image_type(fz_context *ctx, fz_image *image)
1511
0
{
1512
0
  fz_compressed_image *cim;
1513
1514
0
  if (image == NULL || image->drop_image != drop_compressed_image)
1515
0
    return FZ_IMAGE_UNKNOWN;
1516
1517
0
  cim = (fz_compressed_image *)image;
1518
1519
0
  return cim->buffer->params.type;
1520
0
}
1521
1522
fz_image *
1523
fz_new_image_from_file(fz_context *ctx, const char *path)
1524
0
{
1525
0
  fz_buffer *buffer;
1526
0
  fz_image *image = NULL;
1527
1528
0
  buffer = fz_read_file(ctx, path);
1529
0
  fz_try(ctx)
1530
0
    image = fz_new_image_from_buffer(ctx, buffer);
1531
0
  fz_always(ctx)
1532
0
    fz_drop_buffer(ctx, buffer);
1533
0
  fz_catch(ctx)
1534
0
    fz_rethrow(ctx);
1535
1536
0
  return image;
1537
0
}
1538
1539
void
1540
fz_image_resolution(fz_image *image, int *xres, int *yres)
1541
16
{
1542
16
  *xres = image->xres;
1543
16
  *yres = image->yres;
1544
16
  if (*xres < 0 || *yres < 0 || (*xres == 0 && *yres == 0))
1545
0
  {
1546
    /* If neither xres or yres is sane, pick a sane value */
1547
0
    *xres = SANE_DPI; *yres = SANE_DPI;
1548
0
  }
1549
16
  else if (*xres == 0)
1550
0
  {
1551
0
    *xres = *yres;
1552
0
  }
1553
16
  else if (*yres == 0)
1554
0
  {
1555
0
    *yres = *xres;
1556
0
  }
1557
1558
  /* Scale xres and yres up until we get believable values */
1559
16
  if (*xres < SANE_DPI || *yres < SANE_DPI || *xres > INSANE_DPI || *yres > INSANE_DPI)
1560
0
  {
1561
0
    if (*xres < *yres)
1562
0
    {
1563
0
      *yres = *yres * SANE_DPI / *xres;
1564
0
      *xres = SANE_DPI;
1565
0
    }
1566
0
    else
1567
0
    {
1568
0
      *xres = *xres * SANE_DPI / *yres;
1569
0
      *yres = SANE_DPI;
1570
0
    }
1571
1572
0
    if (*xres == *yres || *xres < SANE_DPI || *yres < SANE_DPI || *xres > INSANE_DPI || *yres > INSANE_DPI)
1573
0
    {
1574
0
      *xres = SANE_DPI;
1575
0
      *yres = SANE_DPI;
1576
0
    }
1577
0
  }
1578
16
}
1579
1580
uint8_t fz_image_orientation(fz_context *ctx, fz_image *image)
1581
16
{
1582
16
  return image ? image->orientation : 0;
1583
16
}
1584
1585
fz_matrix fz_image_orientation_matrix(fz_context *ctx, fz_image *image)
1586
8
{
1587
8
  fz_matrix m;
1588
1589
8
  switch (image ? image->orientation : 0)
1590
8
  {
1591
6
  case 0:
1592
7
  case 1: /* 0 degree rotation */
1593
7
    m.a =  1; m.b =  0;
1594
7
    m.c =  0; m.d =  1;
1595
7
    m.e =  0; m.f =  0;
1596
7
    break;
1597
0
  case 2: /* 90 degree ccw */
1598
0
    m.a =  0; m.b = -1;
1599
0
    m.c =  1; m.d =  0;
1600
0
    m.e =  0; m.f =  1;
1601
0
    break;
1602
0
  case 3: /* 180 degree ccw */
1603
0
    m.a = -1; m.b =  0;
1604
0
    m.c =  0; m.d = -1;
1605
0
    m.e =  1; m.f =  1;
1606
0
    break;
1607
1
  case 4: /* 270 degree ccw */
1608
1
    m.a =  0; m.b =  1;
1609
1
    m.c = -1; m.d =  0;
1610
1
    m.e =  1; m.f =  0;
1611
1
    break;
1612
0
  case 5: /* flip on X */
1613
0
    m.a = -1; m.b = 0;
1614
0
    m.c =  0; m.d = 1;
1615
0
    m.e =  1; m.f = 0;
1616
0
    break;
1617
0
  case 6: /* flip on X, then rotate ccw by 90 degrees */
1618
0
    m.a =  0; m.b =  1;
1619
0
    m.c =  1; m.d =  0;
1620
0
    m.e =  0; m.f =  0;
1621
0
    break;
1622
0
  case 7: /* flip on X, then rotate ccw by 180 degrees */
1623
0
    m.a =  1; m.b =  0;
1624
0
    m.c =  0; m.d = -1;
1625
0
    m.e =  0; m.f =  1;
1626
0
    break;
1627
0
  case 8: /* flip on X, then rotate ccw by 270 degrees */
1628
0
    m.a =  0; m.b = -1;
1629
0
    m.c = -1; m.d =  0;
1630
0
    m.e =  1; m.f =  1;
1631
0
    break;
1632
8
  }
1633
1634
8
  return m;
1635
8
}
1636
1637
typedef struct fz_display_list_image_s
1638
{
1639
  fz_image super;
1640
  fz_matrix transform;
1641
  fz_display_list *list;
1642
} fz_display_list_image;
1643
1644
static fz_pixmap *
1645
display_list_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
1646
0
{
1647
0
  fz_display_list_image *image = (fz_display_list_image *)image_;
1648
0
  fz_matrix ctm;
1649
0
  fz_device *dev;
1650
0
  fz_pixmap *pix;
1651
1652
0
  fz_var(dev);
1653
1654
0
  if (subarea)
1655
0
  {
1656
    /* So, the whole image should be scaled to w * h, but we only want the
1657
     * given subarea of it. */
1658
0
    int l = (subarea->x0 * w) / image->super.w;
1659
0
    int t = (subarea->y0 * h) / image->super.h;
1660
0
    int r = (subarea->x1 * w + image->super.w - 1) / image->super.w;
1661
0
    int b = (subarea->y1 * h + image->super.h - 1) / image->super.h;
1662
1663
0
    pix = fz_new_pixmap(ctx, image->super.colorspace, r-l, b-t, NULL, 0);
1664
0
    pix->x = l;
1665
0
    pix->y = t;
1666
0
  }
1667
0
  else
1668
0
  {
1669
0
    pix = fz_new_pixmap(ctx, image->super.colorspace, w, h, NULL, 0);
1670
0
  }
1671
1672
  /* If we render the display list into pix with the image matrix, we'll get a unit
1673
   * square result. Therefore scale by w, h. */
1674
0
  ctm = fz_pre_scale(image->transform, w, h);
1675
1676
0
  fz_clear_pixmap(ctx, pix); /* clear to transparent */
1677
0
  fz_try(ctx)
1678
0
  {
1679
0
    dev = fz_new_draw_device(ctx, ctm, pix);
1680
0
    fz_run_display_list(ctx, image->list, dev, fz_identity, fz_infinite_rect, NULL);
1681
0
    fz_close_device(ctx, dev);
1682
0
  }
1683
0
  fz_always(ctx)
1684
0
    fz_drop_device(ctx, dev);
1685
0
  fz_catch(ctx)
1686
0
  {
1687
0
    fz_drop_pixmap(ctx, pix);
1688
0
    fz_rethrow(ctx);
1689
0
  }
1690
1691
  /* Never do more subsampling, cos we've already given them the right size */
1692
0
  if (l2factor)
1693
0
    *l2factor = 0;
1694
1695
0
  return pix;
1696
0
}
1697
1698
static void drop_display_list_image(fz_context *ctx, fz_image *image_)
1699
0
{
1700
0
  fz_display_list_image *image = (fz_display_list_image *)image_;
1701
1702
0
  if (image == NULL)
1703
0
    return;
1704
0
  fz_drop_display_list(ctx, image->list);
1705
0
}
1706
1707
static size_t
1708
display_list_image_get_size(fz_context *ctx, fz_image *image_)
1709
0
{
1710
0
  fz_display_list_image *image = (fz_display_list_image *)image_;
1711
1712
0
  if (image == NULL)
1713
0
    return 0;
1714
1715
0
  return sizeof(fz_display_list_image) + 4096; /* FIXME */
1716
0
}
1717
1718
fz_image *fz_new_image_from_display_list(fz_context *ctx, float w, float h, fz_display_list *list)
1719
0
{
1720
0
  fz_display_list_image *image;
1721
0
  int iw, ih;
1722
1723
0
  iw = w * SCALABLE_IMAGE_DPI / 72;
1724
0
  ih = h * SCALABLE_IMAGE_DPI / 72;
1725
1726
0
  image = fz_new_derived_image(ctx, iw, ih, 8, fz_device_rgb(ctx),
1727
0
        SCALABLE_IMAGE_DPI, SCALABLE_IMAGE_DPI, 0, 0,
1728
0
        NULL, NULL, NULL, fz_display_list_image,
1729
0
        display_list_image_get_pixmap,
1730
0
        display_list_image_get_size,
1731
0
        drop_display_list_image);
1732
0
  image->super.scalable = 1;
1733
0
  image->transform = fz_scale(1 / w, 1 / h);
1734
0
  image->list = fz_keep_display_list(ctx, list);
1735
1736
0
  return &image->super;
1737
0
}