예제 #1
0
bool LoadSaveThread::exifRotate(DImg& image, const QString& filePath)
{
    // Keep in sync with the variant in thumbnailcreator.cpp
    if (wasExifRotated(image))
    {
        return false;
    }

    // Rotate thumbnail based on metadata orientation information

    bool rotatedOrFlipped = image.rotateAndFlip(exifOrientation(image, filePath));
    image.setAttribute("exifRotated", true);

    return rotatedOrFlipped;
}
예제 #2
0
파일: jpegutils.cpp 프로젝트: KDE/digikam
bool JpegRotator::exifTransform(const MetaEngineRotation& matrix)
{
    FileWriteLocker lock(m_destFile);

    QFileInfo fi(m_file);

    if (!fi.exists())
    {
        qCDebug(DIGIKAM_GENERAL_LOG) << "ExifRotate: file does not exist: " << m_file;
        return false;
    }

    if (!isJpegImage(m_file))
    {
        // Not a jpeg image.
        qCDebug(DIGIKAM_GENERAL_LOG) << "ExifRotate: not a JPEG file: " << m_file;
        return false;
    }

    QList<TransformAction> actions = matrix.transformations();

    if (actions.isEmpty())
    {
        if (m_file != m_destFile)
        {
            copyFile(m_file, m_destFile);
        }

        return true;
    }

    QString     dest = m_destFile;
    QString     src  = m_file;
    QString     dir  = fi.absolutePath();
    QStringList unlinkLater;

    for (int i=0; i<actions.size(); i++)
    {
        SafeTemporaryFile* const temp = new SafeTemporaryFile(dir + QLatin1String("/JpegRotator-XXXXXX.digikamtempfile.jpg"));
        temp->setAutoRemove(false);
        temp->open();
        QString tempFile = temp->fileName();
        // Crash fix: a QTemporaryFile is not properly closed until its destructor is called.
        delete temp;

        if (!performJpegTransform(actions[i], src, tempFile))
        {
            qCDebug(DIGIKAM_GENERAL_LOG) << "JPEG lossless transform failed for" << src;

             // See bug 320107 : if lossless transform cannot be achieve, do lossy transform.
            DImg srcImg;

            qCDebug(DIGIKAM_GENERAL_LOG) << "Trying lossy transform for " << src;

            if (!srcImg.load(src))
            {
                ::unlink(QFile::encodeName(tempFile).constData());
                return false;
            }

            if (actions[i] != MetaEngineRotation::NoTransformation)
            {
                srcImg.transform(actions[i]);
            }

            srcImg.setAttribute(QLatin1String("quality"), getJpegQuality(src));

            if (!srcImg.save(tempFile, DImg::JPEG))
            {
                qCDebug(DIGIKAM_GENERAL_LOG) << "Lossy transform failed for" << src;

                ::unlink(QFile::encodeName(tempFile).constData());
                return false;
            }

            qCDebug(DIGIKAM_GENERAL_LOG) << "Lossy transform done for " << src;
        }

        if (i+1 != actions.size())
        {
            // another round
            src = tempFile;
            unlinkLater << tempFile;
            continue;
        }

        // finalize
        updateMetadata(tempFile, matrix);

        // atomic rename

        if (DMetadata::hasSidecar(tempFile))
        {
            QString sidecarTemp = DMetadata::sidecarPath(tempFile);
            QString sidecarDest = DMetadata::sidecarPath(dest);

#ifdef Q_OS_WIN
            if (::MoveFileEx((LPCWSTR)sidecarTemp.utf16(), (LPCWSTR)sidecarDest.utf16(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == 0)
#else
            if (::rename(QFile::encodeName(sidecarTemp).constData(), QFile::encodeName(sidecarDest).constData()) != 0)
#endif
            {
                qCDebug(DIGIKAM_GENERAL_LOG) << "Renaming sidecar file" << sidecarTemp << "to" << sidecarDest << "failed";
                unlinkLater << sidecarTemp;
                break;
            }
        }

#ifdef Q_OS_WIN
        if (::MoveFileEx((LPCWSTR)tempFile.utf16(), (LPCWSTR)dest.utf16(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) == 0)
#else
        if (::rename(QFile::encodeName(tempFile).constData(), QFile::encodeName(dest).constData()) != 0)
#endif
        {
            qCDebug(DIGIKAM_GENERAL_LOG) << "Renaming" << tempFile << "to" << dest << "failed";
            unlinkLater << tempFile;
            break;
        }
    }

    foreach (const QString& tempFile, unlinkLater)
    {
        ::unlink(QFile::encodeName(tempFile).constData());
    }