Exemple #1
0
static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
{
    Image
    *image;

    jas_cmprof_t
    *cm_profile;

    jas_iccprof_t
    *icc_profile;

    jas_image_t
    *jp2_image;

    jas_matrix_t
    *pixels[4];

    jas_stream_t
    *jp2_stream;

    MagickBooleanType
    status;

    QuantumAny
    pixel,
    range[4];

    register ssize_t
    i,
    x;

    register Quantum
    *q;

    size_t
    maximum_component_depth,
    number_components,
    x_step[4],
    y_step[4];

    ssize_t
    components[4],
               y;

    /*
      Open image file.
    */
    assert(image_info != (const ImageInfo *) NULL);
    assert(image_info->signature == MagickSignature);
    if (image_info->debug != MagickFalse)
        (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
                              image_info->filename);
    assert(exception != (ExceptionInfo *) NULL);
    assert(exception->signature == MagickSignature);
    image=AcquireImage(image_info,exception);
    status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    if (status == MagickFalse)
    {
        image=DestroyImageList(image);
        return((Image *) NULL);
    }
    /*
      Initialize JPEG 2000 API.
    */
    jp2_stream=JP2StreamManager(image);
    if (jp2_stream == (jas_stream_t *) NULL)
        ThrowReaderException(DelegateError,"UnableToManageJP2Stream");
    jp2_image=jas_image_decode(jp2_stream,-1,0);
    if (jp2_image == (jas_image_t *) NULL)
    {
        (void) jas_stream_close(jp2_stream);
        ThrowReaderException(DelegateError,"UnableToDecodeImageFile");
    }
    switch (jas_clrspc_fam(jas_image_clrspc(jp2_image)))
    {
    case JAS_CLRSPC_FAM_RGB:
    {
        components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_R);
        components[1]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_G);
        components[2]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_B);
        if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
        {
            (void) jas_stream_close(jp2_stream);
            jas_image_destroy(jp2_image);
            ThrowReaderException(CorruptImageError,"MissingImageChannel");
        }
        number_components=3;
        components[3]=jas_image_getcmptbytype(jp2_image,3);
        if (components[3] > 0)
        {
            image->matte=MagickTrue;
            number_components++;
        }
        break;
    }
    case JAS_CLRSPC_FAM_GRAY:
    {
        components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_GRAY_Y);
        if (components[0] < 0)
        {
            (void) jas_stream_close(jp2_stream);
            jas_image_destroy(jp2_image);
            ThrowReaderException(CorruptImageError,"MissingImageChannel");
        }
        number_components=1;
        break;
    }
    case JAS_CLRSPC_FAM_YCBCR:
    {
        components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_Y);
        components[1]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_CB);
        components[2]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_CR);
        if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
        {
            (void) jas_stream_close(jp2_stream);
            jas_image_destroy(jp2_image);
            ThrowReaderException(CorruptImageError,"MissingImageChannel");
        }
        number_components=3;
        components[3]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_UNKNOWN);
        if (components[3] > 0)
        {
            image->matte=MagickTrue;
            number_components++;
        }
        image->colorspace=YCbCrColorspace;
        break;
    }
    default:
    {
        (void) jas_stream_close(jp2_stream);
        jas_image_destroy(jp2_image);
        ThrowReaderException(CoderError,"ColorspaceModelIsNotSupported");
    }
    }
    image->columns=jas_image_width(jp2_image);
    image->rows=jas_image_height(jp2_image);
    image->compression=JPEG2000Compression;
    if (number_components == 1)
        image->colorspace=GRAYColorspace;
    for (i=0; i < (ssize_t) number_components; i++)
    {
        size_t
        height,
        width;

        width=(size_t) (jas_image_cmptwidth(jp2_image,components[i])*
                        jas_image_cmpthstep(jp2_image,components[i]));
        height=(size_t) (jas_image_cmptheight(jp2_image,components[i])*
                         jas_image_cmptvstep(jp2_image,components[i]));
        x_step[i]=(unsigned int) jas_image_cmpthstep(jp2_image,components[i]);
        y_step[i]=(unsigned int) jas_image_cmptvstep(jp2_image,components[i]);
        if ((width != image->columns) || (height != image->rows) ||
                (jas_image_cmpttlx(jp2_image,components[i]) != 0) ||
                (jas_image_cmpttly(jp2_image,components[i]) != 0) ||
                (x_step[i] != 1) || (y_step[i] != 1) ||
                (jas_image_cmptsgnd(jp2_image,components[i]) != MagickFalse))
        {
            (void) jas_stream_close(jp2_stream);
            jas_image_destroy(jp2_image);
            ThrowReaderException(CoderError,"IrregularChannelGeometryNotSupported");
        }
    }
    /*
      Convert JPEG 2000 pixels.
    */
    image->matte=number_components > 3 ? MagickTrue : MagickFalse;
    maximum_component_depth=0;
    for (i=0; i < (ssize_t) number_components; i++)
    {
        maximum_component_depth=(unsigned int) MagickMax((size_t)
                                jas_image_cmptprec(jp2_image,components[i]),(size_t)
                                maximum_component_depth);
        pixels[i]=jas_matrix_create(1,(int) (image->columns/x_step[i]));
        if (pixels[i] == (jas_matrix_t *) NULL)
        {
            for (--i; i >= 0; i--)
                jas_matrix_destroy(pixels[i]);
            jas_image_destroy(jp2_image);
            ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
        }
    }
    image->depth=maximum_component_depth;
    if (image_info->ping != MagickFalse)
    {
        (void) jas_stream_close(jp2_stream);
        jas_image_destroy(jp2_image);
        return(GetFirstImageInList(image));
    }
    for (i=0; i < (ssize_t) number_components; i++)
        range[i]=GetQuantumRange((size_t) jas_image_cmptprec(jp2_image,
                                 components[i]));
    for (y=0; y < (ssize_t) image->rows; y++)
    {
        q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
        if (q == (Quantum *) NULL)
            break;
        for (i=0; i < (ssize_t) number_components; i++)
            (void) jas_image_readcmpt(jp2_image,(short) components[i],0,
                                      (jas_image_coord_t) (y/y_step[i]),(jas_image_coord_t) (image->columns/
                                              x_step[i]),1,pixels[i]);
        switch (number_components)
        {
        case 1:
        {
            /*
              Grayscale.
            */
            for (x=0; x < (ssize_t) image->columns; x++)
            {
                pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
                SetPixelGray(image,ScaleAnyToQuantum((QuantumAny) pixel,range[0]),q);
                q+=GetPixelChannels(image);
            }
            break;
        }
        case 3:
        {
            /*
              RGB.
            */
            for (x=0; x < (ssize_t) image->columns; x++)
            {
                pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
                SetPixelRed(image,ScaleAnyToQuantum((QuantumAny) pixel,range[0]),q);
                pixel=(QuantumAny) jas_matrix_getv(pixels[1],x/x_step[1]);
                SetPixelGreen(image,ScaleAnyToQuantum((QuantumAny) pixel,range[1]),q);
                pixel=(QuantumAny) jas_matrix_getv(pixels[2],x/x_step[2]);
                SetPixelBlue(image,ScaleAnyToQuantum((QuantumAny) pixel,range[2]),q);
                q+=GetPixelChannels(image);
            }
            break;
        }
        case 4:
        {
            /*
              RGBA.
            */
            for (x=0; x < (ssize_t) image->columns; x++)
            {
                pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
                SetPixelRed(image,ScaleAnyToQuantum((QuantumAny) pixel,range[0]),q);
                pixel=(QuantumAny) jas_matrix_getv(pixels[1],x/x_step[1]);
                SetPixelGreen(image,ScaleAnyToQuantum((QuantumAny) pixel,range[1]),q);
                pixel=(QuantumAny) jas_matrix_getv(pixels[2],x/x_step[2]);
                SetPixelBlue(image,ScaleAnyToQuantum((QuantumAny) pixel,range[2]),q);
                pixel=(QuantumAny) jas_matrix_getv(pixels[3],x/x_step[3]);
                SetPixelAlpha(image,ScaleAnyToQuantum((QuantumAny) pixel,range[3]),q);
                q+=GetPixelChannels(image);
            }
            break;
        }
        }
        if (SyncAuthenticPixels(image,exception) == MagickFalse)
            break;
        status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
                                image->rows);
        if (status == MagickFalse)
            break;
    }
    cm_profile=jas_image_cmprof(jp2_image);
    icc_profile=(jas_iccprof_t *) NULL;
    if (cm_profile != (jas_cmprof_t *) NULL)
        icc_profile=jas_iccprof_createfromcmprof(cm_profile);
    if (icc_profile != (jas_iccprof_t *) NULL)
    {
        jas_stream_t
        *icc_stream;

        icc_stream=jas_stream_memopen(NULL,0);
        if ((icc_stream != (jas_stream_t *) NULL) &&
                (jas_iccprof_save(icc_profile,icc_stream) == 0) &&
                (jas_stream_flush(icc_stream) == 0))
        {
            StringInfo
            *icc_profile,
            *profile;

            jas_stream_memobj_t
            *blob;

            /*
              Extract the icc profile, handle errors without much noise.
            */
            blob=(jas_stream_memobj_t *) icc_stream->obj_;
            if (image->debug != MagickFalse)
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                                      "Profile: ICC, %.20g bytes",(double) blob->len_);
            profile=BlobToStringInfo(blob->buf_,blob->len_);
            if (profile == (StringInfo *) NULL)
                ThrowReaderException(CorruptImageError,"MemoryAllocationFailed");
            icc_profile=(StringInfo *) GetImageProfile(image,"icc");
            if (icc_profile == (StringInfo *) NULL)
                (void) SetImageProfile(image,"icc",profile,exception);
            else
                (void) ConcatenateStringInfo(icc_profile,profile);
            profile=DestroyStringInfo(profile);
            (void) jas_stream_close(icc_stream);
        }
    }
    (void) jas_stream_close(jp2_stream);
    jas_image_destroy(jp2_image);
    for (i=0; i < (ssize_t) number_components; i++)
        jas_matrix_destroy(pixels[i]);
    return(GetFirstImageInList(image));
}
Exemple #2
0
bool JP2KLoader::load(const QString& filePath, DImgLoaderObserver* observer)
{
    readMetadata(filePath, DImg::JPEG);

    FILE* file = fopen(QFile::encodeName(filePath), "rb");

    if (!file)
    {
        loadingFailed();
        return false;
    }

    unsigned char header[9];

    if (fread(&header, 9, 1, file) != 1)
    {
        fclose(file);
        loadingFailed();
        return false;
    }

    unsigned char jp2ID[5] = { 0x6A, 0x50, 0x20, 0x20, 0x0D, };
    unsigned char jpcID[2] = { 0xFF, 0x4F };

    if (memcmp(&header[4], &jp2ID, 5) != 0 &&
        memcmp(&header,    &jpcID, 2) != 0)
    {
        // not a jpeg2000 file
        fclose(file);
        loadingFailed();
        return false;
    }

    fclose(file);

    imageSetAttribute("format", "JP2K");

    if (!(m_loadFlags & LoadImageData) && !(m_loadFlags & LoadICCData))
    {
        // libjasper will load the full image in memory already when calling jas_image_decode.
        // This is bad when scanning. See bugs 215458 and 195583.
        //FIXME: Use Exiv2 or OpenJPEG to extract this info
        DMetadata metadata(filePath);
        QSize size = metadata.getImageDimensions();

        if (size.isValid())
        {
            imageWidth() = size.width();
            imageHeight() = size.height();
        }

        return true;
    }

    // -------------------------------------------------------------------
    // Initialize JPEG 2000 API.

    register long  i, x, y;
    int            components[4];
    unsigned int   maximum_component_depth, scale[4], x_step[4], y_step[4];
    unsigned long  number_components;

    jas_image_t*  jp2_image   = 0;
    jas_stream_t* jp2_stream  = 0;
    jas_matrix_t* pixels[4];

    int init = jas_init();

    if (init != 0)
    {
        kDebug() << "Unable to init JPEG2000 decoder";
        loadingFailed();
        return false;
    }

    jp2_stream = jas_stream_fopen(QFile::encodeName(filePath), "rb");

    if (jp2_stream == 0)
    {
        kDebug() << "Unable to open JPEG2000 stream";
        loadingFailed();
        return false;
    }

    jp2_image = jas_image_decode(jp2_stream, -1, 0);

    if (jp2_image == 0)
    {
        jas_stream_close(jp2_stream);
        kDebug() << "Unable to decode JPEG2000 image";
        loadingFailed();
        return false;
    }

    jas_stream_close(jp2_stream);

    // some pseudo-progress
    if (observer)
    {
        observer->progressInfo(m_image, 0.1F);
    }

    // -------------------------------------------------------------------
    // Check color space.

    int colorModel;

    switch (jas_clrspc_fam(jas_image_clrspc(jp2_image)))
    {
        case JAS_CLRSPC_FAM_RGB:
        {
            components[0] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_RGB_R);
            components[1] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_RGB_G);
            components[2] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_RGB_B);

            if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
            {
                jas_image_destroy(jp2_image);
                kDebug() << "Error parsing JPEG2000 image : Missing Image Channel";
                loadingFailed();
                return false;
            }

            number_components = 3;
            components[3]     = jas_image_getcmptbytype(jp2_image, 3);

            if (components[3] > 0)
            {
                m_hasAlpha = true;
                ++number_components;
            }

            colorModel = DImg::RGB;
            break;
        }
        case JAS_CLRSPC_FAM_GRAY:
        {
            components[0] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_GRAY_Y);

            if (components[0] < 0)
            {
                jas_image_destroy(jp2_image);
                kDebug() << "Error parsing JP2000 image : Missing Image Channel";
                loadingFailed();
                return false;
            }

            number_components = 1;
            colorModel        = DImg::GRAYSCALE;
            break;
        }
        case JAS_CLRSPC_FAM_YCBCR:
        {
            components[0] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_YCBCR_Y);
            components[1] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_YCBCR_CB);
            components[2] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_YCBCR_CR);

            if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
            {
                jas_image_destroy(jp2_image);
                kDebug() << "Error parsing JP2000 image : Missing Image Channel";
                loadingFailed();
                return false;
            }

            number_components = 3;
            components[3]     = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_UNKNOWN);

            if (components[3] > 0)
            {
                m_hasAlpha = true;
                ++number_components;
            }

            // FIXME : image->colorspace=YCbCrColorspace;
            colorModel = DImg::YCBCR;
            break;
        }
        default:
        {
            jas_image_destroy(jp2_image);
            kDebug() << "Error parsing JP2000 image : Colorspace Model Is Not Supported";
            loadingFailed();
            return false;
        }
    }

    // -------------------------------------------------------------------
    // Check image geometry.

    imageWidth()  = jas_image_width(jp2_image);
    imageHeight() = jas_image_height(jp2_image);

    for (i = 0; i < (long)number_components; ++i)
    {
        if ((((jas_image_cmptwidth(jp2_image, components[i])*
               jas_image_cmpthstep(jp2_image, components[i])) != (long)imageWidth()))  ||
            (((jas_image_cmptheight(jp2_image, components[i])*
               jas_image_cmptvstep(jp2_image, components[i])) != (long)imageHeight())) ||
            (jas_image_cmpttlx(jp2_image, components[i]) != 0)                      ||
            (jas_image_cmpttly(jp2_image, components[i]) != 0)                      ||
            (jas_image_cmptsgnd(jp2_image, components[i]) != false))
        {
            jas_image_destroy(jp2_image);
            kDebug() << "Error parsing JPEG2000 image : Irregular Channel Geometry Not Supported";
            loadingFailed();
            return false;
        }

        x_step[i] = jas_image_cmpthstep(jp2_image, components[i]);
        y_step[i] = jas_image_cmptvstep(jp2_image, components[i]);
    }

    // -------------------------------------------------------------------
    // Get image format.

    m_hasAlpha              = number_components > 3;
    maximum_component_depth = 0;

    for (i = 0; i < (long)number_components; ++i)
    {
        maximum_component_depth = qMax((long)jas_image_cmptprec(jp2_image,components[i]),
                                       (long)maximum_component_depth);
        pixels[i] = jas_matrix_create(1, ((unsigned int)imageWidth())/x_step[i]);

        if (!pixels[i])
        {
            jas_image_destroy(jp2_image);
            kDebug() << "Error decoding JPEG2000 image data : Memory Allocation Failed";
            loadingFailed();
            return false;
        }
    }

    if (maximum_component_depth > 8)
    {
        m_sixteenBit = true;
    }

    for (i = 0 ; i < (long)number_components ; ++i)
    {
        scale[i] = 1;
        int prec = jas_image_cmptprec(jp2_image, components[i]);

        if (m_sixteenBit && prec < 16)
        {
            scale[i] = (1 << (16 - jas_image_cmptprec(jp2_image, components[i])));
        }
    }

    // -------------------------------------------------------------------
    // Get image data.

    uchar* data = 0;

    if (m_loadFlags & LoadImageData)
    {
        if (m_sixteenBit)          // 16 bits image.
        {
            data = new_failureTolerant(imageWidth()*imageHeight()*8);
        }
        else
        {
            data = new_failureTolerant(imageWidth()*imageHeight()*4);
        }

        if (!data)
        {
            kDebug() << "Error decoding JPEG2000 image data : Memory Allocation Failed";
            jas_image_destroy(jp2_image);

            for (i = 0 ; i < (long)number_components ; ++i)
            {
                jas_matrix_destroy(pixels[i]);
            }

            jas_cleanup();
            loadingFailed();
            return false;
        }

        uint   checkPoint     = 0;
        uchar* dst            = data;
        unsigned short* dst16 = (unsigned short*)data;

        for (y = 0 ; y < (long)imageHeight() ; ++y)
        {
            for (i = 0 ; i < (long)number_components; ++i)
            {
                int ret = jas_image_readcmpt(jp2_image, (short)components[i], 0,
                                             ((unsigned int) y)            / y_step[i],
                                             ((unsigned int) imageWidth()) / x_step[i],
                                             1, pixels[i]);

                if (ret != 0)
                {
                    kDebug() << "Error decoding JPEG2000 image data";
                    delete [] data;
                    jas_image_destroy(jp2_image);

                    for (i = 0 ; i < (long)number_components ; ++i)
                    {
                        jas_matrix_destroy(pixels[i]);
                    }

                    jas_cleanup();
                    loadingFailed();
                    return false;
                }
            }

            switch (number_components)
            {
                case 1: // Grayscale.
                {
                    for (x = 0 ; x < (long)imageWidth() ; ++x)
                    {
                        dst[0] = (uchar)(scale[0]*jas_matrix_getv(pixels[0], x/x_step[0]));
                        dst[1] = dst[0];
                        dst[2] = dst[0];
                        dst[3] = 0xFF;

                        dst += 4;
                    }

                    break;
                }
                case 3: // RGB.
                {
                    if (!m_sixteenBit)   // 8 bits image.
                    {
                        for (x = 0 ; x < (long)imageWidth() ; ++x)
                        {
                            // Blue
                            dst[0] = (uchar)(scale[2]*jas_matrix_getv(pixels[2], x/x_step[2]));
                            // Green
                            dst[1] = (uchar)(scale[1]*jas_matrix_getv(pixels[1], x/x_step[1]));
                            // Red
                            dst[2] = (uchar)(scale[0]*jas_matrix_getv(pixels[0], x/x_step[0]));
                            // Alpha
                            dst[3] = 0xFF;

                            dst += 4;
                        }
                    }
                    else                // 16 bits image.
                    {
                        for (x = 0 ; x < (long)imageWidth() ; ++x)
                        {
                            // Blue
                            dst16[0] = (unsigned short)(scale[2]*jas_matrix_getv(pixels[2], x/x_step[2]));
                            // Green
                            dst16[1] = (unsigned short)(scale[1]*jas_matrix_getv(pixels[1], x/x_step[1]));
                            // Red
                            dst16[2] = (unsigned short)(scale[0]*jas_matrix_getv(pixels[0], x/x_step[0]));
                            // Alpha
                            dst16[3] = 0xFFFF;

                            dst16 += 4;
                        }
                    }

                    break;
                }
                case 4: // RGBA.
                {
                    if (!m_sixteenBit)   // 8 bits image.
                    {
                        for (x = 0 ; x < (long)imageWidth() ; ++x)
                        {
                            // Blue
                            dst[0] = (uchar)(scale[2] * jas_matrix_getv(pixels[2], x/x_step[2]));
                            // Green
                            dst[1] = (uchar)(scale[1] * jas_matrix_getv(pixels[1], x/x_step[1]));
                            // Red
                            dst[2] = (uchar)(scale[0] * jas_matrix_getv(pixels[0], x/x_step[0]));
                            // Alpha
                            dst[3] = (uchar)(scale[3] * jas_matrix_getv(pixels[3], x/x_step[3]));

                            dst += 4;
                        }
                    }
                    else                // 16 bits image.
                    {
                        for (x = 0 ; x < (long)imageWidth() ; ++x)
                        {
                            // Blue
                            dst16[0] = (unsigned short)(scale[2]*jas_matrix_getv(pixels[2], x/x_step[2]));
                            // Green
                            dst16[1] = (unsigned short)(scale[1]*jas_matrix_getv(pixels[1], x/x_step[1]));
                            // Red
                            dst16[2] = (unsigned short)(scale[0]*jas_matrix_getv(pixels[0], x/x_step[0]));
                            // Alpha
                            dst16[3] = (unsigned short)(scale[3]*jas_matrix_getv(pixels[3], x/x_step[3]));

                            dst16 += 4;
                        }
                    }

                    break;
                }
            }

            // use 0-10% and 90-100% for pseudo-progress
            if (observer && y >= (long)checkPoint)
            {
                checkPoint += granularity(observer, y, 0.8F);

                if (!observer->continueQuery(m_image))
                {
                    delete [] data;
                    jas_image_destroy(jp2_image);

                    for (i = 0 ; i < (long)number_components ; ++i)
                    {
                        jas_matrix_destroy(pixels[i]);
                    }

                    jas_cleanup();

                    loadingFailed();
                    return false;
                }

                observer->progressInfo(m_image, 0.1 + (0.8 * ( ((float)y)/((float)imageHeight()) )));
            }
        }
    }

    // -------------------------------------------------------------------
    // Get ICC color profile.

    if (m_loadFlags & LoadICCData)
    {
        jas_iccprof_t* icc_profile = 0;
        jas_stream_t*  icc_stream  = 0;
        jas_cmprof_t*  cm_profile  = 0;

        cm_profile = jas_image_cmprof(jp2_image);

        if (cm_profile != 0)
        {
            icc_profile = jas_iccprof_createfromcmprof(cm_profile);
        }

        if (icc_profile != 0)
        {
            icc_stream = jas_stream_memopen(NULL, 0);

            if (icc_stream != 0)
            {
                if (jas_iccprof_save(icc_profile, icc_stream) == 0)
                {
                    if (jas_stream_flush(icc_stream) == 0)
                    {
                        jas_stream_memobj_t* blob = (jas_stream_memobj_t*) icc_stream->obj_;
                        QByteArray profile_rawdata;
                        profile_rawdata.resize(blob->len_);
                        memcpy(profile_rawdata.data(), blob->buf_, blob->len_);
                        imageSetIccProfile(profile_rawdata);
                        jas_stream_close(icc_stream);
                    }
                }
            }
        }
    }

    if (observer)
    {
        observer->progressInfo(m_image, 1.0);
    }

    imageData() = data;
    imageSetAttribute("format", "JP2K");
    imageSetAttribute("originalColorModel", colorModel);
    imageSetAttribute("originalBitDepth", maximum_component_depth);
    imageSetAttribute("originalSize", QSize(imageWidth(), imageHeight()));

    jas_image_destroy(jp2_image);

    for (i = 0 ; i < (long)number_components ; ++i)
    {
        jas_matrix_destroy(pixels[i]);
    }

    jas_cleanup();

    return true;
}
Exemple #3
0
int jp2_write_header(jas_image_t *image, jas_stream_t *out)
{
    jp2_box_t *box;
    jp2_ftyp_t *ftyp;
    jp2_ihdr_t *ihdr;
    jas_stream_t *tmpstream;
    int allcmptssame;
    jp2_bpcc_t *bpcc;
    long len;
    uint_fast16_t cmptno;
    jp2_colr_t *colr;
    jp2_cdefchan_t *cdefchanent;
    jp2_cdef_t *cdef;
    int i;
    uint_fast32_t typeasoc;
jas_iccprof_t *iccprof;
jas_stream_t *iccstream;
int pos;
int needcdef;
int prec;
int sgnd;

    box = 0;
    tmpstream = 0;

    allcmptssame = 1;
    sgnd = jas_image_cmptsgnd(image, 0);
    prec = jas_image_cmptprec(image, 0);
    for (i = 1; i < jas_image_numcmpts(image); ++i) {
        if (jas_image_cmptsgnd(image, i) != sgnd ||
          jas_image_cmptprec(image, i) != prec) {
            allcmptssame = 0;
            break;
        }
    }

    /* Output the signature box. */

    if (!(box = jp2_box_create(JP2_BOX_JP))) {
        goto error;
    }
    box->data.jp.magic = JP2_JP_MAGIC;
    if (jp2_box_put(box, out)) {
        goto error;
    }
    jp2_box_destroy(box);
    box = 0;

    /* Output the file type box. */

    if (!(box = jp2_box_create(JP2_BOX_FTYP))) {
        goto error;
    }
    ftyp = &box->data.ftyp;
    ftyp->majver = JP2_FTYP_MAJVER;
    ftyp->minver = JP2_FTYP_MINVER;
    ftyp->numcompatcodes = 1;
    ftyp->compatcodes[0] = JP2_FTYP_COMPATCODE;
    if (jp2_box_put(box, out)) {
        goto error;
    }
    jp2_box_destroy(box);
    box = 0;

    /*
     * Generate the data portion of the JP2 header box.
     * We cannot simply output the header for this box
     * since we do not yet know the correct value for the length
     * field.
     */

    if (!(tmpstream = jas_stream_memopen(0, 0))) {
        goto error;
    }

    /* Generate image header box. */

    if (!(box = jp2_box_create(JP2_BOX_IHDR))) {
        goto error;
    }
    ihdr = &box->data.ihdr;
    ihdr->width = jas_image_width(image);
    ihdr->height = jas_image_height(image);
    ihdr->numcmpts = jas_image_numcmpts(image);
    ihdr->bpc = allcmptssame ? JP2_SPTOBPC(jas_image_cmptsgnd(image, 0),
      jas_image_cmptprec(image, 0)) : JP2_IHDR_BPCNULL;
    ihdr->comptype = JP2_IHDR_COMPTYPE;
    ihdr->csunk = 0;
    ihdr->ipr = 0;
    if (jp2_box_put(box, tmpstream)) {
        goto error;
    }
    jp2_box_destroy(box);
    box = 0;

    /* Generate bits per component box. */

    if (!allcmptssame) {
        if (!(box = jp2_box_create(JP2_BOX_BPCC))) {
            goto error;
        }
        bpcc = &box->data.bpcc;
        bpcc->numcmpts = jas_image_numcmpts(image);
        if (!(bpcc->bpcs = jas_alloc2(bpcc->numcmpts,
          sizeof(uint_fast8_t)))) {
            goto error;
        }
        for (cmptno = 0; cmptno < bpcc->numcmpts; ++cmptno) {
            bpcc->bpcs[cmptno] = JP2_SPTOBPC(jas_image_cmptsgnd(image,
              cmptno), jas_image_cmptprec(image, cmptno));
        }
        if (jp2_box_put(box, tmpstream)) {
            goto error;
        }
        jp2_box_destroy(box);
        box = 0;
    }

    /* Generate color specification box. */

    if (!(box = jp2_box_create(JP2_BOX_COLR))) {
        goto error;
    }
    colr = &box->data.colr;
    switch (jas_image_clrspc(image)) {
    case JAS_CLRSPC_SRGB:
    case JAS_CLRSPC_SYCBCR:
    case JAS_CLRSPC_SGRAY:
        colr->method = JP2_COLR_ENUM;
        colr->csid = clrspctojp2(jas_image_clrspc(image));
        colr->pri = JP2_COLR_PRI;
        colr->approx = 0;
        break;
    default:
        colr->method = JP2_COLR_ICC;
        colr->pri = JP2_COLR_PRI;
        colr->approx = 0;
        iccprof = jas_iccprof_createfromcmprof(jas_image_cmprof(image));
        assert(iccprof);
        iccstream = jas_stream_memopen(0, 0);
        assert(iccstream);
        if (jas_iccprof_save(iccprof, iccstream))
            abort();
        if ((pos = jas_stream_tell(iccstream)) < 0)
            abort();
        colr->iccplen = pos;
        colr->iccp = jas_malloc(pos);
        assert(colr->iccp);
        jas_stream_rewind(iccstream);
        if (jas_stream_read(iccstream, colr->iccp, colr->iccplen) != colr->iccplen)
            abort();
        jas_stream_close(iccstream);
        jas_iccprof_destroy(iccprof);
        break;
    }
    if (jp2_box_put(box, tmpstream)) {
        goto error;
    }
    jp2_box_destroy(box);
    box = 0;

    needcdef = 1;
    switch (jas_clrspc_fam(jas_image_clrspc(image))) {
    case JAS_CLRSPC_FAM_RGB:
        if (jas_image_cmpttype(image, 0) ==
          JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R) &&
          jas_image_cmpttype(image, 1) ==
          JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G) &&
          jas_image_cmpttype(image, 2) ==
          JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B))
            needcdef = 0;
        break;
    case JAS_CLRSPC_FAM_YCBCR:
        if (jas_image_cmpttype(image, 0) ==
          JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_Y) &&
          jas_image_cmpttype(image, 1) ==
          JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CB) &&
          jas_image_cmpttype(image, 2) ==
          JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_YCBCR_CR))
            needcdef = 0;
        break;
    case JAS_CLRSPC_FAM_GRAY:
        if (jas_image_cmpttype(image, 0) ==
          JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_GRAY_Y))
            needcdef = 0;
        break;
    default:
        abort();
        break;
    }

    if (needcdef) {
        if (!(box = jp2_box_create(JP2_BOX_CDEF))) {
            goto error;
        }
        cdef = &box->data.cdef;
        cdef->numchans = jas_image_numcmpts(image);
        cdef->ents = jas_alloc2(cdef->numchans, sizeof(jp2_cdefchan_t));
        for (i = 0; i < jas_image_numcmpts(image); ++i) {
            cdefchanent = &cdef->ents[i];
            cdefchanent->channo = i;
            typeasoc = jp2_gettypeasoc(jas_image_clrspc(image), jas_image_cmpttype(image, i));
            cdefchanent->type = typeasoc >> 16;
            cdefchanent->assoc = typeasoc & 0x7fff;
        }
        if (jp2_box_put(box, tmpstream)) {
            goto error;
        }
        jp2_box_destroy(box);
        box = 0;
    }

    /* Determine the total length of the JP2 header box. */

    len = jas_stream_tell(tmpstream);
    jas_stream_rewind(tmpstream);

    /*
     * Output the JP2 header box and all of the boxes which it contains.
     */

    if (!(box = jp2_box_create(JP2_BOX_JP2H))) {
        goto error;
    }
    box->len = len + JP2_BOX_HDRLEN(false);
    if (jp2_box_put(box, out)) {
        goto error;
    }
    jp2_box_destroy(box);
    box = 0;

    if (jas_stream_copy(out, tmpstream, len)) {
        goto error;
    }

    jas_stream_close(tmpstream);
    tmpstream = 0;

    return 0;
    abort();

error:

    if (box) {
        jp2_box_destroy(box);
    }
    if (tmpstream) {
        jas_stream_close(tmpstream);
    }
    return -1;
}