Exemple #1
0
bool JpegContent::loadFromData(const QByteArray& data)
{
    Exiv2::Image::AutoPtr image;
    Exiv2ImageLoader loader;
    if (!loader.load(data)) {
        qCritical() << "Could not load image with Exiv2, reported error:" << loader.errorMessage();
    }
    image = loader.popImage();

    return loadFromData(data, image.get());
}
Exemple #2
0
void CmsProfileTest::testLoadFromExiv2Image()
{
    QFETCH(QString, fileName);
    Exiv2::Image::AutoPtr image;
    {
        QByteArray data;
        QString path = pathForTestFile(fileName);
        qWarning() << path;
        QFile file(path);
        QVERIFY(file.open(QIODevice::ReadOnly));
        data = file.readAll();

        Exiv2ImageLoader loader;
        QVERIFY(loader.load(data));
        image = loader.popImage();
    }
    Cms::Profile::Ptr ptr = Cms::Profile::loadFromExiv2Image(image.get());
    QVERIFY(!ptr.isNull());
}
    bool loadMetaInfo()
    {
        LOG("mFormatHint" << mFormatHint);
        QBuffer buffer;
        buffer.setBuffer(&mData);
        buffer.open(QIODevice::ReadOnly);

#ifdef KDCRAW_FOUND
        if (KDcrawIface::KDcraw::rawFilesList().contains(QString(mFormatHint))) {
            QByteArray previewData;

            // if the image is in format supported by dcraw, fetch its embedded preview
            mJpegContent.reset(new JpegContent());

            // use KDcraw for getting the embedded preview
            // KDcraw functionality cloned locally (temp. solution)
            bool ret = KDcrawIface::KDcraw::loadEmbeddedPreview(previewData, buffer);

            QImage originalImage;
            if (!ret || !originalImage.loadFromData(previewData) || qMin(originalImage.width(), originalImage.height()) < MIN_PREV_SIZE) {
                // if the embedded preview loading failed or gets just a small image, load
                // half preview instead. That's slower but it works even for images containing
                // small (160x120px) or none embedded preview.
                if (!KDcrawIface::KDcraw::loadHalfPreview(previewData, buffer)) {
                    qWarning() << "unable to get half preview for " << q->document()->url().fileName();
                    return false;
                }
            }

            buffer.close();

            // now it's safe to replace mData with the jpeg data
            mData = previewData;

            // need to fill mFormat so gwenview can tell the type when trying to save
            mFormat = mFormatHint;
        } else {
#else
{
#endif
            QImageReader reader(&buffer, mFormatHint);
            mImageSize = reader.size();

            if (!reader.canRead()) {
                qWarning() << "QImageReader::read() using format hint" << mFormatHint << "failed:" << reader.errorString();
                if (buffer.pos() != 0) {
                    qWarning() << "A bad Qt image decoder moved the buffer to" << buffer.pos() << "in a call to canRead()! Rewinding.";
                    buffer.seek(0);
                }
                reader.setFormat(QByteArray());
                // Set buffer again, otherwise QImageReader won't restart from scratch
                reader.setDevice(&buffer);
                if (!reader.canRead()) {
                    qWarning() << "QImageReader::read() without format hint failed:" << reader.errorString();
                    return false;
                }
                qWarning() << "Image format is actually" << reader.format() << "not" << mFormatHint;
            }

            mFormat = reader.format();

            if (mFormat == "jpg") {
                // if mFormatHint was "jpg", then mFormat is "jpg", but the rest of
                // Gwenview code assumes JPEG images have "jpeg" format.
                mFormat = "jpeg";
            }
        }

        LOG("mFormat" << mFormat);
        GV_RETURN_VALUE_IF_FAIL(!mFormat.isEmpty(), false);

        Exiv2ImageLoader loader;
        if (loader.load(mData)) {
            mExiv2Image = loader.popImage();
        }

        if (mFormat == "jpeg" && mExiv2Image.get()) {
            mJpegContent.reset(new JpegContent());
        }

        if (mJpegContent.get()) {
            if (!mJpegContent->loadFromData(mData, mExiv2Image.get()) &&
                !mJpegContent->loadFromData(mData)) {
                qWarning() << "Unable to use preview of " << q->document()->url().fileName();
                return false;
            }
            // Use the size from JpegContent, as its correctly transposed if the
            // image has been rotated
            mImageSize = mJpegContent->size();

            mCmsProfile = Cms::Profile::loadFromExiv2Image(mExiv2Image.get());

        }

        LOG("mImageSize" << mImageSize);

        if (!mCmsProfile) {
            mCmsProfile = Cms::Profile::loadFromImageData(mData, mFormat);
        }

        return true;
    }

    void loadImageData()
    {
        QBuffer buffer;
        buffer.setBuffer(&mData);
        buffer.open(QIODevice::ReadOnly);
        QImageReader reader(&buffer, mFormat);

        LOG("mImageDataInvertedZoom=" << mImageDataInvertedZoom);
        if (mImageSize.isValid()
                && mImageDataInvertedZoom != 1
                && reader.supportsOption(QImageIOHandler::ScaledSize)
           ) {
            // Do not use mImageSize here: QImageReader needs a non-transposed
            // image size
            QSize size = reader.size() / mImageDataInvertedZoom;
            if (!size.isEmpty()) {
                LOG("Setting scaled size to" << size);
                reader.setScaledSize(size);
            } else {
                LOG("Not setting scaled size as it is empty" << size);
            }
        }

        bool ok = reader.read(&mImage);
        if (!ok) {
            LOG("QImageReader::read() failed");
            return;
        }

        if (mJpegContent.get() && GwenviewConfig::applyExifOrientation()) {
            Gwenview::Orientation orientation = mJpegContent->orientation();
            QMatrix matrix = ImageUtils::transformMatrix(orientation);
            mImage = mImage.transformed(matrix);
        }

        if (reader.supportsAnimation()
                && reader.nextImageDelay() > 0 // Assume delay == 0 <=> only one frame
           ) {
            /*
             * QImageReader is not really helpful to detect animated gif:
             * - QImageReader::imageCount() returns 0
             * - QImageReader::nextImageDelay() may return something > 0 if the
             *   image consists of only one frame but includes a "Graphic
             *   Control Extension" (usually only present if we have an
             *   animation) (Bug #185523)
             *
             * Decoding the next frame is the only reliable way I found to
             * detect an animated gif
             */
            LOG("May be an animated image. delay:" << reader.nextImageDelay());
            QImage nextImage;
            if (reader.read(&nextImage)) {
                LOG("Really an animated image (more than one frame)");
                mAnimated = true;
            } else {
                qWarning() << q->document()->url() << "is not really an animated image (only one frame)";
            }
        }
    }