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()); }
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)"; } } }