jasper-software / jasper

Official Repository for the JasPer Image Coding Toolkit
http://www.ece.uvic.ca/~mdadams/jasper
Other
217 stars 103 forks source link

Can't encode jpc with YCbCr input data #346

Closed mixern6 closed 1 year ago

mixern6 commented 1 year ago

Hi, I have an image in YUV format (https://i.stack.imgur.com/2QNDQ.jpg), which Id' like to encode as YCbCr jpc. When I set the color space to JAS_CLRSPC_SYCBCR it still saves the image as if it is set to be JAS_CLRSPC_SRGB. Here is the code I use:

QImage im("C:/test/2QNDQ.jpg");
im.convertTo(QImage::Format_RGB888); // just make sure each component takes 8 bits.

jas_conf_clear();
jas_conf_set_max_mem_usage(JAS_DEFAULT_MAX_MEM_USAGE);
if (jas_init_library()) {
    qDebug("Jasper library initialization failed");
}
if (jas_init_thread()) {
    jas_cleanup_library();
    qDebug("Jasper thread initialization failed");
}

jas_image_cmptparm_t m_cmptparms[3];

jas_image_cmptparm_t *cmptparm = m_cmptparms;
uint_fast16_t numcmpts = 3;

for (uint_fast16_t cmptno = 0; cmptno < numcmpts; ++cmptno, ++cmptparm)
{
    cmptparm->tlx = 0;
    cmptparm->tly = 0;
    cmptparm->width = im.width();
    cmptparm->height = im.height();
    cmptparm->prec = 8;
    cmptparm->sgnd = false;
}

m_cmptparms[0].hstep = 1;
m_cmptparms[0].vstep = 1;
m_cmptparms[1].hstep = 1;
m_cmptparms[1].vstep = 1;
m_cmptparms[2].hstep = 1;
m_cmptparms[2].vstep = 1;

jas_image_t* m_image = jas_image_create(numcmpts, m_cmptparms, JAS_CLRSPC_SYCBCR);
if(!m_image)
{
    throw "Failed to create image";
}
jas_image_setcmpttype(m_image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_Y));
jas_image_setcmpttype(m_image, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CB));
jas_image_setcmpttype(m_image, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CR));

int bufferSize = im.width() * im.height();
long* plane = new long[bufferSize];
memset(plane, 0, bufferSize);

for(int i = 0; i < 3; i++)
{
    int size = im.width() * im.height();
    for(int j = 0; j < size ; j++)
    {
        const unsigned char* data = im.bits();
        plane[j] = data[j * 3 + i];
    }

    int res = jas_image_writecmpt2(m_image, i, 0, 0, im.width(), im.height(), plane);
    if(res < 0)
    {
        char szoutopts[255];
        sprintf_s(szoutopts,"Failed to write component %d data", i);
        throw szoutopts;
    }
}
delete[] plane;
int outfmt = jas_image_strtofmt("jpc");

jas_stream_t* stream = nullptr;
if (!(stream = jas_stream_fopen ("C:/test/image.jpc", "wb")))
{
    qDebug() << "error: cannot create stream";
    return false;
}
int res = jas_image_encode(m_image, stream, outfmt, "");

There are no errors, only this warning: "warning: color space apparently not RGB". The result image looks exactly the same as the source one if I open it in Photoshop. How can I tell jasper that the source image is in YUV format and not RGB?

osamu620 commented 1 year ago

.jpc is a codestream that does not have the information on the input/output colorspace. To specify the colorspace for the reconstructed (decoded) image, you should use .jp2 file format. The JP2 file format is box-based. It has the "colour specification box" that defines one method by which an application can interpret the colorspace of the decompressed image data.

mdadams commented 1 year ago

For the reason that Osama noted, what you are trying to do cannot work. Therefore, what you are observing is not a bug in JasPer. The warning message from JasPer is just trying to indicate that your code is doing something highly questionable and probably will not work as intended.