"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "plugins/impex/tiff/kis_tiff_import.cc" between
krita-5.1.3.tar.xz and krita-5.1.4.tar.xz

About: Krita is a painting program offering art tools for everyone (concept art, texture and matte painters, illustrations and comics).

kis_tiff_import.cc  (krita-5.1.3.tar.xz):kis_tiff_import.cc  (krita-5.1.4.tar.xz)
/* /*
* SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net> * SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net>
* SPDX-FileCopyrightText: 2022 L. E. Segovia <amy@amyspark.me> * SPDX-FileCopyrightText: 2022 L. E. Segovia <amy@amyspark.me>
* *
* SPDX-License-Identifier: GPL-2.0-or-later * SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#include "kis_tiff_import.h" #include "kis_tiff_import.h"
#include "KisImportExportErrorCode.h"
#include "kis_assert.h"
#include <QBuffer> #include <QBuffer>
#include <QFileInfo> #include <QFileInfo>
#include <QPair> #include <QPair>
#include <QSharedPointer> #include <QSharedPointer>
#include <QStack> #include <QStack>
#include <array> #include <array>
#include <exiv2/exiv2.hpp> #include <exiv2/exiv2.hpp>
#include <kpluginfactory.h> #include <kpluginfactory.h>
#ifdef Q_OS_WIN
#include <io.h>
#endif
#include <tiffio.h> #include <tiffio.h>
#include <KisDocument.h> #include <KisDocument.h>
#include <KisImportExportAdditionalChecks.h> #include <KisImportExportAdditionalChecks.h>
#include <KisViewManager.h> #include <KisViewManager.h>
#include <KoColorProfile.h> #include <KoColorProfile.h>
#include <KoDocumentInfo.h> #include <KoDocumentInfo.h>
#include <KoUnit.h> #include <KoUnit.h>
#include <KisExiv2IODevice.h>
#include <kis_group_layer.h> #include <kis_group_layer.h>
#include <kis_image.h> #include <kis_image.h>
#include <kis_meta_data_backend_registry.h> #include <kis_meta_data_backend_registry.h>
#include <kis_meta_data_tags.h> #include <kis_meta_data_tags.h>
#include <kis_paint_layer.h> #include <kis_paint_layer.h>
#include <kis_transform_worker.h> #include <kis_transform_worker.h>
#include <kis_transparency_mask.h> #include <kis_transparency_mask.h>
#ifdef TIFF_HAS_PSD_TAGS #ifdef TIFF_HAS_PSD_TAGS
#include <psd_resource_block.h> #include <psd_resource_block.h>
skipping to change at line 52 skipping to change at line 58
#ifdef HAVE_JPEG_TURBO #ifdef HAVE_JPEG_TURBO
#include <turbojpeg.h> #include <turbojpeg.h>
#endif #endif
#include "kis_buffer_stream.h" #include "kis_buffer_stream.h"
#include "kis_tiff_logger.h" #include "kis_tiff_logger.h"
#include "kis_tiff_reader.h" #include "kis_tiff_reader.h"
#include "kis_tiff_ycbcr_reader.h" #include "kis_tiff_ycbcr_reader.h"
enum class TiffResolution : quint8 {
NONE = RESUNIT_NONE,
INCH = RESUNIT_INCH,
CM = RESUNIT_CENTIMETER,
};
struct KisTiffBasicInfo { struct KisTiffBasicInfo {
uint32_t width{}; uint32_t width{};
uint32_t height{}; uint32_t height{};
float x{}; float x{};
float y{}; float y{};
float xres{}; float xres{};
float yres{}; float yres{};
uint16_t depth{}; uint16_t depth{};
uint16_t sampletype{}; uint16_t sampletype{};
uint16_t nbchannels{}; uint16_t nbchannels{};
uint16_t color_type{}; uint16_t color_type{};
uint16_t *sampleinfo = nullptr; uint16_t *sampleinfo = nullptr;
uint16_t extrasamplescount = 0; uint16_t extrasamplescount = 0;
const KoColorSpace *cs = nullptr; const KoColorSpace *cs = nullptr;
QPair<QString, QString> colorSpaceIdTag; QPair<QString, QString> colorSpaceIdTag;
KoColorTransformation *transform = nullptr; KoColorTransformation *transform = nullptr;
uint8_t dstDepth{}; uint8_t dstDepth{};
TiffResolution resolution = TiffResolution::NONE;
}; };
K_PLUGIN_FACTORY_WITH_JSON(TIFFImportFactory, K_PLUGIN_FACTORY_WITH_JSON(TIFFImportFactory,
"krita_tiff_import.json", "krita_tiff_import.json",
registerPlugin<KisTIFFImport>();) registerPlugin<KisTIFFImport>();)
QPair<QString, QString> getColorSpaceForColorType(uint16_t sampletype, QPair<QString, QString> getColorSpaceForColorType(uint16_t sampletype,
uint16_t color_type, uint16_t color_type,
uint16_t color_nb_bits, uint16_t color_nb_bits,
TIFF *image, TIFF *image,
skipping to change at line 431 skipping to change at line 444
* probably, it is just a single layered group. * probably, it is just a single layered group.
*/ */
KisNodeSP lastAddedLayer; KisNodeSP lastAddedLayer;
using LayerStyleMapping = QPair<QDomDocument, KisLayerSP>; using LayerStyleMapping = QPair<QDomDocument, KisLayerSP>;
QVector<LayerStyleMapping> allStylesXml; QVector<LayerStyleMapping> allStylesXml;
const std::shared_ptr<PSDLayerMaskSection> &layerSection = const std::shared_ptr<PSDLayerMaskSection> &layerSection =
photoshopLayerRecord.record(); photoshopLayerRecord.record();
KIS_SAFE_ASSERT_RECOVER(layerSection->nLayers != 0)
{
return ImportExportCodes::FileFormatIncorrect;
}
for (int i = 0; i != layerSection->nLayers; i++) { for (int i = 0; i != layerSection->nLayers; i++) {
PSDLayerRecord *layerRecord = layerSection->layers.at(i); PSDLayerRecord *layerRecord = layerSection->layers.at(i);
dbgFile << "Going to read channels for layer" << i dbgFile << "Going to read channels for layer" << i
<< layerRecord->layerName; << layerRecord->layerName;
KisLayerSP newLayer; KisLayerSP newLayer;
if (layerRecord->infoBlocks.keys.contains("lsct") if (layerRecord->infoBlocks.keys.contains("lsct")
&& layerRecord->infoBlocks.sectionDividerType != psd_other) { && layerRecord->infoBlocks.sectionDividerType != psd_other) {
if (layerRecord->infoBlocks.sectionDividerType if (layerRecord->infoBlocks.sectionDividerType
== psd_bounding_divider == psd_bounding_divider
&& !groupStack.isEmpty()) { && !groupStack.isEmpty()) {
skipping to change at line 689 skipping to change at line 707
// Creating the KisImageSP // Creating the KisImageSP
if (!m_image) { if (!m_image) {
m_image = new KisImage(m_doc->createUndoStore(), m_image = new KisImage(m_doc->createUndoStore(),
static_cast<qint32>(width), static_cast<qint32>(width),
static_cast<qint32>(height), static_cast<qint32>(height),
cs, cs,
"built image"); "built image");
KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE( KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(
m_image, m_image,
ImportExportCodes::InsufficientMemory); ImportExportCodes::InsufficientMemory);
m_image->setResolution( // It is the "invert" macro because we
POINT_TO_INCH(static_cast<qreal>(xres)), // convert from pointer-per-unit to points
POINT_TO_INCH(static_cast<qreal>( if (basicInfo.resolution == TiffResolution::INCH) {
yres))); // It is the "invert" macro because we convert from m_image->setResolution(POINT_TO_INCH(static_cast<qreal>(xres)), POIN
// pointer-per-inchs to points T_TO_INCH(static_cast<qreal>(yres)));
} else {
m_image->setResolution(POINT_TO_CM(static_cast<qreal>(xres)), POINT_
TO_CM(static_cast<qreal>(yres)));
}
} else { } else {
if (m_image->width() < static_cast<qint32>(width) if (m_image->width() < static_cast<qint32>(width)
|| m_image->height() < static_cast<qint32>(height)) { || m_image->height() < static_cast<qint32>(height)) {
qint32 newwidth = (m_image->width() < static_cast<qint32>(width)) qint32 newwidth = (m_image->width() < static_cast<qint32>(width))
? static_cast<qint32>(width) ? static_cast<qint32>(width)
: m_image->width(); : m_image->width();
qint32 newheight = (m_image->height() < static_cast<qint32>(height)) qint32 newheight = (m_image->height() < static_cast<qint32>(height))
? static_cast<qint32>(height) ? static_cast<qint32>(height)
: m_image->height(); : m_image->height();
m_image->resizeImage(QRect(0, 0, newwidth, newheight)); m_image->resizeImage(QRect(0, 0, newwidth, newheight));
skipping to change at line 1510 skipping to change at line 1530
// but we don't stop // but we don't stop
basicInfo.xres = 100; basicInfo.xres = 100;
} }
if (TIFFGetField(image, TIFFTAG_YRESOLUTION, &basicInfo.yres) == 0) { if (TIFFGetField(image, TIFFTAG_YRESOLUTION, &basicInfo.yres) == 0) {
dbgFile << "Image does not define y resolution"; dbgFile << "Image does not define y resolution";
// but we don't stop // but we don't stop
basicInfo.yres = 100; basicInfo.yres = 100;
} }
if (TIFFGetField(image, TIFFTAG_RESOLUTIONUNIT, &basicInfo.resolution) == 0)
{
dbgFile << "Image does not define resolution unit";
// but we don't stop
basicInfo.resolution = TiffResolution::INCH;
}
if (TIFFGetField(image, TIFFTAG_XPOSITION, &basicInfo.x) == 0) { if (TIFFGetField(image, TIFFTAG_XPOSITION, &basicInfo.x) == 0) {
dbgFile << "Image does not define a horizontal offset"; dbgFile << "Image does not define a horizontal offset";
basicInfo.x = 0; basicInfo.x = 0;
} }
if (TIFFGetField(image, TIFFTAG_YPOSITION, &basicInfo.y) == 0) { if (TIFFGetField(image, TIFFTAG_YPOSITION, &basicInfo.y) == 0) {
dbgFile << "Image does not define a vertical offset"; dbgFile << "Image does not define a vertical offset";
basicInfo.y = 0; basicInfo.y = 0;
} }
skipping to change at line 1767 skipping to change at line 1793
{ {
dbgFile << "Start decoding TIFF File"; dbgFile << "Start decoding TIFF File";
if (!KisImportExportAdditionalChecks::doesFileExist(filename())) { if (!KisImportExportAdditionalChecks::doesFileExist(filename())) {
return ImportExportCodes::FileNotExist; return ImportExportCodes::FileNotExist;
} }
if (!KisImportExportAdditionalChecks::isFileReadable(filename())) { if (!KisImportExportAdditionalChecks::isFileReadable(filename())) {
return ImportExportCodes::NoAccessToRead; return ImportExportCodes::NoAccessToRead;
} }
QFile file(filename());
if (!file.open(QFile::ReadOnly)) {
return KisImportExportErrorCode(KisImportExportErrorCannotRead(file.erro
r()));
}
// Open the TIFF file // Open the TIFF file
const QByteArray encodedFilename = QFile::encodeName(filename()); const QByteArray encodedFilename = QFile::encodeName(filename());
std::unique_ptr<TIFF, decltype(&TIFFClose)> image(
TIFFOpen(encodedFilename.data(), "r"), // https://gitlab.com/libtiff/libtiff/-/issues/173
&TIFFClose); #ifdef Q_OS_WIN
const intptr_t handle = _get_osfhandle(file.handle());
#else
const int handle = file.handle();
#endif
std::unique_ptr<TIFF, decltype(&TIFFCleanup)> image(TIFFFdOpen(handle, encod
edFilename.data(), "r"), &TIFFCleanup);
if (!image) { if (!image) {
dbgFile << "Could not open the file, either it does not exist, either " dbgFile << "Could not open the file, either it does not exist, either "
"it is not a TIFF :" "it is not a TIFF :"
<< filename(); << filename();
return (ImportExportCodes::FileFormatIncorrect); return (ImportExportCodes::FileFormatIncorrect);
} }
dbgFile << "Reading first image descriptor"; dbgFile << "Reading first image descriptor";
KisImportExportErrorCode result = readTIFFDirectory(document, image.get()); KisImportExportErrorCode result = readTIFFDirectory(document, image.get());
if (!result.isOk()) { if (!result.isOk()) {
skipping to change at line 1798 skipping to change at line 1835
m_photoshopBlockParsed = true; m_photoshopBlockParsed = true;
while (TIFFReadDirectory(image.get())) { while (TIFFReadDirectory(image.get())) {
result = readTIFFDirectory(document, image.get()); result = readTIFFDirectory(document, image.get());
if (!result.isOk()) { if (!result.isOk()) {
return result; return result;
} }
} }
} }
// Freeing memory // Freeing memory
image.reset(); image.reset();
file.close();
{ {
// HACK!! Externally parse the Exif metadata // HACK!! Externally parse the Exif metadata
// libtiff has no way to access the fields wholesale // libtiff has no way to access the fields wholesale
try { try {
const std::string encodedFilename = KisExiv2IODevice::ptr_type basicIoDevice(new KisExiv2IODevice(filena
QFile::encodeName(filename()).toStdString(); me()));
const std::unique_ptr<Exiv2::Image> readImg( const std::unique_ptr<Exiv2::Image> readImg(Exiv2::ImageFactory::ope
Exiv2::ImageFactory::open(encodedFilename).release()); n(basicIoDevice).release());
readImg->readMetadata(); readImg->readMetadata();
const KisMetaData::IOBackend *io = const KisMetaData::IOBackend *io =
KisMetadataBackendRegistry::instance()->value("exif"); KisMetadataBackendRegistry::instance()->value("exif");
// All IFDs are paint layer children of root // All IFDs are paint layer children of root
KisNodeSP node = m_image->rootLayer()->firstChild(); KisNodeSP node = m_image->rootLayer()->firstChild();
QBuffer ioDevice; QBuffer ioDevice;
skipping to change at line 1867 skipping to change at line 1903
Exiv2::littleEndian, Exiv2::littleEndian,
tempData); tempData);
// Reencode into Qt land // Reencode into Qt land
ioDevice.setData(reinterpret_cast<char *>(tempBlob.data()), ioDevice.setData(reinterpret_cast<char *>(tempBlob.data()),
static_cast<int>(tempBlob.size())); static_cast<int>(tempBlob.size()));
} }
// Get layer // Get layer
KisLayer *layer = qobject_cast<KisLayer *>(node.data()); KisLayer *layer = qobject_cast<KisLayer *>(node.data());
Q_ASSERT(layer); KIS_ASSERT_RECOVER(layer)
{
errFile << "Attempted to import metadata on an empty document";
return ImportExportCodes::InternalError;
}
// Inject the data as any other IOBackend // Inject the data as any other IOBackend
io->loadFrom(layer->metaData(), &ioDevice); io->loadFrom(layer->metaData(), &ioDevice);
} catch (Exiv2::AnyError &e) { } catch (Exiv2::AnyError &e) {
errFile << "Failed metadata import:" << e.code() << e.what(); errFile << "Failed metadata import:" << e.code() << e.what();
} }
} }
document->setCurrentImage(m_image); document->setCurrentImage(m_image);
 End of changes. 14 change blocks. 
13 lines changed or deleted 60 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)