mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	Merge pull request #4996 from nulano/jp2-decode-subsample
This commit is contained in:
		
						commit
						197673b9b2
					
				| 
						 | 
					@ -1,3 +1,4 @@
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +14,8 @@ from .helper import (
 | 
				
			||||||
    skip_unless_feature,
 | 
					    skip_unless_feature,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXTRA_DIR = "Tests/images/jpeg2000"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pytestmark = skip_unless_feature("jpg_2000")
 | 
					pytestmark = skip_unless_feature("jpg_2000")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_card = Image.open("Tests/images/test-card.png")
 | 
					test_card = Image.open("Tests/images/test-card.png")
 | 
				
			||||||
| 
						 | 
					@ -233,6 +236,26 @@ def test_parser_feed():
 | 
				
			||||||
    assert p.image.size == (640, 480)
 | 
					    assert p.image.size == (640, 480)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.mark.skipif(
 | 
				
			||||||
 | 
					    not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					@pytest.mark.parametrize("name", ("subsampling_1", "subsampling_2", "zoo1", "zoo2"))
 | 
				
			||||||
 | 
					def test_subsampling_decode(name):
 | 
				
			||||||
 | 
					    test = f"{EXTRA_DIR}/{name}.jp2"
 | 
				
			||||||
 | 
					    reference = f"{EXTRA_DIR}/{name}.ppm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with Image.open(test) as im:
 | 
				
			||||||
 | 
					        epsilon = 3  # for YCbCr images
 | 
				
			||||||
 | 
					        with Image.open(reference) as im2:
 | 
				
			||||||
 | 
					            width, height = im2.size
 | 
				
			||||||
 | 
					            if name[-1] == "2":
 | 
				
			||||||
 | 
					                # RGB reference images are downscaled
 | 
				
			||||||
 | 
					                epsilon = 3e-3
 | 
				
			||||||
 | 
					                width, height = width * 2, height * 2
 | 
				
			||||||
 | 
					            expected = im2.resize((width, height), Image.NEAREST)
 | 
				
			||||||
 | 
					        assert_image_similar(im, expected, epsilon)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize(
 | 
					@pytest.mark.parametrize(
 | 
				
			||||||
    "test_file",
 | 
					    "test_file",
 | 
				
			||||||
    [
 | 
					    [
 | 
				
			||||||
| 
						 | 
					@ -246,4 +269,7 @@ def test_crashes(test_file):
 | 
				
			||||||
    with open(test_file, "rb") as f:
 | 
					    with open(test_file, "rb") as f:
 | 
				
			||||||
        with Image.open(f) as im:
 | 
					        with Image.open(f) as im:
 | 
				
			||||||
            # Valgrind should not complain here
 | 
					            # Valgrind should not complain here
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
                im.load()
 | 
					                im.load()
 | 
				
			||||||
 | 
					            except OSError:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,6 +73,8 @@ struct j2k_decode_unpacker {
 | 
				
			||||||
    const char *mode;
 | 
					    const char *mode;
 | 
				
			||||||
    OPJ_COLOR_SPACE color_space;
 | 
					    OPJ_COLOR_SPACE color_space;
 | 
				
			||||||
    unsigned components;
 | 
					    unsigned components;
 | 
				
			||||||
 | 
					    /* bool indicating if unpacker supports subsampling */
 | 
				
			||||||
 | 
					    int subsampling;
 | 
				
			||||||
    j2k_unpacker_t unpacker;
 | 
					    j2k_unpacker_t unpacker;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -350,6 +352,7 @@ j2ku_srgb_rgb(
 | 
				
			||||||
    unsigned h = tileinfo->y1 - tileinfo->y0;
 | 
					    unsigned h = tileinfo->y1 - tileinfo->y0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int shifts[3], offsets[3], csiz[3];
 | 
					    int shifts[3], offsets[3], csiz[3];
 | 
				
			||||||
 | 
					    unsigned dx[3], dy[3];
 | 
				
			||||||
    const UINT8 *cdata[3];
 | 
					    const UINT8 *cdata[3];
 | 
				
			||||||
    const UINT8 *cptr = tiledata;
 | 
					    const UINT8 *cptr = tiledata;
 | 
				
			||||||
    unsigned n, x, y;
 | 
					    unsigned n, x, y;
 | 
				
			||||||
| 
						 | 
					@ -359,6 +362,8 @@ j2ku_srgb_rgb(
 | 
				
			||||||
        shifts[n] = 8 - in->comps[n].prec;
 | 
					        shifts[n] = 8 - in->comps[n].prec;
 | 
				
			||||||
        offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
 | 
					        offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
 | 
				
			||||||
        csiz[n] = (in->comps[n].prec + 7) >> 3;
 | 
					        csiz[n] = (in->comps[n].prec + 7) >> 3;
 | 
				
			||||||
 | 
					        dx[n] = (in->comps[n].dx);
 | 
				
			||||||
 | 
					        dy[n] = (in->comps[n].dy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (csiz[n] == 3) {
 | 
					        if (csiz[n] == 3) {
 | 
				
			||||||
            csiz[n] = 4;
 | 
					            csiz[n] = 4;
 | 
				
			||||||
| 
						 | 
					@ -368,14 +373,14 @@ j2ku_srgb_rgb(
 | 
				
			||||||
            offsets[n] += 1 << (-shifts[n] - 1);
 | 
					            offsets[n] += 1 << (-shifts[n] - 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cptr += csiz[n] * w * h;
 | 
					        cptr += csiz[n] * (w / dx[n]) * (h / dy[n]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (y = 0; y < h; ++y) {
 | 
					    for (y = 0; y < h; ++y) {
 | 
				
			||||||
        const UINT8 *data[3];
 | 
					        const UINT8 *data[3];
 | 
				
			||||||
        UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
 | 
					        UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
 | 
				
			||||||
        for (n = 0; n < 3; ++n) {
 | 
					        for (n = 0; n < 3; ++n) {
 | 
				
			||||||
            data[n] = &cdata[n][csiz[n] * y * w];
 | 
					            data[n] = &cdata[n][csiz[n] * (y / dy[n]) * (w / dx[n])];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (x = 0; x < w; ++x) {
 | 
					        for (x = 0; x < w; ++x) {
 | 
				
			||||||
| 
						 | 
					@ -384,15 +389,13 @@ j2ku_srgb_rgb(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                switch (csiz[n]) {
 | 
					                switch (csiz[n]) {
 | 
				
			||||||
                    case 1:
 | 
					                    case 1:
 | 
				
			||||||
                        word = *data[n]++;
 | 
					                        word = data[n][x / dx[n]];
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 2:
 | 
					                    case 2:
 | 
				
			||||||
                        word = *(const UINT16 *)data[n];
 | 
					                        word = ((const UINT16 *)data[n])[x / dx[n]];
 | 
				
			||||||
                        data[n] += 2;
 | 
					 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 4:
 | 
					                    case 4:
 | 
				
			||||||
                        word = *(const UINT32 *)data[n];
 | 
					                        word = ((const UINT32 *)data[n])[x / dx[n]];
 | 
				
			||||||
                        data[n] += 4;
 | 
					 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -415,6 +418,7 @@ j2ku_sycc_rgb(
 | 
				
			||||||
    unsigned h = tileinfo->y1 - tileinfo->y0;
 | 
					    unsigned h = tileinfo->y1 - tileinfo->y0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int shifts[3], offsets[3], csiz[3];
 | 
					    int shifts[3], offsets[3], csiz[3];
 | 
				
			||||||
 | 
					    unsigned dx[3], dy[3];
 | 
				
			||||||
    const UINT8 *cdata[3];
 | 
					    const UINT8 *cdata[3];
 | 
				
			||||||
    const UINT8 *cptr = tiledata;
 | 
					    const UINT8 *cptr = tiledata;
 | 
				
			||||||
    unsigned n, x, y;
 | 
					    unsigned n, x, y;
 | 
				
			||||||
| 
						 | 
					@ -424,6 +428,8 @@ j2ku_sycc_rgb(
 | 
				
			||||||
        shifts[n] = 8 - in->comps[n].prec;
 | 
					        shifts[n] = 8 - in->comps[n].prec;
 | 
				
			||||||
        offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
 | 
					        offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
 | 
				
			||||||
        csiz[n] = (in->comps[n].prec + 7) >> 3;
 | 
					        csiz[n] = (in->comps[n].prec + 7) >> 3;
 | 
				
			||||||
 | 
					        dx[n] = (in->comps[n].dx);
 | 
				
			||||||
 | 
					        dy[n] = (in->comps[n].dy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (csiz[n] == 3) {
 | 
					        if (csiz[n] == 3) {
 | 
				
			||||||
            csiz[n] = 4;
 | 
					            csiz[n] = 4;
 | 
				
			||||||
| 
						 | 
					@ -433,7 +439,7 @@ j2ku_sycc_rgb(
 | 
				
			||||||
            offsets[n] += 1 << (-shifts[n] - 1);
 | 
					            offsets[n] += 1 << (-shifts[n] - 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cptr += csiz[n] * w * h;
 | 
					        cptr += csiz[n] * (w / dx[n]) * (h / dy[n]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (y = 0; y < h; ++y) {
 | 
					    for (y = 0; y < h; ++y) {
 | 
				
			||||||
| 
						 | 
					@ -441,7 +447,7 @@ j2ku_sycc_rgb(
 | 
				
			||||||
        UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
 | 
					        UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
 | 
				
			||||||
        UINT8 *row_start = row;
 | 
					        UINT8 *row_start = row;
 | 
				
			||||||
        for (n = 0; n < 3; ++n) {
 | 
					        for (n = 0; n < 3; ++n) {
 | 
				
			||||||
            data[n] = &cdata[n][csiz[n] * y * w];
 | 
					            data[n] = &cdata[n][csiz[n] * (y / dy[n]) * (w / dx[n])];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (x = 0; x < w; ++x) {
 | 
					        for (x = 0; x < w; ++x) {
 | 
				
			||||||
| 
						 | 
					@ -450,15 +456,13 @@ j2ku_sycc_rgb(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                switch (csiz[n]) {
 | 
					                switch (csiz[n]) {
 | 
				
			||||||
                    case 1:
 | 
					                    case 1:
 | 
				
			||||||
                        word = *data[n]++;
 | 
					                        word = data[n][x / dx[n]];
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 2:
 | 
					                    case 2:
 | 
				
			||||||
                        word = *(const UINT16 *)data[n];
 | 
					                        word = ((const UINT16 *)data[n])[x / dx[n]];
 | 
				
			||||||
                        data[n] += 2;
 | 
					 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 4:
 | 
					                    case 4:
 | 
				
			||||||
                        word = *(const UINT32 *)data[n];
 | 
					                        word = ((const UINT32 *)data[n])[x / dx[n]];
 | 
				
			||||||
                        data[n] += 4;
 | 
					 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -483,6 +487,7 @@ j2ku_srgba_rgba(
 | 
				
			||||||
    unsigned h = tileinfo->y1 - tileinfo->y0;
 | 
					    unsigned h = tileinfo->y1 - tileinfo->y0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int shifts[4], offsets[4], csiz[4];
 | 
					    int shifts[4], offsets[4], csiz[4];
 | 
				
			||||||
 | 
					    unsigned dx[4], dy[4];
 | 
				
			||||||
    const UINT8 *cdata[4];
 | 
					    const UINT8 *cdata[4];
 | 
				
			||||||
    const UINT8 *cptr = tiledata;
 | 
					    const UINT8 *cptr = tiledata;
 | 
				
			||||||
    unsigned n, x, y;
 | 
					    unsigned n, x, y;
 | 
				
			||||||
| 
						 | 
					@ -492,6 +497,8 @@ j2ku_srgba_rgba(
 | 
				
			||||||
        shifts[n] = 8 - in->comps[n].prec;
 | 
					        shifts[n] = 8 - in->comps[n].prec;
 | 
				
			||||||
        offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
 | 
					        offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
 | 
				
			||||||
        csiz[n] = (in->comps[n].prec + 7) >> 3;
 | 
					        csiz[n] = (in->comps[n].prec + 7) >> 3;
 | 
				
			||||||
 | 
					        dx[n] = (in->comps[n].dx);
 | 
				
			||||||
 | 
					        dy[n] = (in->comps[n].dy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (csiz[n] == 3) {
 | 
					        if (csiz[n] == 3) {
 | 
				
			||||||
            csiz[n] = 4;
 | 
					            csiz[n] = 4;
 | 
				
			||||||
| 
						 | 
					@ -501,14 +508,14 @@ j2ku_srgba_rgba(
 | 
				
			||||||
            offsets[n] += 1 << (-shifts[n] - 1);
 | 
					            offsets[n] += 1 << (-shifts[n] - 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cptr += csiz[n] * w * h;
 | 
					        cptr += csiz[n] * (w / dx[n]) * (h / dy[n]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (y = 0; y < h; ++y) {
 | 
					    for (y = 0; y < h; ++y) {
 | 
				
			||||||
        const UINT8 *data[4];
 | 
					        const UINT8 *data[4];
 | 
				
			||||||
        UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
 | 
					        UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
 | 
				
			||||||
        for (n = 0; n < 4; ++n) {
 | 
					        for (n = 0; n < 4; ++n) {
 | 
				
			||||||
            data[n] = &cdata[n][csiz[n] * y * w];
 | 
					            data[n] = &cdata[n][csiz[n] * (y / dy[n]) * (w / dx[n])];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (x = 0; x < w; ++x) {
 | 
					        for (x = 0; x < w; ++x) {
 | 
				
			||||||
| 
						 | 
					@ -517,15 +524,13 @@ j2ku_srgba_rgba(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                switch (csiz[n]) {
 | 
					                switch (csiz[n]) {
 | 
				
			||||||
                    case 1:
 | 
					                    case 1:
 | 
				
			||||||
                        word = *data[n]++;
 | 
					                        word = data[n][x / dx[n]];
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 2:
 | 
					                    case 2:
 | 
				
			||||||
                        word = *(const UINT16 *)data[n];
 | 
					                        word = ((const UINT16 *)data[n])[x / dx[n]];
 | 
				
			||||||
                        data[n] += 2;
 | 
					 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 4:
 | 
					                    case 4:
 | 
				
			||||||
                        word = *(const UINT32 *)data[n];
 | 
					                        word = ((const UINT32 *)data[n])[x / dx[n]];
 | 
				
			||||||
                        data[n] += 4;
 | 
					 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -547,6 +552,7 @@ j2ku_sycca_rgba(
 | 
				
			||||||
    unsigned h = tileinfo->y1 - tileinfo->y0;
 | 
					    unsigned h = tileinfo->y1 - tileinfo->y0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int shifts[4], offsets[4], csiz[4];
 | 
					    int shifts[4], offsets[4], csiz[4];
 | 
				
			||||||
 | 
					    unsigned dx[4], dy[4];
 | 
				
			||||||
    const UINT8 *cdata[4];
 | 
					    const UINT8 *cdata[4];
 | 
				
			||||||
    const UINT8 *cptr = tiledata;
 | 
					    const UINT8 *cptr = tiledata;
 | 
				
			||||||
    unsigned n, x, y;
 | 
					    unsigned n, x, y;
 | 
				
			||||||
| 
						 | 
					@ -556,6 +562,8 @@ j2ku_sycca_rgba(
 | 
				
			||||||
        shifts[n] = 8 - in->comps[n].prec;
 | 
					        shifts[n] = 8 - in->comps[n].prec;
 | 
				
			||||||
        offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
 | 
					        offsets[n] = in->comps[n].sgnd ? 1 << (in->comps[n].prec - 1) : 0;
 | 
				
			||||||
        csiz[n] = (in->comps[n].prec + 7) >> 3;
 | 
					        csiz[n] = (in->comps[n].prec + 7) >> 3;
 | 
				
			||||||
 | 
					        dx[n] = (in->comps[n].dx);
 | 
				
			||||||
 | 
					        dy[n] = (in->comps[n].dy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (csiz[n] == 3) {
 | 
					        if (csiz[n] == 3) {
 | 
				
			||||||
            csiz[n] = 4;
 | 
					            csiz[n] = 4;
 | 
				
			||||||
| 
						 | 
					@ -565,7 +573,7 @@ j2ku_sycca_rgba(
 | 
				
			||||||
            offsets[n] += 1 << (-shifts[n] - 1);
 | 
					            offsets[n] += 1 << (-shifts[n] - 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cptr += csiz[n] * w * h;
 | 
					        cptr += csiz[n] * (w / dx[n]) * (h / dy[n]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (y = 0; y < h; ++y) {
 | 
					    for (y = 0; y < h; ++y) {
 | 
				
			||||||
| 
						 | 
					@ -573,7 +581,7 @@ j2ku_sycca_rgba(
 | 
				
			||||||
        UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
 | 
					        UINT8 *row = (UINT8 *)im->image[y0 + y] + x0 * 4;
 | 
				
			||||||
        UINT8 *row_start = row;
 | 
					        UINT8 *row_start = row;
 | 
				
			||||||
        for (n = 0; n < 4; ++n) {
 | 
					        for (n = 0; n < 4; ++n) {
 | 
				
			||||||
            data[n] = &cdata[n][csiz[n] * y * w];
 | 
					            data[n] = &cdata[n][csiz[n] * (y / dy[n]) * (w / dx[n])];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (x = 0; x < w; ++x) {
 | 
					        for (x = 0; x < w; ++x) {
 | 
				
			||||||
| 
						 | 
					@ -582,15 +590,13 @@ j2ku_sycca_rgba(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                switch (csiz[n]) {
 | 
					                switch (csiz[n]) {
 | 
				
			||||||
                    case 1:
 | 
					                    case 1:
 | 
				
			||||||
                        word = *data[n]++;
 | 
					                        word = data[n][x / dx[n]];
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 2:
 | 
					                    case 2:
 | 
				
			||||||
                        word = *(const UINT16 *)data[n];
 | 
					                        word = ((const UINT16 *)data[n])[x / dx[n]];
 | 
				
			||||||
                        data[n] += 2;
 | 
					 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case 4:
 | 
					                    case 4:
 | 
				
			||||||
                        word = *(const UINT32 *)data[n];
 | 
					                        word = ((const UINT32 *)data[n])[x / dx[n]];
 | 
				
			||||||
                        data[n] += 4;
 | 
					 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -604,22 +610,22 @@ j2ku_sycca_rgba(
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct j2k_decode_unpacker j2k_unpackers[] = {
 | 
					static const struct j2k_decode_unpacker j2k_unpackers[] = {
 | 
				
			||||||
    {"L", OPJ_CLRSPC_GRAY, 1, j2ku_gray_l},
 | 
					    {"L", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_l},
 | 
				
			||||||
    {"I;16", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i},
 | 
					    {"I;16", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_i},
 | 
				
			||||||
    {"I;16B", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i},
 | 
					    {"I;16B", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_i},
 | 
				
			||||||
    {"LA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la},
 | 
					    {"LA", OPJ_CLRSPC_GRAY, 2, 0, j2ku_graya_la},
 | 
				
			||||||
    {"RGB", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb},
 | 
					    {"RGB", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_rgb},
 | 
				
			||||||
    {"RGB", OPJ_CLRSPC_GRAY, 2, j2ku_gray_rgb},
 | 
					    {"RGB", OPJ_CLRSPC_GRAY, 2, 0, j2ku_gray_rgb},
 | 
				
			||||||
    {"RGB", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb},
 | 
					    {"RGB", OPJ_CLRSPC_SRGB, 3, 1, j2ku_srgb_rgb},
 | 
				
			||||||
    {"RGB", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb},
 | 
					    {"RGB", OPJ_CLRSPC_SYCC, 3, 1, j2ku_sycc_rgb},
 | 
				
			||||||
    {"RGB", OPJ_CLRSPC_SRGB, 4, j2ku_srgb_rgb},
 | 
					    {"RGB", OPJ_CLRSPC_SRGB, 4, 1, j2ku_srgb_rgb},
 | 
				
			||||||
    {"RGB", OPJ_CLRSPC_SYCC, 4, j2ku_sycc_rgb},
 | 
					    {"RGB", OPJ_CLRSPC_SYCC, 4, 1, j2ku_sycc_rgb},
 | 
				
			||||||
    {"RGBA", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb},
 | 
					    {"RGBA", OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_rgb},
 | 
				
			||||||
    {"RGBA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la},
 | 
					    {"RGBA", OPJ_CLRSPC_GRAY, 2, 0, j2ku_graya_la},
 | 
				
			||||||
    {"RGBA", OPJ_CLRSPC_SRGB, 3, j2ku_srgb_rgb},
 | 
					    {"RGBA", OPJ_CLRSPC_SRGB, 3, 1, j2ku_srgb_rgb},
 | 
				
			||||||
    {"RGBA", OPJ_CLRSPC_SYCC, 3, j2ku_sycc_rgb},
 | 
					    {"RGBA", OPJ_CLRSPC_SYCC, 3, 1, j2ku_sycc_rgb},
 | 
				
			||||||
    {"RGBA", OPJ_CLRSPC_SRGB, 4, j2ku_srgba_rgba},
 | 
					    {"RGBA", OPJ_CLRSPC_SRGB, 4, 1, j2ku_srgba_rgba},
 | 
				
			||||||
    {"RGBA", OPJ_CLRSPC_SYCC, 4, j2ku_sycca_rgba},
 | 
					    {"RGBA", OPJ_CLRSPC_SYCC, 4, 1, j2ku_sycca_rgba},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* -------------------------------------------------------------------- */
 | 
					/* -------------------------------------------------------------------- */
 | 
				
			||||||
| 
						 | 
					@ -644,6 +650,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) {
 | 
				
			||||||
    j2k_unpacker_t unpack = NULL;
 | 
					    j2k_unpacker_t unpack = NULL;
 | 
				
			||||||
    size_t buffer_size = 0, tile_bytes = 0;
 | 
					    size_t buffer_size = 0, tile_bytes = 0;
 | 
				
			||||||
    unsigned n, tile_height, tile_width;
 | 
					    unsigned n, tile_height, tile_width;
 | 
				
			||||||
 | 
					    int subsampling;
 | 
				
			||||||
    int total_component_width = 0;
 | 
					    int total_component_width = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    stream = opj_stream_create(BUFFER_SIZE, OPJ_TRUE);
 | 
					    stream = opj_stream_create(BUFFER_SIZE, OPJ_TRUE);
 | 
				
			||||||
| 
						 | 
					@ -706,11 +713,16 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) {
 | 
				
			||||||
        goto quick_exit;
 | 
					        goto quick_exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (n = 1; n < image->numcomps; ++n) {
 | 
					    /*
 | 
				
			||||||
 | 
					     * Find first component with subsampling.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * This is a heuristic to determine the colorspace if unspecified.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    subsampling = -1;
 | 
				
			||||||
 | 
					    for (n = 0; n < image->numcomps; ++n) {
 | 
				
			||||||
        if (image->comps[n].dx != 1 || image->comps[n].dy != 1) {
 | 
					        if (image->comps[n].dx != 1 || image->comps[n].dy != 1) {
 | 
				
			||||||
            state->errcode = IMAGING_CODEC_BROKEN;
 | 
					            subsampling = n;
 | 
				
			||||||
            state->state = J2K_STATE_FAILED;
 | 
					            break;
 | 
				
			||||||
            goto quick_exit;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -726,12 +738,14 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       If colorspace is unspecified, we assume:
 | 
					       If colorspace is unspecified, we assume:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
           Number of components   Colorspace
 | 
					           Number of components   Subsampling   Colorspace
 | 
				
			||||||
         -----------------------------------------
 | 
					         -------------------------------------------------------
 | 
				
			||||||
           1                      gray
 | 
					           1                      Any           gray
 | 
				
			||||||
           2                      gray (+ alpha)
 | 
					           2                      Any           gray (+ alpha)
 | 
				
			||||||
           3                      sRGB
 | 
					           3                      -1, 0         sRGB
 | 
				
			||||||
           4                      sRGB (+ alpha)
 | 
					           3                      1, 2          YCbCr
 | 
				
			||||||
 | 
					           4                      -1, 0, 3      sRGB (+ alpha)
 | 
				
			||||||
 | 
					           4                      1, 2          YCbCr (+ alpha)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -746,14 +760,25 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) {
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case 3:
 | 
					            case 3:
 | 
				
			||||||
            case 4:
 | 
					            case 4:
 | 
				
			||||||
 | 
					                switch (subsampling) {
 | 
				
			||||||
 | 
					                    case -1:
 | 
				
			||||||
 | 
					                    case 0:
 | 
				
			||||||
 | 
					                    case 3:
 | 
				
			||||||
                        color_space = OPJ_CLRSPC_SRGB;
 | 
					                        color_space = OPJ_CLRSPC_SRGB;
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
 | 
					                    case 1:
 | 
				
			||||||
 | 
					                    case 2:
 | 
				
			||||||
 | 
					                        color_space = OPJ_CLRSPC_SYCC;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (n = 0; n < sizeof(j2k_unpackers) / sizeof(j2k_unpackers[0]); ++n) {
 | 
					    for (n = 0; n < sizeof(j2k_unpackers) / sizeof(j2k_unpackers[0]); ++n) {
 | 
				
			||||||
        if (color_space == j2k_unpackers[n].color_space &&
 | 
					        if (color_space == j2k_unpackers[n].color_space &&
 | 
				
			||||||
            image->numcomps == j2k_unpackers[n].components &&
 | 
					            image->numcomps == j2k_unpackers[n].components &&
 | 
				
			||||||
 | 
					            (j2k_unpackers[n].subsampling || (subsampling == -1)) &&
 | 
				
			||||||
            strcmp(im->mode, j2k_unpackers[n].mode) == 0) {
 | 
					            strcmp(im->mode, j2k_unpackers[n].mode) == 0) {
 | 
				
			||||||
            unpack = j2k_unpackers[n].unpacker;
 | 
					            unpack = j2k_unpackers[n].unpacker;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user