diff --git a/kimgio/jp2.cpp b/kimgio/jp2.cpp index 948eef3fd..5f087e228 100644 --- a/kimgio/jp2.cpp +++ b/kimgio/jp2.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -36,10 +37,6 @@ * - Doesn't support OPJ_CODEC_J2K. * - Doesn't support subsampling. * - Doesn't read ICC profiles. - * - Doesn't write images. - * - * Improvements: - * - kimgio_jp2_read_srgba/kimgio_jp2_read_grayscale could be merged. * * The API documentation is rather poor, so good references on how to use OpenJPEG * are the tools provided by OpenJPEG, such as 'opj_decompress': @@ -91,48 +88,7 @@ static void kimgio_jp2_warn_handler(const char *message, void *data) kdWarning(kCategory) << "Warning decoding JP2 image: " << message; } -static void kimgio_jp2_read_srgba(TQImage &image, const KIMGJP2Wrapper &jp2) -{ - const int height = image.height(); - const int width = image.width(); - - unsigned char alphaMask = 0x0; - - for (int row = 0; row < height; row++) - { - for (int col = 0; col < width; col++) - { - const int offset = row * width + col; - OPJ_INT32 r, g, b, a = 0xFF; - - // Convert to unsigned - r = jp2.image->comps[0].data[offset]; - r += (jp2.image->comps[0].sgnd ? 1 << (jp2.image->comps[0].prec - 1) : 0); - - g = jp2.image->comps[1].data[offset]; - g += (jp2.image->comps[0].sgnd ? 1 << (jp2.image->comps[1].prec - 1) : 0); - - b = jp2.image->comps[2].data[offset]; - b += (jp2.image->comps[2].sgnd ? 1 << (jp2.image->comps[2].prec - 1) : 0); - - if (jp2.image->numcomps > 3 && jp2.image->comps[3].alpha) - { - a = jp2.image->comps[3].data[offset]; - a += (jp2.image->comps[3].sgnd ? 1 << (jp2.image->comps[3].prec - 1) : 0); - } - - image.setPixel(col, row, tqRgba(r, g, b, a)); - alphaMask |= (255 - a); - } - } - - if (alphaMask != 0x0) - { - image.setAlphaBuffer(true); - } -} - -static void kimgio_jp2_read_grayscale(TQImage &image, const KIMGJP2Wrapper &jp2) +static void kimgio_jp2_read_image(TQImage &image, const KIMGJP2Wrapper &jp2) { const int height = image.height(); const int width = image.width(); @@ -144,20 +100,63 @@ static void kimgio_jp2_read_grayscale(TQImage &image, const KIMGJP2Wrapper &jp2) for (int col = 0; col < width; col++) { const int offset = row * width + col; - OPJ_INT32 g, a = 0xFF; + uint8_t rgba[4] = { 0x00, 0x00, 0x00, 0xFF }; - // Convert to unsigned - g = jp2.image->comps[0].data[offset]; - g += (jp2.image->comps[0].sgnd ? (1 << jp2.image->comps[0].prec - 1) : 0); - - if (jp2.image->numcomps > 1 && jp2.image->comps[1].alpha) + for (int comp = 0; comp < jp2.image->numcomps; comp++) { - a = jp2.image->comps[1].data[offset]; - a = (jp2.image->comps[1].sgnd ? (1 << jp2.image->comps[1].prec - 1) : 0); + OPJ_INT32 value = jp2.image->comps[comp].data[offset]; + value += (jp2.image->comps[comp].sgnd ? (1 << jp2.image->comps[comp].prec - 1) : 0); + value = kClamp(value, 0, 255); + + switch (comp) + { + case 0: + { + // Red or Grayscale + rgba[0] = value; + rgba[1] = value; + rgba[2] = value; + break; + } + case 1: + { + if ((jp2.image->color_space == OPJ_CLRSPC_GRAY) && + (jp2.image->comps[comp].alpha != 0)) + { + // Grayscale with Alpha + rgba[3] = value; + } + else + { + // Green + rgba[1] = value; + } + break; + } + case 2: + { + // Blue + rgba[2] = value; + break; + } + case 3: + { + // Alpha? + if (jp2.image->comps[comp].alpha != 0) + { + rgba[3] = value; + } + break; + } + default: + { + break; + } + } } - image.setPixel(col, row, tqRgba(g, g, g, a)); - alphaMask |= (255 - a); + image.setPixel(col, row, tqRgba(rgba[0], rgba[1], rgba[2], rgba[3])); + alphaMask |= (255 - rgba[3]); } } @@ -297,13 +296,9 @@ TDE_EXPORT void kimgio_jp2_read(TQImageIO* io) switch (jp2.image->color_space) { case OPJ_CLRSPC_SRGB: - { - kimgio_jp2_read_srgba(image, jp2); - break; - } case OPJ_CLRSPC_GRAY: { - kimgio_jp2_read_grayscale(image, jp2); + kimgio_jp2_read_image(image, jp2); break; } default: