Skip to content

Commit 4f4c3b3

Browse files
committed
jpeg2000: add subsampling decoder support
1 parent 834821f commit 4f4c3b3

File tree

1 file changed

+79
-49
lines changed

1 file changed

+79
-49
lines changed

src/libImaging/Jpeg2KDecode.c

+79-49
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ struct j2k_decode_unpacker {
7878
const char *mode;
7979
OPJ_COLOR_SPACE color_space;
8080
unsigned components;
81+
/* bool indicating if unpacker supports subsampling */
82+
int subsampling;
8183
j2k_unpacker_t unpacker;
8284
};
8385

@@ -332,6 +334,7 @@ j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
332334
unsigned h = tileinfo->y1 - tileinfo->y0;
333335

334336
int shifts[3], offsets[3], csiz[3];
337+
unsigned dx[3], dy[3];
335338
const UINT8 *cdata[3];
336339
const UINT8 *cptr = tiledata;
337340
unsigned n, x, y;
@@ -341,6 +344,8 @@ j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
341344
shifts[n] = 8 - in->comps[n].prec;
342345
offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
343346
csiz[n] = (in->comps[n].prec + 7) >> 3;
347+
dx[n] = (in->comps[n].dx);
348+
dy[n] = (in->comps[n].dy);
344349

345350
if (csiz[n] == 3) {
346351
csiz[n] = 4;
@@ -350,24 +355,24 @@ j2ku_srgb_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
350355
offsets[n] += 1 << (-shifts[n] - 1);
351356
}
352357

353-
cptr += csiz[n] * w * h;
358+
cptr += csiz[n] * (w / dx[n]) * (h / dy[n]);
354359
}
355360

356361
for (y = 0; y < h; ++y) {
357362
const UINT8 *data[3];
358363
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
359364
for (n = 0; n < 3; ++n) {
360-
data[n] = &cdata[n][csiz[n] * y * w];
365+
data[n] = &cdata[n][csiz[n] * (y / dy[n]) * (w / dx[n])];
361366
}
362367

363368
for (x = 0; x < w; ++x) {
364369
for (n = 0; n < 3; ++n) {
365370
UINT32 word = 0;
366371

367372
switch (csiz[n]) {
368-
case 1: word = *data[n]++; break;
369-
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break;
370-
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break;
373+
case 1: word = data[n][x / dx[n]]; break;
374+
case 2: word = ((const UINT16 *)data[n])[x / dx[n]]; break;
375+
case 4: word = ((const UINT32 *)data[n])[x / dx[n]]; break;
371376
}
372377

373378
row[n] = j2ku_shift(offsets[n] + word, shifts[n]);
@@ -387,6 +392,7 @@ j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
387392
unsigned h = tileinfo->y1 - tileinfo->y0;
388393

389394
int shifts[3], offsets[3], csiz[3];
395+
unsigned dx[3], dy[3];
390396
const UINT8 *cdata[3];
391397
const UINT8 *cptr = tiledata;
392398
unsigned n, x, y;
@@ -396,6 +402,8 @@ j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
396402
shifts[n] = 8 - in->comps[n].prec;
397403
offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
398404
csiz[n] = (in->comps[n].prec + 7) >> 3;
405+
dx[n] = (in->comps[n].dx);
406+
dy[n] = (in->comps[n].dy);
399407

400408
if (csiz[n] == 3) {
401409
csiz[n] = 4;
@@ -405,25 +413,25 @@ j2ku_sycc_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
405413
offsets[n] += 1 << (-shifts[n] - 1);
406414
}
407415

408-
cptr += csiz[n] * w * h;
416+
cptr += csiz[n] * (w / dx[n]) * (h / dy[n]);
409417
}
410418

411419
for (y = 0; y < h; ++y) {
412420
const UINT8 *data[3];
413421
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
414422
UINT8 *row_start = row;
415423
for (n = 0; n < 3; ++n) {
416-
data[n] = &cdata[n][csiz[n] * y * w];
424+
data[n] = &cdata[n][csiz[n] * (y / dy[n]) * (w / dx[n])];
417425
}
418426

419427
for (x = 0; x < w; ++x) {
420428
for (n = 0; n < 3; ++n) {
421429
UINT32 word = 0;
422430

423431
switch (csiz[n]) {
424-
case 1: word = *data[n]++; break;
425-
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break;
426-
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break;
432+
case 1: word = data[n][x / dx[n]]; break;
433+
case 2: word = ((const UINT16 *)data[n])[x / dx[n]]; break;
434+
case 4: word = ((const UINT32 *)data[n])[x / dx[n]]; break;
427435
}
428436

429437
row[n] = j2ku_shift(offsets[n] + word, shifts[n]);
@@ -445,6 +453,7 @@ j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
445453
unsigned h = tileinfo->y1 - tileinfo->y0;
446454

447455
int shifts[4], offsets[4], csiz[4];
456+
unsigned dx[4], dy[4];
448457
const UINT8 *cdata[4];
449458
const UINT8 *cptr = tiledata;
450459
unsigned n, x, y;
@@ -454,6 +463,8 @@ j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
454463
shifts[n] = 8 - in->comps[n].prec;
455464
offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
456465
csiz[n] = (in->comps[n].prec + 7) >> 3;
466+
dx[n] = (in->comps[n].dx);
467+
dy[n] = (in->comps[n].dy);
457468

458469
if (csiz[n] == 3) {
459470
csiz[n] = 4;
@@ -463,24 +474,24 @@ j2ku_srgba_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
463474
offsets[n] += 1 << (-shifts[n] - 1);
464475
}
465476

466-
cptr += csiz[n] * w * h;
477+
cptr += csiz[n] * (w / dx[n]) * (h / dy[n]);
467478
}
468479

469480
for (y = 0; y < h; ++y) {
470481
const UINT8 *data[4];
471482
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
472483
for (n = 0; n < 4; ++n) {
473-
data[n] = &cdata[n][csiz[n] * y * w];
484+
data[n] = &cdata[n][csiz[n] * (y / dy[n]) * (w / dx[n])];
474485
}
475486

476487
for (x = 0; x < w; ++x) {
477488
for (n = 0; n < 4; ++n) {
478489
UINT32 word = 0;
479490

480491
switch (csiz[n]) {
481-
case 1: word = *data[n]++; break;
482-
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break;
483-
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break;
492+
case 1: word = data[n][x / dx[n]]; break;
493+
case 2: word = ((const UINT16 *)data[n])[x / dx[n]]; break;
494+
case 4: word = ((const UINT32 *)data[n])[x / dx[n]]; break;
484495
}
485496

486497
row[n] = j2ku_shift(offsets[n] + word, shifts[n]);
@@ -499,6 +510,7 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
499510
unsigned h = tileinfo->y1 - tileinfo->y0;
500511

501512
int shifts[4], offsets[4], csiz[4];
513+
unsigned dx[4], dy[4];
502514
const UINT8 *cdata[4];
503515
const UINT8 *cptr = tiledata;
504516
unsigned n, x, y;
@@ -508,6 +520,8 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
508520
shifts[n] = 8 - in->comps[n].prec;
509521
offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
510522
csiz[n] = (in->comps[n].prec + 7) >> 3;
523+
dx[n] = (in->comps[n].dx);
524+
dy[n] = (in->comps[n].dy);
511525

512526
if (csiz[n] == 3) {
513527
csiz[n] = 4;
@@ -517,25 +531,25 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
517531
offsets[n] += 1 << (-shifts[n] - 1);
518532
}
519533

520-
cptr += csiz[n] * w * h;
534+
cptr += csiz[n] * (w / dx[n]) * (h / dy[n]);
521535
}
522536

523537
for (y = 0; y < h; ++y) {
524538
const UINT8 *data[4];
525539
UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
526540
UINT8 *row_start = row;
527541
for (n = 0; n < 4; ++n) {
528-
data[n] = &cdata[n][csiz[n] * y * w];
542+
data[n] = &cdata[n][csiz[n] * (y / dy[n]) * (w / dx[n])];
529543
}
530544

531545
for (x = 0; x < w; ++x) {
532546
for (n = 0; n < 4; ++n) {
533547
UINT32 word = 0;
534548

535549
switch (csiz[n]) {
536-
case 1: word = *data[n]++; break;
537-
case 2: word = *(const UINT16 *)data[n]; data[n] += 2; break;
538-
case 4: word = *(const UINT32 *)data[n]; data[n] += 4; break;
550+
case 1: word = data[n][x / dx[n]]; break;
551+
case 2: word = ((const UINT16 *)data[n])[x / dx[n]]; break;
552+
case 4: word = ((const UINT32 *)data[n])[x / dx[n]]; break;
539553
}
540554

541555
row[n] = j2ku_shift(offsets[n] + word, shifts[n]);
@@ -548,22 +562,22 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
548562
}
549563

550564
static const struct j2k_decode_unpacker j2k_unpackers[] = {
551-
{ "L", OPJ_CLRSPC_GRAY, 1, j2ku_gray_l },
552-
{ "I;16", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i },
553-
{ "I;16B", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i },
554-
{ "LA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la },
555-
{ "RGB", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb },
556-
{ "RGB", OPJ_CLRSPC_GRAY, 2, j2ku_gray_rgb },
557-
{ "RGB", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb },
558-
{ "RGB", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb },
559-
{ "RGB", OPJ_CLRSPC_SRGB, 4, j2ku_srgb_rgb },
560-
{ "RGB", OPJ_CLRSPC_SYCC, 4, j2ku_sycc_rgb },
561-
{ "RGBA", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb },
562-
{ "RGBA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la },
563-
{ "RGBA", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb },
564-
{ "RGBA", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb },
565-
{ "RGBA", OPJ_CLRSPC_SRGB, 4, j2ku_srgba_rgba },
566-
{ "RGBA", OPJ_CLRSPC_SYCC, 4, j2ku_sycca_rgba },
565+
{ "L", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_l },
566+
{ "I;16", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_i },
567+
{ "I;16B", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_i },
568+
{ "LA", OPJ_CLRSPC_GRAY, 2, 0, j2ku_graya_la },
569+
{ "RGB", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_rgb },
570+
{ "RGB", OPJ_CLRSPC_GRAY, 2, 0, j2ku_gray_rgb },
571+
{ "RGB", OPJ_CLRSPC_SRGB, 3, 1, j2ku_srgb_rgb },
572+
{ "RGB", OPJ_CLRSPC_SYCC, 3, 1, j2ku_sycc_rgb },
573+
{ "RGB", OPJ_CLRSPC_SRGB, 4, 1, j2ku_srgb_rgb },
574+
{ "RGB", OPJ_CLRSPC_SYCC, 4, 1, j2ku_sycc_rgb },
575+
{ "RGBA", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_rgb },
576+
{ "RGBA", OPJ_CLRSPC_GRAY, 2, 0, j2ku_graya_la },
577+
{ "RGBA", OPJ_CLRSPC_SRGB, 3, 1, j2ku_srgb_rgb },
578+
{ "RGBA", OPJ_CLRSPC_SYCC, 3, 1, j2ku_sycc_rgb },
579+
{ "RGBA", OPJ_CLRSPC_SRGB, 4, 1, j2ku_srgba_rgba },
580+
{ "RGBA", OPJ_CLRSPC_SYCC, 4, 1, j2ku_sycca_rgba },
567581
};
568582

569583
/* -------------------------------------------------------------------- */
@@ -589,7 +603,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
589603
j2k_unpacker_t unpack = NULL;
590604
size_t buffer_size = 0, tile_bytes = 0;
591605
unsigned n, tile_height, tile_width;
592-
int components;
606+
int components, subsampling;
593607

594608

595609
stream = opj_stream_create(BUFFER_SIZE, OPJ_TRUE);
@@ -652,11 +666,16 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
652666
goto quick_exit;
653667
}
654668

655-
for (n = 1; n < image->numcomps; ++n) {
669+
/*
670+
* Find first component with subsampling.
671+
*
672+
* This is a heuristic to determine the colorspace if unspecified.
673+
*/
674+
subsampling = -1;
675+
for (n = 0; n < image->numcomps; ++n) {
656676
if (image->comps[n].dx != 1 || image->comps[n].dy != 1) {
657-
state->errcode = IMAGING_CODEC_BROKEN;
658-
state->state = J2K_STATE_FAILED;
659-
goto quick_exit;
677+
subsampling = n;
678+
break;
660679
}
661680
}
662681

@@ -672,12 +691,14 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
672691
673692
If colorspace is unspecified, we assume:
674693
675-
Number of components Colorspace
676-
-----------------------------------------
677-
1 gray
678-
2 gray (+ alpha)
679-
3 sRGB
680-
4 sRGB (+ alpha)
694+
Number of components Subsampling Colorspace
695+
-------------------------------------------------------
696+
1 Any gray
697+
2 Any gray (+ alpha)
698+
3 -1, 0 sRGB
699+
3 1, 2 YCbCr
700+
4 -1, 0, 3 sRGB (+ alpha)
701+
4 1, 2 YCbCr (+ alpha)
681702
682703
*/
683704

@@ -686,14 +707,23 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
686707

687708
if (color_space == OPJ_CLRSPC_UNSPECIFIED) {
688709
switch (image->numcomps) {
689-
case 1: case 2: color_space = OPJ_CLRSPC_GRAY; break;
690-
case 3: case 4: color_space = OPJ_CLRSPC_SRGB; break;
710+
case 1: case 2:
711+
color_space = OPJ_CLRSPC_GRAY; break;
712+
case 3: case 4:
713+
switch (subsampling) {
714+
case -1: case 0: case 3:
715+
color_space = OPJ_CLRSPC_SRGB; break;
716+
case 1: case 2:
717+
color_space = OPJ_CLRSPC_SYCC; break;
718+
}
719+
break;
691720
}
692721
}
693722

694723
for (n = 0; n < sizeof(j2k_unpackers) / sizeof (j2k_unpackers[0]); ++n) {
695724
if (color_space == j2k_unpackers[n].color_space
696725
&& image->numcomps == j2k_unpackers[n].components
726+
&& (j2k_unpackers[n].subsampling || (subsampling == -1))
697727
&& strcmp (im->mode, j2k_unpackers[n].mode) == 0) {
698728
unpack = j2k_unpackers[n].unpacker;
699729
break;

0 commit comments

Comments
 (0)