bool PGFLoader::save(const QString& filePath, DImgLoaderObserver* const observer) { m_observer = observer; #ifdef WIN32 #ifdef UNICODE HANDLE fd = CreateFile((LPCWSTR)(QFile::encodeName(filePath).constData()), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); #else HANDLE fd = CreateFile(QFile::encodeName(filePath).constData(), GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); #endif if (fd == INVALID_HANDLE_VALUE) { qCWarning(DIGIKAM_DIMG_LOG_PGF) << "Error: Could not open destination file."; return false; } #elif defined(__POSIX__) int fd = open(QFile::encodeName(filePath).constData(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd == -1) { qCWarning(DIGIKAM_DIMG_LOG_PGF) << "Error: Could not open destination file."; return false; } #endif try { QVariant qualityAttr = imageGetAttribute(QLatin1String("quality")); int quality = qualityAttr.isValid() ? qualityAttr.toInt() : 3; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF quality: " << quality; CPGFFileStream stream(fd); CPGFImage pgf; PGFHeader header; header.width = imageWidth(); header.height = imageHeight(); header.quality = quality; if (imageHasAlpha()) { if (imageSixteenBit()) { // NOTE : there is no PGF color mode in 16 bits with alpha. header.channels = 3; header.bpp = 48; header.mode = ImageModeRGB48; } else { header.channels = 4; header.bpp = 32; header.mode = ImageModeRGBA; } } else { if (imageSixteenBit()) { header.channels = 3; header.bpp = 48; header.mode = ImageModeRGB48; } else { header.channels = 3; header.bpp = 24; header.mode = ImageModeRGBColor; } } #ifdef PGFCodecVersionID # if PGFCodecVersionID < 0x061142 header.background.rgbtBlue = 0; header.background.rgbtGreen = 0; header.background.rgbtRed = 0; # endif #endif pgf.SetHeader(header); // NOTE: see bug #273765 : Loading PGF thumbs with OpenMP support through a separated thread do not work properlly with libppgf 6.11.24 pgf.ConfigureEncoder(false); pgf.ImportBitmap(4 * imageWidth() * (imageSixteenBit() ? 2 : 1), (UINT8*)imageData(), imageBitsDepth() * 4, NULL, CallbackForLibPGF, this); UINT32 nWrittenBytes = 0; #ifdef PGFCodecVersionID # if PGFCodecVersionID >= 0x061124 pgf.Write(&stream, &nWrittenBytes, CallbackForLibPGF, this); # endif #else pgf.Write(&stream, 0, CallbackForLibPGF, &nWrittenBytes, this); #endif qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF width = " << header.width; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF height = " << header.height; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF bbp = " << header.bpp; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF channels = " << header.channels; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF quality = " << header.quality; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "PGF mode = " << header.mode; qCDebug(DIGIKAM_DIMG_LOG_PGF) << "Bytes Written = " << nWrittenBytes; #ifdef WIN32 CloseHandle(fd); #else close(fd); #endif // TODO: Store ICC profile in an appropriate place in the image storeColorProfileInMetadata(); if (observer) { observer->progressInfo(m_image, 1.0); } imageSetAttribute(QLatin1String("savedformat"), QLatin1String("PGF")); saveMetadata(filePath); return true; } catch (IOException& e) { int err = e.error; if (err >= AppError) { err -= AppError; } qCWarning(DIGIKAM_DIMG_LOG_PGF) << "Error: Opening and saving PGF image failed (" << err << ")!"; #ifdef WIN32 CloseHandle(fd); #else close(fd); #endif return false; } return true; }
bool writePGFImageDataToStream(const QImage& image, CPGFStream& stream, int quality, UINT32& nWrittenBytes, bool verbose) { try { if (image.isNull()) { kDebug() << "Thumb image is null"; return false; } QImage img; // Convert image with Alpha channel. if (image.format() != QImage::Format_ARGB32) { img = image.convertToFormat(QImage::Format_ARGB32); if (verbose) kDebug() << "RGB => ARGB"; } else { img = image; } CPGFImage pgfImg; PGFHeader header; header.width = img.width(); header.height = img.height(); header.nLevels = 0; // Auto. header.quality = quality; header.bpp = img.depth(); header.channels = 4; header.mode = ImageModeRGBA; header.usedBitsPerChannel = 0; // Auto #ifdef PGFCodecVersionID # if PGFCodecVersionID < 0x061142 header.background.rgbtBlue = 0; header.background.rgbtGreen = 0; header.background.rgbtRed = 0; # endif #endif pgfImg.SetHeader(header); // NOTE: see bug #273765 : Loading PGF thumbs with OpenMP support through a separated thread do not work properlly with libppgf 6.11.24 pgfImg.ConfigureEncoder(false); if (verbose) { kDebug() << "PGF image settings:"; kDebug() << " width: " << header.width; kDebug() << " height: " << header.height; kDebug() << " nLevels: " << header.nLevels; kDebug() << " quality: " << header.quality; kDebug() << " bpp: " << header.bpp; kDebug() << " channels: " << header.channels; kDebug() << " mode: " << header.mode; kDebug() << " usedBitsPerChannel: " << header.usedBitsPerChannel; } if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { int map[] = {3, 2, 1, 0}; pgfImg.ImportBitmap(img.bytesPerLine(), (UINT8*)img.bits(), img.depth(), map); } else { int map[] = {0, 1, 2, 3}; pgfImg.ImportBitmap(img.bytesPerLine(), (UINT8*)img.bits(), img.depth(), map); } nWrittenBytes = 0; #ifdef PGFCodecVersionID # if PGFCodecVersionID >= 0x061124 pgfImg.Write(&stream, &nWrittenBytes); # else pgfImg.Write(&stream, 0, 0, &nWrittenBytes); # endif #else pgfImg.Write(&stream, 0, 0, &nWrittenBytes); #endif } catch (IOException& e) { int err = e.error; if (err >= AppError) { err -= AppError; } kDebug() << "Error running libpgf (" << err << ")!"; return false; } return true; }