From 935816e8c989e326ab546e298fa946b2e427af18 Mon Sep 17 00:00:00 2001 From: mayeut Date: Tue, 3 Nov 2015 22:34:43 +0100 Subject: [PATCH] Update TIFF conversion to support more bit depth. Update #611 --- applications/codec/CMakeLists.txt | 1 + applications/codec/convert.c | 1096 ++++++++--------------- applications/codec/convert.h | 11 + applications/codec/converttif.c | 633 +++++++++++++ tests/CMakeLists.txt | 2 +- tests/nonregression/test_suite.ctest.in | 135 ++- 6 files changed, 1096 insertions(+), 782 deletions(-) create mode 100644 applications/codec/converttif.c diff --git a/applications/codec/CMakeLists.txt b/applications/codec/CMakeLists.txt index c0a4dd72..c91b9c01 100644 --- a/applications/codec/CMakeLists.txt +++ b/applications/codec/CMakeLists.txt @@ -3,6 +3,7 @@ # First thing define the common source: SET(common_SRCS convert.c + converttif.c index.c ${OPENJPEG_SOURCE_DIR}/applications/common/color.c ) diff --git a/applications/codec/convert.c b/applications/codec/convert.c index beeec151..8e459ab8 100644 --- a/applications/codec/convert.c +++ b/applications/codec/convert.c @@ -36,10 +36,6 @@ #include #include -#ifdef HAVE_LIBTIFF -#include -#endif /* HAVE_LIBTIFF */ - #ifdef HAVE_LIBPNG #include #include @@ -164,6 +160,389 @@ void scale_component(opj_image_comp_t* component, int precision) component->prec = precision; } + +/* planar / interleaved conversions */ +/* used by PNG/TIFF */ +static void convert_32s_C1P1(const int32_t* pSrc, int32_t* const* pDst, size_t length) +{ + memcpy(pDst[0], pSrc, length * sizeof(int32_t)); +} +static void convert_32s_C2P2(const int32_t* pSrc, int32_t* const* pDst, size_t length) +{ + size_t i; + int32_t* pDst0 = pDst[0]; + int32_t* pDst1 = pDst[1]; + + for (i = 0; i < length; i++) { + pDst0[i] = pSrc[2*i+0]; + pDst1[i] = pSrc[2*i+1]; + } +} +static void convert_32s_C3P3(const int32_t* pSrc, int32_t* const* pDst, size_t length) +{ + size_t i; + int32_t* pDst0 = pDst[0]; + int32_t* pDst1 = pDst[1]; + int32_t* pDst2 = pDst[2]; + + for (i = 0; i < length; i++) { + pDst0[i] = pSrc[3*i+0]; + pDst1[i] = pSrc[3*i+1]; + pDst2[i] = pSrc[3*i+2]; + } +} +static void convert_32s_C4P4(const int32_t* pSrc, int32_t* const* pDst, size_t length) +{ + size_t i; + int32_t* pDst0 = pDst[0]; + int32_t* pDst1 = pDst[1]; + int32_t* pDst2 = pDst[2]; + int32_t* pDst3 = pDst[3]; + + for (i = 0; i < length; i++) { + pDst0[i] = pSrc[4*i+0]; + pDst1[i] = pSrc[4*i+1]; + pDst2[i] = pSrc[4*i+2]; + pDst3[i] = pSrc[4*i+3]; + } +} +const convert_32s_CXPX convert_32s_CXPX_LUT[5] = { + NULL, + convert_32s_C1P1, + convert_32s_C2P2, + convert_32s_C3P3, + convert_32s_C4P4 +}; + +static void convert_32s_P1C1(int32_t const* const* pSrc, int32_t* pDst, size_t length, int32_t adjust) +{ + size_t i; + const int32_t* pSrc0 = pSrc[0]; + + for (i = 0; i < length; i++) { + pDst[i] = pSrc0[i] + adjust; + } +} +static void convert_32s_P2C2(int32_t const* const* pSrc, int32_t* pDst, size_t length, int32_t adjust) +{ + size_t i; + const int32_t* pSrc0 = pSrc[0]; + const int32_t* pSrc1 = pSrc[1]; + + for (i = 0; i < length; i++) { + pDst[2*i+0] = pSrc0[i] + adjust; + pDst[2*i+1] = pSrc1[i] + adjust; + } +} +static void convert_32s_P3C3(int32_t const* const* pSrc, int32_t* pDst, size_t length, int32_t adjust) +{ + size_t i; + const int32_t* pSrc0 = pSrc[0]; + const int32_t* pSrc1 = pSrc[1]; + const int32_t* pSrc2 = pSrc[2]; + + for (i = 0; i < length; i++) { + pDst[3*i+0] = pSrc0[i] + adjust; + pDst[3*i+1] = pSrc1[i] + adjust; + pDst[3*i+2] = pSrc2[i] + adjust; + } +} +static void convert_32s_P4C4(int32_t const* const* pSrc, int32_t* pDst, size_t length, int32_t adjust) +{ + size_t i; + const int32_t* pSrc0 = pSrc[0]; + const int32_t* pSrc1 = pSrc[1]; + const int32_t* pSrc2 = pSrc[2]; + const int32_t* pSrc3 = pSrc[3]; + + for (i = 0; i < length; i++) { + pDst[4*i+0] = pSrc0[i] + adjust; + pDst[4*i+1] = pSrc1[i] + adjust; + pDst[4*i+2] = pSrc2[i] + adjust; + pDst[4*i+3] = pSrc3[i] + adjust; + } +} +const convert_32s_PXCX convert_32s_PXCX_LUT[5] = { + NULL, + convert_32s_P1C1, + convert_32s_P2C2, + convert_32s_P3C3, + convert_32s_P4C4 +}; + +/* bit depth conversions */ +/* used by PNG/TIFF up to 8bpp */ +static void convert_1u32s_C1R(const uint8_t* pSrc, int32_t* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)7U); i+=8U) { + uint32_t val = *pSrc++; + pDst[i+0] = (int32_t)( val >> 7); + pDst[i+1] = (int32_t)((val >> 6) & 0x1U); + pDst[i+2] = (int32_t)((val >> 5) & 0x1U); + pDst[i+3] = (int32_t)((val >> 4) & 0x1U); + pDst[i+4] = (int32_t)((val >> 3) & 0x1U); + pDst[i+5] = (int32_t)((val >> 2) & 0x1U); + pDst[i+6] = (int32_t)((val >> 1) & 0x1U); + pDst[i+7] = (int32_t)(val & 0x1U); + } + if (length & 7U) { + uint32_t val = *pSrc++; + length = length & 7U; + pDst[i+0] = (int32_t)(val >> 7); + + if (length > 1U) { + pDst[i+1] = (int32_t)((val >> 6) & 0x1U); + if (length > 2U) { + pDst[i+2] = (int32_t)((val >> 5) & 0x1U); + if (length > 3U) { + pDst[i+3] = (int32_t)((val >> 4) & 0x1U); + if (length > 4U) { + pDst[i+4] = (int32_t)((val >> 3) & 0x1U); + if (length > 5U) { + pDst[i+5] = (int32_t)((val >> 2) & 0x1U); + if (length > 6U) { + pDst[i+6] = (int32_t)((val >> 1) & 0x1U); + } + } + } + } + } + } + } +} +static void convert_2u32s_C1R(const uint8_t* pSrc, int32_t* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)3U); i+=4U) { + uint32_t val = *pSrc++; + pDst[i+0] = (int32_t)( val >> 6); + pDst[i+1] = (int32_t)((val >> 4) & 0x3U); + pDst[i+2] = (int32_t)((val >> 2) & 0x3U); + pDst[i+3] = (int32_t)(val & 0x3U); + } + if (length & 3U) { + uint32_t val = *pSrc++; + length = length & 3U; + pDst[i+0] = (int32_t)(val >> 6); + + if (length > 1U) { + pDst[i+1] = (int32_t)((val >> 4) & 0x3U); + if (length > 2U) { + pDst[i+2] = (int32_t)((val >> 2) & 0x3U); + + } + } + } +} +static void convert_4u32s_C1R(const uint8_t* pSrc, int32_t* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)1U); i+=2U) { + uint32_t val = *pSrc++; + pDst[i+0] = (int32_t)(val >> 4); + pDst[i+1] = (int32_t)(val & 0xFU); + } + if (length & 1U) { + uint8_t val = *pSrc++; + pDst[i+0] = (int32_t)(val >> 4); + } +} +static void convert_6u32s_C1R(const uint8_t* pSrc, int32_t* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)3U); i+=4U) { + uint32_t val0 = *pSrc++; + uint32_t val1 = *pSrc++; + uint32_t val2 = *pSrc++; + pDst[i+0] = (int32_t)(val0 >> 2); + pDst[i+1] = (int32_t)(((val0 & 0x3U) << 4) | (val1 >> 4)); + pDst[i+2] = (int32_t)(((val1 & 0xFU) << 2) | (val2 >> 6)); + pDst[i+3] = (int32_t)(val2 & 0x3FU); + + } + if (length & 3U) { + uint32_t val0 = *pSrc++; + length = length & 3U; + pDst[i+0] = (int32_t)(val0 >> 2); + + if (length > 1U) { + uint32_t val1 = *pSrc++; + pDst[i+1] = (int32_t)(((val0 & 0x3U) << 4) | (val1 >> 4)); + if (length > 2U) { + uint32_t val2 = *pSrc++; + pDst[i+2] = (int32_t)(((val1 & 0xFU) << 2) | (val2 >> 6)); + } + } + } +} +static void convert_8u32s_C1R(const uint8_t* pSrc, int32_t* pDst, size_t length) +{ + size_t i; + for (i = 0; i < length; i++) { + pDst[i] = pSrc[i]; + } +} +const convert_XXx32s_C1R convert_XXu32s_C1R_LUT[9] = { + NULL, + convert_1u32s_C1R, + convert_2u32s_C1R, + NULL, + convert_4u32s_C1R, + NULL, + convert_6u32s_C1R, + NULL, + convert_8u32s_C1R +}; + + +static void convert_32s1u_C1R(const int32_t* pSrc, uint8_t* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)7U); i+=8U) { + uint32_t src0 = (uint32_t)pSrc[i+0]; + uint32_t src1 = (uint32_t)pSrc[i+1]; + uint32_t src2 = (uint32_t)pSrc[i+2]; + uint32_t src3 = (uint32_t)pSrc[i+3]; + uint32_t src4 = (uint32_t)pSrc[i+4]; + uint32_t src5 = (uint32_t)pSrc[i+5]; + uint32_t src6 = (uint32_t)pSrc[i+6]; + uint32_t src7 = (uint32_t)pSrc[i+7]; + + *pDst++ = (uint8_t)((src0 << 7) | (src1 << 6) | (src2 << 5) | (src3 << 4) | (src4 << 3) | (src5 << 2) | (src6 << 1) | src7); + } + + if (length & 7U) { + uint32_t src0 = (uint32_t)pSrc[i+0]; + uint32_t src1 = 0U; + uint32_t src2 = 0U; + uint32_t src3 = 0U; + uint32_t src4 = 0U; + uint32_t src5 = 0U; + uint32_t src6 = 0U; + length = length & 7U; + + if (length > 1U) { + src1 = (uint32_t)pSrc[i+1]; + if (length > 2U) { + src2 = (uint32_t)pSrc[i+2]; + if (length > 3U) { + src3 = (uint32_t)pSrc[i+3]; + if (length > 4U) { + src4 = (uint32_t)pSrc[i+4]; + if (length > 5U) { + src5 = (uint32_t)pSrc[i+5]; + if (length > 6U) { + src6 = (uint32_t)pSrc[i+6]; + } + } + } + } + } + } + *pDst++ = (uint8_t)((src0 << 7) | (src1 << 6) | (src2 << 5) | (src3 << 4) | (src4 << 3) | (src5 << 2) | (src6 << 1)); + } +} + +static void convert_32s2u_C1R(const int32_t* pSrc, uint8_t* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)3U); i+=4U) { + uint32_t src0 = (uint32_t)pSrc[i+0]; + uint32_t src1 = (uint32_t)pSrc[i+1]; + uint32_t src2 = (uint32_t)pSrc[i+2]; + uint32_t src3 = (uint32_t)pSrc[i+3]; + + *pDst++ = (uint8_t)((src0 << 6) | (src1 << 4) | (src2 << 2) | src3); + } + + if (length & 3U) { + uint32_t src0 = (uint32_t)pSrc[i+0]; + uint32_t src1 = 0U; + uint32_t src2 = 0U; + length = length & 3U; + + if (length > 1U) { + src1 = (uint32_t)pSrc[i+1]; + if (length > 2U) { + src2 = (uint32_t)pSrc[i+2]; + } + } + *pDst++ = (uint8_t)((src0 << 6) | (src1 << 4) | (src2 << 2)); + } +} + +static void convert_32s4u_C1R(const int32_t* pSrc, uint8_t* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)1U); i+=2U) { + uint32_t src0 = (uint32_t)pSrc[i+0]; + uint32_t src1 = (uint32_t)pSrc[i+1]; + + *pDst++ = (uint8_t)((src0 << 4) | src1); + } + + if (length & 1U) { + uint32_t src0 = (uint32_t)pSrc[i+0]; + *pDst++ = (uint8_t)((src0 << 4)); + } +} + +static void convert_32s6u_C1R(const int32_t* pSrc, uint8_t* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)3U); i+=4U) { + uint32_t src0 = (uint32_t)pSrc[i+0]; + uint32_t src1 = (uint32_t)pSrc[i+1]; + uint32_t src2 = (uint32_t)pSrc[i+2]; + uint32_t src3 = (uint32_t)pSrc[i+3]; + + *pDst++ = (uint8_t)((src0 << 2) | (src1 >> 4)); + *pDst++ = (uint8_t)(((src1 & 0xFU) << 4) | (src2 >> 2)); + *pDst++ = (uint8_t)(((src2 & 0x3U) << 6) | src3); + } + + if (length & 3U) { + uint32_t src0 = (uint32_t)pSrc[i+0]; + uint32_t src1 = 0U; + uint32_t src2 = 0U; + length = length & 3U; + + if (length > 1U) { + src1 = (uint32_t)pSrc[i+1]; + if (length > 2U) { + src2 = (uint32_t)pSrc[i+2]; + } + } + *pDst++ = (uint8_t)((src0 << 2) | (src1 >> 4)); + if (length > 1U) { + *pDst++ = (uint8_t)(((src1 & 0xFU) << 4) | (src2 >> 2)); + if (length > 2U) { + *pDst++ = (uint8_t)(((src2 & 0x3U) << 6)); + } + } + } +} +static void convert_32s8u_C1R(const int32_t* pSrc, uint8_t* pDst, size_t length) +{ + size_t i; + for (i = 0; i < length; ++i) { + pDst[i] = (uint8_t)pSrc[i]; + } +} +const convert_32sXXx_C1R convert_32sXXu_C1R_LUT[9] = { + NULL, + convert_32s1u_C1R, + convert_32s2u_C1R, + NULL, + convert_32s4u_C1R, + NULL, + convert_32s6u_C1R, + NULL, + convert_32s8u_C1R +}; + + /* -->> -->> -->> -->> TGA IMAGE FORMAT @@ -2202,715 +2581,6 @@ int imagetopnm(opj_image_t * image, const char *outfile) return 0; }/* imagetopnm() */ -#ifdef HAVE_LIBTIFF -/* -->> -->> -->> -->> - - TIFF IMAGE FORMAT - - <<-- <<-- <<-- <<-- */ - -int imagetotif(opj_image_t * image, const char *outfile) -{ - int width, height, imgsize; - int bps,index,adjust, sgnd; - int ushift, dshift, has_alpha, force16; - TIFF *tif; - tdata_t buf; - tstrip_t strip; - tsize_t strip_size; - - ushift = dshift = force16 = has_alpha = 0; - bps = image->comps[0].prec; - - if(bps > 8 && bps < 16) - { - ushift = 16 - bps; dshift = bps - ushift; - bps = 16; force16 = 1; - } - - if(bps != 8 && bps != 16) - { - fprintf(stderr,"imagetotif: Bits=%d, Only 8 and 16 bits implemented\n", - bps); - fprintf(stderr,"\tAborting\n"); - return 1; - } - tif = TIFFOpen(outfile, "wb"); - - if (!tif) - { - fprintf(stderr, "imagetotif:failed to open %s for writing\n", outfile); - return 1; - } - sgnd = image->comps[0].sgnd; - adjust = sgnd ? 1 << (image->comps[0].prec - 1) : 0; - - if(image->numcomps >= 3 - && image->comps[0].dx == image->comps[1].dx - && image->comps[1].dx == image->comps[2].dx - && image->comps[0].dy == image->comps[1].dy - && image->comps[1].dy == image->comps[2].dy - && image->comps[0].prec == image->comps[1].prec - && image->comps[1].prec == image->comps[2].prec) - { - has_alpha = (image->numcomps == 4); - - width = image->comps[0].w; - height = image->comps[0].h; - imgsize = width * height ; - - TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width); - TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height); - TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3 + has_alpha); - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); - TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); - TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); - TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1); - strip_size = TIFFStripSize(tif); - buf = _TIFFmalloc(strip_size); - index=0; - - for(strip = 0; strip < TIFFNumberOfStrips(tif); strip++) - { - unsigned char *dat8; - tsize_t i, ssize, last_i = 0; - int step, restx; - ssize = TIFFStripSize(tif); - dat8 = (unsigned char*)buf; - - if(bps == 8) - { - step = 3 + has_alpha; - restx = step - 1; - - for(i=0; i < ssize - restx; i += step) - { - int r, g, b, a = 0; - - if(index < imgsize) - { - r = image->comps[0].data[index]; - g = image->comps[1].data[index]; - b = image->comps[2].data[index]; - if(has_alpha) a = image->comps[3].data[index]; - - if(sgnd) - { - r += adjust; - g += adjust; - b += adjust; - if(has_alpha) a += adjust; - } - dat8[i+0] = r ; - dat8[i+1] = g ; - dat8[i+2] = b ; - if(has_alpha) dat8[i+3] = a; - - index++; - last_i = i + step; - } - else - break; - }/*for(i = 0;)*/ - - if(last_i < ssize) - { - for(i = last_i; i < ssize; i += step) - { - int r, g, b, a = 0; - - if(index < imgsize) - { - r = image->comps[0].data[index]; - g = image->comps[1].data[index]; - b = image->comps[2].data[index]; - if(has_alpha) a = image->comps[3].data[index]; - - if(sgnd) - { - r += adjust; - g += adjust; - b += adjust; - if(has_alpha) a += adjust; - } - dat8[i+0] = r ; - if(i+1 < ssize) dat8[i+1] = g ; else break; - if(i+2 < ssize) dat8[i+2] = b ; else break; - if(has_alpha) - { - if(i+3 < ssize) dat8[i+3] = a ; else break; - } - index++; - } - else - break; - }/*for(i)*/ - }/*if(last_i < ssize)*/ - - } /*if(bps == 8)*/ - else - if(bps == 16) - { - step = 6 + has_alpha + has_alpha; - restx = step - 1; - - for(i = 0; i < ssize - restx ; i += step) - { - int r, g, b, a = 0; - - if(index < imgsize) - { - r = image->comps[0].data[index]; - g = image->comps[1].data[index]; - b = image->comps[2].data[index]; - if(has_alpha) a = image->comps[3].data[index]; - - if(sgnd) - { - r += adjust; - g += adjust; - b += adjust; - if(has_alpha) a += adjust; - } - if(force16) - { - r = (r<>dshift); - g = (g<>dshift); - b = (b<>dshift); - if(has_alpha) a = (a<>dshift); - } - dat8[i+0] = r;/*LSB*/ - dat8[i+1] = (r >> 8);/*MSB*/ - dat8[i+2] = g; - dat8[i+3] = (g >> 8); - dat8[i+4] = b; - dat8[i+5] = (b >> 8); - if(has_alpha) - { - dat8[i+6] = a; - dat8[i+7] = (a >> 8); - } - index++; - last_i = i + step; - } - else - break; - }/*for(i = 0;)*/ - - if(last_i < ssize) - { - for(i = last_i ; i < ssize ; i += step) - { - int r, g, b, a = 0; - - if(index < imgsize) - { - r = image->comps[0].data[index]; - g = image->comps[1].data[index]; - b = image->comps[2].data[index]; - if(has_alpha) a = image->comps[3].data[index]; - - if(sgnd) - { - r += adjust; - g += adjust; - b += adjust; - if(has_alpha) a += adjust; - } - if(force16) - { - r = (r<>dshift); - g = (g<>dshift); - b = (b<>dshift); - if(has_alpha) a = (a<>dshift); - } - dat8[i+0] = r;/*LSB*/ - if(i+1 < ssize) dat8[i+1] = (r >> 8);else break;/*MSB*/ - if(i+2 < ssize) dat8[i+2] = g; else break; - if(i+3 < ssize) dat8[i+3] = (g >> 8);else break; - if(i+4 < ssize) dat8[i+4] = b; else break; - if(i+5 < ssize) dat8[i+5] = (b >> 8);else break; - - if(has_alpha) - { - if(i+6 < ssize) dat8[i+6] = a; else break; - if(i+7 < ssize) dat8[i+7] = (a >> 8); else break; - } - index++; - } - else - break; - }/*for(i)*/ - }/*if(last_i < ssize)*/ - - }/*if(bps == 16)*/ - (void)TIFFWriteEncodedStrip(tif, strip, (void*)buf, strip_size); - }/*for(strip = 0; )*/ - - _TIFFfree((void*)buf); - TIFFClose(tif); - - return 0; - }/*RGB(A)*/ - - if(image->numcomps == 1 /* GRAY */ - || ( image->numcomps == 2 /* GRAY_ALPHA */ - && image->comps[0].dx == image->comps[1].dx - && image->comps[0].dy == image->comps[1].dy - && image->comps[0].prec == image->comps[1].prec)) - { - int step; - - has_alpha = (image->numcomps == 2); - - width = image->comps[0].w; - height = image->comps[0].h; - imgsize = width * height; - -/* Set tags */ - TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width); - TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height); - TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1 + has_alpha); - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); - TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); - TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); - TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1); - -/* Get a buffer for the data */ - strip_size = TIFFStripSize(tif); - buf = _TIFFmalloc(strip_size); - index = 0; - - for(strip = 0; strip < TIFFNumberOfStrips(tif); strip++) - { - unsigned char *dat8; - tsize_t i, ssize = TIFFStripSize(tif); - dat8 = (unsigned char*)buf; - - if(bps == 8) - { - step = 1 + has_alpha; - - for(i=0; i < ssize; i += step) - { - if(index < imgsize) - { - int r, a = 0; - - r = image->comps[0].data[index]; - if(has_alpha) a = image->comps[1].data[index]; - - if(sgnd) - { - r += adjust; - if(has_alpha) a += adjust; - } - dat8[i+0] = r; - if(has_alpha) dat8[i+1] = a; - index++; - } - else - break; - }/*for(i )*/ - }/*if(bps == 8*/ - else - if(bps == 16) - { - step = 2 + has_alpha + has_alpha; - - for(i=0; i < ssize; i += step) - { - if(index < imgsize) - { - int r, a = 0; - - r = image->comps[0].data[index]; - if(has_alpha) a = image->comps[1].data[index]; - - if(sgnd) - { - r += adjust; - if(has_alpha) a += adjust; - } - if(force16) - { - r = (r<>dshift); - if(has_alpha) a = (a<>dshift); - } - dat8[i+0] = r;/*LSB*/ - dat8[i+1] = r >> 8;/*MSB*/ - if(has_alpha) - { - dat8[i+2] = a; - dat8[i+3] = a >> 8; - } - index++; - }/*if(index < imgsize)*/ - else - break; - }/*for(i )*/ - } - (void)TIFFWriteEncodedStrip(tif, strip, (void*)buf, strip_size); - }/*for(strip*/ - - _TIFFfree(buf); - TIFFClose(tif); - - return 0; - } - - TIFFClose(tif); - - fprintf(stderr,"imagetotif: Bad color format.\n" - "\tOnly RGB(A) and GRAY(A) has been implemented\n"); - fprintf(stderr,"\tFOUND: numcomps(%d)\n\tAborting\n", - image->numcomps); - - return 1; -}/* imagetotif() */ - -/* - * libtiff/tif_getimage.c : 1,2,4,8,16 bitspersample accepted - * CINEMA : 12 bit precision -*/ -opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters) -{ - int subsampling_dx = parameters->subsampling_dx; - int subsampling_dy = parameters->subsampling_dy; - TIFF *tif; - tdata_t buf; - tstrip_t strip; - tsize_t strip_size; - int j, numcomps, w, h,index; - OPJ_COLOR_SPACE color_space; - opj_image_cmptparm_t cmptparm[4]; /* RGBA */ - opj_image_t *image = NULL; - int imgsize = 0; - int has_alpha = 0; - unsigned short tiBps, tiPhoto, tiSf, tiSpp, tiPC; - unsigned int tiWidth, tiHeight; - - tif = TIFFOpen(filename, "r"); - - if(!tif) - { - fprintf(stderr, "tiftoimage:Failed to open %s for reading\n", filename); - return 0; - } - tiBps = tiPhoto = tiSf = tiSpp = tiPC = 0; - tiWidth = tiHeight = 0; - - TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &tiWidth); - TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &tiHeight); - TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &tiBps); - TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &tiSf); - TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &tiSpp); - TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &tiPhoto); - TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &tiPC); - w= tiWidth; - h= tiHeight; - - { - unsigned short b = tiBps, p = tiPhoto; - - if(tiBps != 8 && tiBps != 16 && tiBps != 12) b = 0; - if(tiPhoto != 1 && tiPhoto != 2) p = 0; - - if( !b || !p) - { - if( !b) - fprintf(stderr,"imagetotif: Bits=%d, Only 8 and 16 bits" - " implemented\n",tiBps); - else - if( !p) - fprintf(stderr,"tiftoimage: Bad color format %d.\n\tOnly RGB(A)" - " and GRAY(A) has been implemented\n",(int) tiPhoto); - - fprintf(stderr,"\tAborting\n"); - TIFFClose(tif); - - return NULL; - } - } - {/* From: tiff-4.0.x/libtiff/tif_getimage.c : */ - uint16* sampleinfo; - uint16 extrasamples; - - TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, - &extrasamples, &sampleinfo); - - if(extrasamples >= 1) - { - switch(sampleinfo[0]) - { - case EXTRASAMPLE_UNSPECIFIED: -/* Workaround for some images without correct info about alpha channel -*/ - if(tiSpp > 3) - has_alpha = 1; - break; - - case EXTRASAMPLE_ASSOCALPHA: /* data pre-multiplied */ - case EXTRASAMPLE_UNASSALPHA: /* data not pre-multiplied */ - has_alpha = 1; - break; - } - } - else /* extrasamples == 0 */ - if(tiSpp == 4 || tiSpp == 2) has_alpha = 1; - } - -/* initialize image components -*/ - memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t)); - - if(tiPhoto == PHOTOMETRIC_RGB) /* RGB(A) */ - { - numcomps = 3 + has_alpha; - color_space = CLRSPC_SRGB; - - for(j = 0; j < numcomps; j++) - { - if(parameters->cp_cinema) - { - cmptparm[j].prec = 12; - cmptparm[j].bpp = 12; - } - else - { - cmptparm[j].prec = tiBps; - cmptparm[j].bpp = tiBps; - } - cmptparm[j].dx = subsampling_dx; - cmptparm[j].dy = subsampling_dy; - cmptparm[j].w = w; - cmptparm[j].h = h; - } - - image = opj_image_create(numcomps, &cmptparm[0], color_space); - - if(!image) - { - TIFFClose(tif); - return NULL; - } -/* set image offset and reference grid -*/ - image->x0 = parameters->image_offset_x0; - image->y0 = parameters->image_offset_y0; - image->x1 = !image->x0 ? (w - 1) * subsampling_dx + 1 : - image->x0 + (w - 1) * subsampling_dx + 1; - image->y1 = !image->y0 ? (h - 1) * subsampling_dy + 1 : - image->y0 + (h - 1) * subsampling_dy + 1; - - buf = _TIFFmalloc(TIFFStripSize(tif)); - - strip_size=TIFFStripSize(tif); - index = 0; - imgsize = image->comps[0].w * image->comps[0].h ; -/* Read the Image components -*/ - for(strip = 0; strip < TIFFNumberOfStrips(tif); strip++) - { - unsigned char *dat8; - int step; - tsize_t i, ssize; - ssize = TIFFReadEncodedStrip(tif, strip, buf, strip_size); - dat8 = (unsigned char*)buf; - - if(tiBps == 16) - { - step = 6 + has_alpha + has_alpha; - - for(i = 0; i < ssize; i += step) - { - if(index < imgsize) - { - image->comps[0].data[index] = ( dat8[i+1] << 8 ) | dat8[i+0]; /* R */ - image->comps[1].data[index] = ( dat8[i+3] << 8 ) | dat8[i+2]; /* G */ - image->comps[2].data[index] = ( dat8[i+5] << 8 ) | dat8[i+4]; /* B */ - if(has_alpha) - image->comps[3].data[index] = ( dat8[i+7] << 8 ) | dat8[i+6]; - - if(parameters->cp_cinema) - { -/* Rounding 16 to 12 bits -*/ - image->comps[0].data[index] = - (image->comps[0].data[index] + 0x08) >> 4 ; - image->comps[1].data[index] = - (image->comps[1].data[index] + 0x08) >> 4 ; - image->comps[2].data[index] = - (image->comps[2].data[index] + 0x08) >> 4 ; - if(has_alpha) - image->comps[3].data[index] = - (image->comps[3].data[index] + 0x08) >> 4 ; - } - index++; - } - else - break; - }/*for(i = 0)*/ - }/*if(tiBps == 16)*/ - else - if(tiBps == 8) - { - step = 3 + has_alpha; - - for(i = 0; i < ssize; i += step) - { - if(index < imgsize) - { - image->comps[0].data[index] = dat8[i+0];/* R */ - image->comps[1].data[index] = dat8[i+1];/* G */ - image->comps[2].data[index] = dat8[i+2];/* B */ - if(has_alpha) - image->comps[3].data[index] = dat8[i+3]; - - if(parameters->cp_cinema) - { -/* Rounding 8 to 12 bits -*/ - image->comps[0].data[index] = image->comps[0].data[index] << 4 ; - image->comps[1].data[index] = image->comps[1].data[index] << 4 ; - image->comps[2].data[index] = image->comps[2].data[index] << 4 ; - if(has_alpha) - image->comps[3].data[index] = image->comps[3].data[index] << 4 ; - } - index++; - }/*if(index*/ - else - break; - }/*for(i )*/ - }/*if( tiBps == 8)*/ - else - if(tiBps == 12)/* CINEMA file */ - { - step = 9; - - for(i = 0; i < ssize; i += step) - { - if((index < imgsize)&(index+1 < imgsize)) - { - image->comps[0].data[index] = ( dat8[i+0]<<4 ) |(dat8[i+1]>>4); - image->comps[1].data[index] = ((dat8[i+1]& 0x0f)<< 8) | dat8[i+2]; - - image->comps[2].data[index] = ( dat8[i+3]<<4) |(dat8[i+4]>>4); - image->comps[0].data[index+1] = ((dat8[i+4]& 0x0f)<< 8) | dat8[i+5]; - - image->comps[1].data[index+1] = ( dat8[i+6] <<4) |(dat8[i+7]>>4); - image->comps[2].data[index+1] = ((dat8[i+7]& 0x0f)<< 8) | dat8[i+8]; - - index += 2; - } - else - break; - }/*for(i )*/ - } - }/*for(strip = 0; )*/ - - _TIFFfree(buf); - TIFFClose(tif); - - return image; - }/*RGB(A)*/ - - if(tiPhoto == PHOTOMETRIC_MINISBLACK) /* GRAY(A) */ - { - numcomps = 1 + has_alpha; - color_space = CLRSPC_GRAY; - - for(j = 0; j < numcomps; ++j) - { - cmptparm[j].prec = tiBps; - cmptparm[j].bpp = tiBps; - cmptparm[j].dx = subsampling_dx; - cmptparm[j].dy = subsampling_dy; - cmptparm[j].w = w; - cmptparm[j].h = h; - } - image = opj_image_create(numcomps, &cmptparm[0], color_space); - - if(!image) - { - TIFFClose(tif); - return NULL; - } -/* set image offset and reference grid -*/ - image->x0 = parameters->image_offset_x0; - image->y0 = parameters->image_offset_y0; - image->x1 = !image->x0 ? (w - 1) * subsampling_dx + 1 : - image->x0 + (w - 1) * subsampling_dx + 1; - image->y1 = !image->y0 ? (h - 1) * subsampling_dy + 1 : - image->y0 + (h - 1) * subsampling_dy + 1; - - buf = _TIFFmalloc(TIFFStripSize(tif)); - - strip_size = TIFFStripSize(tif); - index = 0; - imgsize = image->comps[0].w * image->comps[0].h ; -/* Read the Image components -*/ - for(strip = 0; strip < TIFFNumberOfStrips(tif); strip++) - { - unsigned char *dat8; - tsize_t i, ssize; - int step; - - ssize = TIFFReadEncodedStrip(tif, strip, buf, strip_size); - dat8 = (unsigned char*)buf; - - if(tiBps == 16) - { - step = 2 + has_alpha + has_alpha; - - for(i = 0; i < ssize; i += step) - { - if(index < imgsize) - { - image->comps[0].data[index] = ( dat8[i+1] << 8 ) | dat8[i+0]; - if(has_alpha) - image->comps[1].data[index] = ( dat8[i+3] << 8 ) | dat8[i+2]; - index++; - } - else - break; - }/*for(i )*/ - } - else - if(tiBps == 8) - { - step = 1 + has_alpha; - - for(i = 0; i < ssize; i += step) - { - if(index < imgsize) - { - image->comps[0].data[index] = dat8[i+0]; - if(has_alpha) - image->comps[1].data[index] = dat8[i+1]; - index++; - } - else - break; - }/*for(i )*/ - } - }/*for(strip = 0;*/ - - _TIFFfree(buf); - TIFFClose(tif); - - }/*GRAY(A)*/ - - return image; - -}/* tiftoimage() */ - -#endif /* HAVE_LIBTIFF */ - /* -->> -->> -->> -->> RAW IMAGE FORMAT diff --git a/applications/codec/convert.h b/applications/codec/convert.h index 0fb2ee6f..890c68dd 100644 --- a/applications/codec/convert.h +++ b/applications/codec/convert.h @@ -51,6 +51,17 @@ typedef struct raw_cparameters { void clip_component(opj_image_comp_t* component, int precision); void scale_component(opj_image_comp_t* component, int precision); +/* planar / interleaved conversions */ +typedef void (* convert_32s_CXPX)(const int* pSrc, int* const* pDst, size_t length); +extern const convert_32s_CXPX convert_32s_CXPX_LUT[5]; +typedef void (* convert_32s_PXCX)(int const* const* pSrc, int* pDst, size_t length, int adjust); +extern const convert_32s_PXCX convert_32s_PXCX_LUT[5]; +/* bit depth conversions */ +typedef void (* convert_XXx32s_C1R)(const unsigned char* pSrc, int* pDst, size_t length); +extern const convert_XXx32s_C1R convert_XXu32s_C1R_LUT[9]; /* up to 8bpp */ +typedef void (* convert_32sXXx_C1R)(const int* pSrc, unsigned char* pDst, size_t length); +extern const convert_32sXXx_C1R convert_32sXXu_C1R_LUT[9]; /* up to 8bpp */ + /* TGA conversion */ opj_image_t* tgatoimage(const char *filename, opj_cparameters_t *parameters); int imagetotga(opj_image_t * image, const char *outfile); diff --git a/applications/codec/converttif.c b/applications/codec/converttif.c new file mode 100644 index 00000000..999efec6 --- /dev/null +++ b/applications/codec/converttif.c @@ -0,0 +1,633 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2015, Matthieu Darbois + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "opj_config.h" + +#include +#include +#include +#include + +#ifndef HAVE_LIBTIFF +# error HAVE_LIBTIFF_NOT_DEFINED +#endif /* HAVE_LIBTIFF */ + +#include +#include "openjpeg.h" +#include "convert.h" + +/* -->> -->> -->> -->> + + TIFF IMAGE FORMAT + + <<-- <<-- <<-- <<-- */ + +static void tif_32sto10u(const int32* pSrc, uint8* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)3U); i+=4U) { + uint32 src0 = (uint32)pSrc[i+0]; + uint32 src1 = (uint32)pSrc[i+1]; + uint32 src2 = (uint32)pSrc[i+2]; + uint32 src3 = (uint32)pSrc[i+3]; + + *pDst++ = (uint8)(src0 >> 2); + *pDst++ = (uint8)(((src0 & 0x3U) << 6) | (src1 >> 4)); + *pDst++ = (uint8)(((src1 & 0xFU) << 4) | (src2 >> 6)); + *pDst++ = (uint8)(((src2 & 0x3FU) << 2) | (src3 >> 8)); + *pDst++ = (uint8)(src3); + } + + if (length & 3U) { + uint32 src0 = (uint32)pSrc[i+0]; + uint32 src1 = 0U; + uint32 src2 = 0U; + length = length & 3U; + + if (length > 1U) { + src1 = (uint32)pSrc[i+1]; + if (length > 2U) { + src2 = (uint32)pSrc[i+2]; + } + } + *pDst++ = (uint8)(src0 >> 2); + *pDst++ = (uint8)(((src0 & 0x3U) << 6) | (src1 >> 4)); + if (length > 1U) { + *pDst++ = (uint8)(((src1 & 0xFU) << 4) | (src2 >> 6)); + if (length > 2U) { + *pDst++ = (uint8)(((src2 & 0x3FU) << 2)); + } + } + } +} +static void tif_32sto12u(const int32* pSrc, uint8* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)1U); i+=2U) { + uint32 src0 = (uint32)pSrc[i+0]; + uint32 src1 = (uint32)pSrc[i+1]; + + *pDst++ = (uint8)(src0 >> 4); + *pDst++ = (uint8)(((src0 & 0xFU) << 4) | (src1 >> 8)); + *pDst++ = (uint8)(src1); + } + + if (length & 1U) { + uint32 src0 = (uint32)pSrc[i+0]; + *pDst++ = (uint8)(src0 >> 4); + *pDst++ = (uint8)(((src0 & 0xFU) << 4)); + } +} +static void tif_32sto14u(const int32* pSrc, uint8* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)3U); i+=4U) { + uint32 src0 = (uint32)pSrc[i+0]; + uint32 src1 = (uint32)pSrc[i+1]; + uint32 src2 = (uint32)pSrc[i+2]; + uint32 src3 = (uint32)pSrc[i+3]; + + *pDst++ = (uint8)(src0 >> 6); + *pDst++ = (uint8)(((src0 & 0x3FU) << 2) | (src1 >> 12)); + *pDst++ = (uint8)(src1 >> 4); + *pDst++ = (uint8)(((src1 & 0xFU) << 4) | (src2 >> 10)); + *pDst++ = (uint8)(src2 >> 2); + *pDst++ = (uint8)(((src2 & 0x3U) << 6) | (src3 >> 8)); + *pDst++ = (uint8)(src3); + } + + if (length & 3U) { + uint32 src0 = (uint32)pSrc[i+0]; + uint32 src1 = 0U; + uint32 src2 = 0U; + length = length & 3U; + + if (length > 1U) { + src1 = (uint32)pSrc[i+1]; + if (length > 2U) { + src2 = (uint32)pSrc[i+2]; + } + } + *pDst++ = (uint8)(src0 >> 6); + *pDst++ = (uint8)(((src0 & 0x3FU) << 2) | (src1 >> 12)); + if (length > 1U) { + *pDst++ = (uint8)(src1 >> 4); + *pDst++ = (uint8)(((src1 & 0xFU) << 4) | (src2 >> 10)); + if (length > 2U) { + *pDst++ = (uint8)(src2 >> 2); + *pDst++ = (uint8)(((src2 & 0x3U) << 6)); + } + } + } +} +static void tif_32sto16u(const int32* pSrc, uint16* pDst, size_t length) +{ + size_t i; + for (i = 0; i < length; ++i) { + pDst[i] = (uint16)pSrc[i]; + } +} + +int imagetotif(opj_image_t * image, const char *outfile) +{ + int width, height; + int bps,adjust, sgnd; + int tiPhoto; + TIFF *tif; + tdata_t buf; + tsize_t strip_size; + uint32 i, numcomps; + size_t rowStride; + int32* buffer32s = NULL; + int32 const* planes[4]; + convert_32s_PXCX cvtPxToCx = NULL; + convert_32sXXx_C1R cvt32sToTif = NULL; + + bps = (int)image->comps[0].prec; + planes[0] = image->comps[0].data; + + numcomps = image->numcomps; + + if (numcomps > 2U) { + tiPhoto = PHOTOMETRIC_RGB; + if (numcomps > 4U) { + numcomps = 4U; + } + } else { + tiPhoto = PHOTOMETRIC_MINISBLACK; + } + for (i = 1U; i < numcomps; ++i) { + if (image->comps[0].dx != image->comps[i].dx) { + break; + } + if (image->comps[0].dy != image->comps[i].dy) { + break; + } + if (image->comps[0].prec != image->comps[i].prec) { + break; + } + if (image->comps[0].sgnd != image->comps[i].sgnd) { + break; + } + planes[i] = image->comps[i].data; + } + if (i != numcomps) { + fprintf(stderr,"imagetotif: All components shall have the same subsampling, same bit depth.\n"); + fprintf(stderr,"\tAborting\n"); + return 1; + } + + if((bps > 16) || ((bps != 1) && (bps & 1))) bps = 0; + if(bps == 0) + { + fprintf(stderr,"imagetotif: Bits=%d, Only 1, 2, 4, 6, 8, 10, 12, 14 and 16 bits implemented\n",bps); + fprintf(stderr,"\tAborting\n"); + return 1; + } + tif = TIFFOpen(outfile, "wb"); + if (!tif) + { + fprintf(stderr, "imagetotif:failed to open %s for writing\n", outfile); + return 1; + } + for (i = 0U; i < numcomps; ++i) { + clip_component(&(image->comps[i]), image->comps[0].prec); + } + cvtPxToCx = convert_32s_PXCX_LUT[numcomps]; + switch (bps) { + case 1: + case 2: + case 4: + case 6: + case 8: + cvt32sToTif = convert_32sXXu_C1R_LUT[bps]; + break; + case 10: + cvt32sToTif = tif_32sto10u; + break; + case 12: + cvt32sToTif = tif_32sto12u; + break; + case 14: + cvt32sToTif = tif_32sto14u; + break; + case 16: + cvt32sToTif = (convert_32sXXx_C1R)tif_32sto16u; + break; + default: + /* never here */ + break; + } + sgnd = (int)image->comps[0].sgnd; + adjust = sgnd ? 1 << (image->comps[0].prec - 1) : 0; + width = (int)image->comps[0].w; + height = (int)image->comps[0].h; + + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, numcomps); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, tiPhoto); + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1); + + strip_size = TIFFStripSize(tif); + rowStride = ((size_t)width * numcomps * (size_t)bps + 7U) / 8U; + if (rowStride != (size_t)strip_size) { + fprintf(stderr, "Invalid TIFF strip size\n"); + TIFFClose(tif); + return 1; + } + buf = _TIFFmalloc(strip_size); + if (buf == NULL) { + TIFFClose(tif); + return 1; + } + buffer32s = (int32 *)malloc((size_t)width * numcomps * sizeof(int32)); + if (buffer32s == NULL) { + _TIFFfree(buf); + TIFFClose(tif); + return 1; + } + + for (i = 0; i < image->comps[0].h; ++i) { + cvtPxToCx(planes, buffer32s, (size_t)width, adjust); + cvt32sToTif(buffer32s, (uint8 *)buf, (size_t)width * numcomps); + (void)TIFFWriteEncodedStrip(tif, i, (void*)buf, strip_size); + planes[0] += width; + planes[1] += width; + planes[2] += width; + planes[3] += width; + } + _TIFFfree((void*)buf); + TIFFClose(tif); + free(buffer32s); + + return 0; +}/* imagetotif() */ + +static void tif_10uto32s(const uint8* pSrc, int32* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)3U); i+=4U) { + uint32 val0 = *pSrc++; + uint32 val1 = *pSrc++; + uint32 val2 = *pSrc++; + uint32 val3 = *pSrc++; + uint32 val4 = *pSrc++; + + pDst[i+0] = (int32)((val0 << 2) | (val1 >> 6)); + pDst[i+1] = (int32)(((val1 & 0x3FU) << 4) | (val2 >> 4)); + pDst[i+2] = (int32)(((val2 & 0xFU) << 6) | (val3 >> 2)); + pDst[i+3] = (int32)(((val3 & 0x3U) << 8) | val4); + + } + if (length & 3U) { + uint32 val0 = *pSrc++; + uint32 val1 = *pSrc++; + length = length & 3U; + pDst[i+0] = (int32)((val0 << 2) | (val1 >> 6)); + + if (length > 1U) { + uint32 val2 = *pSrc++; + pDst[i+1] = (int32)(((val1 & 0x3FU) << 4) | (val2 >> 4)); + if (length > 2U) { + uint32 val3 = *pSrc++; + pDst[i+2] = (int32)(((val2 & 0xFU) << 6) | (val3 >> 2)); + } + } + } +} +static void tif_12uto32s(const uint8* pSrc, int32* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)1U); i+=2U) { + uint32 val0 = *pSrc++; + uint32 val1 = *pSrc++; + uint32 val2 = *pSrc++; + + pDst[i+0] = (int32)((val0 << 4) | (val1 >> 4)); + pDst[i+1] = (int32)(((val1 & 0xFU) << 8) | val2); + } + if (length & 1U) { + uint32 val0 = *pSrc++; + uint32 val1 = *pSrc++; + pDst[i+0] = (int32)((val0 << 4) | (val1 >> 4)); + } +} +static void tif_14uto32s(const uint8* pSrc, int32* pDst, size_t length) +{ + size_t i; + for (i = 0; i < (length & ~(size_t)3U); i+=4U) { + uint32 val0 = *pSrc++; + uint32 val1 = *pSrc++; + uint32 val2 = *pSrc++; + uint32 val3 = *pSrc++; + uint32 val4 = *pSrc++; + uint32 val5 = *pSrc++; + uint32 val6 = *pSrc++; + + pDst[i+0] = (int32)((val0 << 6) | (val1 >> 2)); + pDst[i+1] = (int32)(((val1 & 0x3U) << 12) | (val2 << 4) | (val3 >> 4)); + pDst[i+2] = (int32)(((val3 & 0xFU) << 10) | (val4 << 2) | (val5 >> 6)); + pDst[i+3] = (int32)(((val5 & 0x3FU) << 8) | val6); + + } + if (length & 3U) { + uint32 val0 = *pSrc++; + uint32 val1 = *pSrc++; + length = length & 3U; + pDst[i+0] = (int32)((val0 << 6) | (val1 >> 2)); + + if (length > 1U) { + uint32 val2 = *pSrc++; + uint32 val3 = *pSrc++; + pDst[i+1] = (int32)(((val1 & 0x3U) << 12) | (val2 << 4) | (val3 >> 4)); + if (length > 2U) { + uint32 val4 = *pSrc++; + uint32 val5 = *pSrc++; + pDst[i+2] = (int32)(((val3 & 0xFU) << 10) | (val4 << 2) | (val5 >> 6)); + } + } + } +} + +/* seems that libtiff decodes this to machine endianness */ +static void tif_16uto32s(const uint16* pSrc, int32* pDst, size_t length) +{ + size_t i; + for (i = 0; i < length; i++) { + pDst[i] = pSrc[i]; + } +} + +/* + * libtiff/tif_getimage.c : 1,2,4,8,16 bitspersample accepted + * CINEMA : 12 bit precision + */ +opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters) +{ + int subsampling_dx = parameters->subsampling_dx; + int subsampling_dy = parameters->subsampling_dy; + TIFF *tif; + tdata_t buf; + tstrip_t strip; + tsize_t strip_size; + int j, currentPlane, numcomps = 0, w, h; + OPJ_COLOR_SPACE color_space = CLRSPC_UNKNOWN; + opj_image_cmptparm_t cmptparm[4]; /* RGBA */ + opj_image_t *image = NULL; + int has_alpha = 0; + unsigned short tiBps, tiPhoto, tiSf, tiSpp, tiPC; + unsigned int tiWidth, tiHeight; + opj_bool is_cinema = (parameters->cp_cinema != OFF) ? OPJ_TRUE : OPJ_FALSE; + convert_XXx32s_C1R cvtTifTo32s = NULL; + convert_32s_CXPX cvtCxToPx = NULL; + int32* buffer32s = NULL; + int32* planes[4]; + size_t rowStride; + + tif = TIFFOpen(filename, "r"); + + if(!tif) + { + fprintf(stderr, "tiftoimage:Failed to open %s for reading\n", filename); + return 0; + } + tiBps = tiPhoto = tiSf = tiSpp = tiPC = 0; + tiWidth = tiHeight = 0; + + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &tiWidth); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &tiHeight); + TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &tiBps); + TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &tiSf); + TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &tiSpp); + TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &tiPhoto); + TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &tiPC); + w= (int)tiWidth; + h= (int)tiHeight; + + if((tiBps > 16U) || ((tiBps != 1U) && (tiBps & 1U))) { + fprintf(stderr,"tiftoimage: Bits=%d, Only 1, 2, 4, 6, 8, 10, 12, 14 and 16 bits implemented\n",tiBps); + fprintf(stderr,"\tAborting\n"); + TIFFClose(tif); + return NULL; + } + if(tiPhoto != PHOTOMETRIC_MINISBLACK && tiPhoto != PHOTOMETRIC_RGB) { + fprintf(stderr,"tiftoimage: Bad color format %d.\n\tOnly RGB(A) and GRAY(A) has been implemented\n",(int) tiPhoto); + fprintf(stderr,"\tAborting\n"); + TIFFClose(tif); + return NULL; + } + + switch (tiBps) { + case 1: + case 2: + case 4: + case 6: + case 8: + cvtTifTo32s = convert_XXu32s_C1R_LUT[tiBps]; + break; + /* others are specific to TIFF */ + case 10: + cvtTifTo32s = tif_10uto32s; + break; + case 12: + cvtTifTo32s = tif_12uto32s; + break; + case 14: + cvtTifTo32s = tif_14uto32s; + break; + case 16: + cvtTifTo32s = (convert_XXx32s_C1R)tif_16uto32s; + break; + default: + /* never here */ + break; + } + + {/* From: tiff-4.0.x/libtiff/tif_getimage.c : */ + uint16* sampleinfo; + uint16 extrasamples; + + TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, + &extrasamples, &sampleinfo); + + if(extrasamples >= 1) + { + switch(sampleinfo[0]) + { + case EXTRASAMPLE_UNSPECIFIED: + /* Workaround for some images without correct info about alpha channel + */ + if(tiSpp > 3) + has_alpha = 1; + break; + + case EXTRASAMPLE_ASSOCALPHA: /* data pre-multiplied */ + case EXTRASAMPLE_UNASSALPHA: /* data not pre-multiplied */ + has_alpha = 1; + break; + } + } + else /* extrasamples == 0 */ + if(tiSpp == 4 || tiSpp == 2) has_alpha = 1; + } + + /* initialize image components */ + memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t)); + + if ((tiPhoto == PHOTOMETRIC_RGB) && (is_cinema) && (tiBps != 12U)) { + fprintf(stdout,"WARNING:\n" + "Input image bitdepth is %d bits\n" + "TIF conversion has automatically rescaled to 12-bits\n" + "to comply with cinema profiles.\n", + tiBps); + } else { + is_cinema = 0U; + } + + if(tiPhoto == PHOTOMETRIC_RGB) /* RGB(A) */ + { + numcomps = 3 + has_alpha; + color_space = CLRSPC_SRGB; + } + else if (tiPhoto == PHOTOMETRIC_MINISBLACK) /* GRAY(A) */ + { + numcomps = 1 + has_alpha; + color_space = CLRSPC_GRAY; + } + + cvtCxToPx = convert_32s_CXPX_LUT[numcomps]; + if (tiPC == PLANARCONFIG_SEPARATE) { + cvtCxToPx = convert_32s_CXPX_LUT[1]; /* override */ + tiSpp = 1U; /* consider only one sample per plane */ + } + + for(j = 0; j < numcomps; j++) + { + cmptparm[j].prec = tiBps; + cmptparm[j].bpp = tiBps; + cmptparm[j].dx = (uint32)subsampling_dx; + cmptparm[j].dy = (uint32)subsampling_dy; + cmptparm[j].w = (uint32)w; + cmptparm[j].h = (uint32)h; + } + + image = opj_image_create((uint32)numcomps, &cmptparm[0], color_space); + if(!image) + { + TIFFClose(tif); + return NULL; + } + /* set image offset and reference grid */ + image->x0 = (uint32)parameters->image_offset_x0; + image->y0 = (uint32)parameters->image_offset_y0; + image->x1 = !image->x0 ? (uint32)(w - 1) * (uint32)subsampling_dx + 1 : + image->x0 + (uint32)(w - 1) * (uint32)subsampling_dx + 1; + image->y1 = !image->y0 ? (uint32)(h - 1) * (uint32)subsampling_dy + 1 : + image->y0 + (uint32)(h - 1) * (uint32)subsampling_dy + 1; + + for(j = 0; j < numcomps; j++) + { + planes[j] = image->comps[j].data; + } + /* image->comps[numcomps - 1].alpha = (uint16)(1 - (numcomps & 1)); */ + + strip_size = TIFFStripSize(tif); + + buf = _TIFFmalloc(strip_size); + if (buf == NULL) { + TIFFClose(tif); + opj_image_destroy(image); + return NULL; + } + rowStride = ((size_t)w * tiSpp * tiBps + 7U) / 8U; + buffer32s = (int32 *)malloc((size_t)w * tiSpp * sizeof(int32)); + if (buffer32s == NULL) { + _TIFFfree(buf); + TIFFClose(tif); + opj_image_destroy(image); + return NULL; + } + + strip = 0; + currentPlane = 0; + do + { + planes[0] = image->comps[currentPlane].data; /* to manage planar data */ + h= (int)tiHeight; + /* Read the Image components */ + for(; (h > 0) && (strip < TIFFNumberOfStrips(tif)); strip++) + { + const uint8 *dat8; + size_t ssize; + + ssize = (size_t)TIFFReadEncodedStrip(tif, strip, buf, strip_size); + dat8 = (const uint8*)buf; + + while (ssize >= rowStride) { + cvtTifTo32s(dat8, buffer32s, (size_t)w * tiSpp); + cvtCxToPx(buffer32s, planes, (size_t)w); + planes[0] += w; + planes[1] += w; + planes[2] += w; + planes[3] += w; + dat8 += rowStride; + ssize -= rowStride; + h--; + } + } + currentPlane++; + } while ((tiPC == PLANARCONFIG_SEPARATE) && (currentPlane < numcomps)); + + free(buffer32s); + _TIFFfree(buf); + TIFFClose(tif); + + if (is_cinema) { + for (j=0; j < numcomps; ++j) { + scale_component(&(image->comps[j]), 12); + } + + } + return image; + +}/* tiftoimage() */ + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b02b4d9e..2a13affa 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -11,7 +11,7 @@ include_directories( # First thing define the common source: set(compare_images_SRCS compare_images.c ${OPENJPEG_SOURCE_DIR}/applications/codec/convert.c -# ${OPENJPEG_SOURCE_DIR}/applications/codec/converttif.c + ${OPENJPEG_SOURCE_DIR}/applications/codec/converttif.c # ${OPENJPEG_SOURCE_DIR}/applications/common/opj_getopt.c ) diff --git a/tests/nonregression/test_suite.ctest.in b/tests/nonregression/test_suite.ctest.in index af57b15e..973fb476 100644 --- a/tests/nonregression/test_suite.ctest.in +++ b/tests/nonregression/test_suite.ctest.in @@ -81,32 +81,31 @@ image_to_j2k -i @INPUT_NR_PATH@/pngsuite/basn6a08.png -o @TEMP_PATH@/basn6a08.pn #image_to_j2k -i @INPUT_NR_PATH@/issue203-127x64-bgrx.bmp -o @TEMP_PATH@/issue203-127x64-bgrx.bmp.jp2 # issue 322 limited tif support -# No plan to fix this in 1.5 branch right now -#image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-01.tif -o @TEMP_PATH@/flower-minisblack-01.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-02.tif -o @TEMP_PATH@/flower-minisblack-02.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-04.tif -o @TEMP_PATH@/flower-minisblack-04.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-06.tif -o @TEMP_PATH@/flower-minisblack-06.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-08.tif -o @TEMP_PATH@/flower-minisblack-08.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-10.tif -o @TEMP_PATH@/flower-minisblack-10.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-12.tif -o @TEMP_PATH@/flower-minisblack-12.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-14.tif -o @TEMP_PATH@/flower-minisblack-14.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-16.tif -o @TEMP_PATH@/flower-minisblack-16.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-02.tif -o @TEMP_PATH@/flower-rgb-contig-02.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-04.tif -o @TEMP_PATH@/flower-rgb-contig-04.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-08.tif -o @TEMP_PATH@/flower-rgb-contig-08.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-10.tif -o @TEMP_PATH@/flower-rgb-contig-10.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-12.tif -o @TEMP_PATH@/flower-rgb-contig-12.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-14.tif -o @TEMP_PATH@/flower-rgb-contig-14.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-16.tif -o @TEMP_PATH@/flower-rgb-contig-16.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-02.tif -o @TEMP_PATH@/flower-rgb-planar-02.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-04.tif -o @TEMP_PATH@/flower-rgb-planar-04.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-08.tif -o @TEMP_PATH@/flower-rgb-planar-08.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-10.tif -o @TEMP_PATH@/flower-rgb-planar-10.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-12.tif -o @TEMP_PATH@/flower-rgb-planar-12.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-14.tif -o @TEMP_PATH@/flower-rgb-planar-14.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-16.tif -o @TEMP_PATH@/flower-rgb-planar-16.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/basn6a08.tif -o @TEMP_PATH@/basn6a08.tif.jp2 -#image_to_j2k -i @INPUT_NR_PATH@/basn4a08.tif -o @TEMP_PATH@/basn4a08.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-01.tif -o @TEMP_PATH@/flower-minisblack-01.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-02.tif -o @TEMP_PATH@/flower-minisblack-02.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-04.tif -o @TEMP_PATH@/flower-minisblack-04.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-06.tif -o @TEMP_PATH@/flower-minisblack-06.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-08.tif -o @TEMP_PATH@/flower-minisblack-08.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-10.tif -o @TEMP_PATH@/flower-minisblack-10.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-12.tif -o @TEMP_PATH@/flower-minisblack-12.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-14.tif -o @TEMP_PATH@/flower-minisblack-14.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-minisblack-16.tif -o @TEMP_PATH@/flower-minisblack-16.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-02.tif -o @TEMP_PATH@/flower-rgb-contig-02.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-04.tif -o @TEMP_PATH@/flower-rgb-contig-04.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-08.tif -o @TEMP_PATH@/flower-rgb-contig-08.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-10.tif -o @TEMP_PATH@/flower-rgb-contig-10.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-12.tif -o @TEMP_PATH@/flower-rgb-contig-12.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-14.tif -o @TEMP_PATH@/flower-rgb-contig-14.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-contig-16.tif -o @TEMP_PATH@/flower-rgb-contig-16.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-02.tif -o @TEMP_PATH@/flower-rgb-planar-02.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-04.tif -o @TEMP_PATH@/flower-rgb-planar-04.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-08.tif -o @TEMP_PATH@/flower-rgb-planar-08.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-10.tif -o @TEMP_PATH@/flower-rgb-planar-10.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-12.tif -o @TEMP_PATH@/flower-rgb-planar-12.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-14.tif -o @TEMP_PATH@/flower-rgb-planar-14.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/flower-rgb-planar-16.tif -o @TEMP_PATH@/flower-rgb-planar-16.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/basn6a08.tif -o @TEMP_PATH@/basn6a08.tif.jp2 +image_to_j2k -i @INPUT_NR_PATH@/basn4a08.tif -o @TEMP_PATH@/basn4a08.tif.jp2 # issue 536 (PNG images are always read as RGB(A) images) + issue 264 (convert.c is unmaintainable) # Test all images from pngsuite @@ -414,50 +413,50 @@ j2k_to_image -i @INPUT_NR_PATH@/issue495.jp2 -o @TEMP_PATH@/issue495.jp2.pgx # #j2k_to_image -i @INPUT_CONF_PATH@/p1_01.j2k -o @TEMP_PATH@/p1_01_4.j2k.png -d 100,80,200,150 # #j2k_to_image -i @INPUT_CONF_PATH@/p1_01.j2k -o @TEMP_PATH@/p1_01_5.j2k.png -d 150,20,200,50 -# # issue 322 limited tif support -# # GRAYSCALE -# j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-1.tif -p 1S -# j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-2.tif -p 2S -# j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-4.tif -p 4S -# j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-6.tif -p 6S -# j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-8.tif -p 8S -# j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-10.tif -p 10S -# j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-12.tif -p 12S -# j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-14.tif -p 14S -# j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-16.tif -p 16S -# # GRAYSCALE ALPHA -# j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-1.tif -p 1S -# j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-2.tif -p 2S -# j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-4.tif -p 4S -# j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-6.tif -p 6S -# j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-8.tif -p 8S -# j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-10.tif -p 10S -# j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-12.tif -p 12S -# j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-14.tif -p 14S -# j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-16.tif -p 16S -# # RGB -# j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-1.tif -p 1S -# j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-2.tif -p 2S -# j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-4.tif -p 4S -# j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-6.tif -p 6S -# j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-8.tif -p 8S -# j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-10.tif -p 10S -# j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-12.tif -p 12S -# j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-14.tif -p 14S -# j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-16.tif -p 16S -# # RGBA -# j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-1.tif -p 1S -# j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-2.tif -p 2S -# j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-4.tif -p 4S -# j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-6.tif -p 6S -# j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-8.tif -p 8S -# j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-10.tif -p 10S -# j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-12.tif -p 12S -# j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-14.tif -p 14S -# j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-16.tif -p 16S - # < NOT IMPLEMENTED +# issue 322 limited tif support +# GRAYSCALE +j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-1.tif -p 1S +j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-2.tif -p 2S +j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-4.tif -p 4S +j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-6.tif -p 6S +j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-8.tif -p 8S +j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-10.tif -p 10S +j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-12.tif -p 12S +j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-14.tif -p 14S +j2k_to_image -i @INPUT_CONF_PATH@/a1_mono.j2c -o @TEMP_PATH@/a1_mono_tif-16.tif -p 16S +# GRAYSCALE ALPHA +j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-1.tif -p 1S +j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-2.tif -p 2S +j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-4.tif -p 4S +j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-6.tif -p 6S +j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-8.tif -p 8S +j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-10.tif -p 10S +j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-12.tif -p 12S +j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-14.tif -p 14S +j2k_to_image -i @INPUT_NR_PATH@/basn4a08.jp2 -o @TEMP_PATH@/basn4a08_tif-16.tif -p 16S +# RGB +j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-1.tif -p 1S +j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-2.tif -p 2S +j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-4.tif -p 4S +j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-6.tif -p 6S +j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-8.tif -p 8S +j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-10.tif -p 10S +j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-12.tif -p 12S +j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-14.tif -p 14S +j2k_to_image -i @INPUT_CONF_PATH@/p0_14.j2k -o @TEMP_PATH@/p0_14_tif-16.tif -p 16S +# RGBA +j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-1.tif -p 1S +j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-2.tif -p 2S +j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-4.tif -p 4S +j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-6.tif -p 6S +j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-8.tif -p 8S +j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-10.tif -p 10S +j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-12.tif -p 12S +j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-14.tif -p 14S +j2k_to_image -i @INPUT_NR_PATH@/basn6a08.jp2 -o @TEMP_PATH@/basn6a08_tif-16.tif -p 16S + #issue 235 CMAP outside jp2h box. CMAP is buggy j2k_to_image -i @INPUT_NR_PATH@/issue235.jp2 -o @TEMP_PATH@/issue235.jp2.pgx