File indexing completed on 2024-05-12 04:19:35
0001 // vim: set tabstop=4 shiftwidth=4 expandtab: 0002 /* 0003 Gwenview: an image viewer 0004 Copyright 2012 Aurélien Gâteau <agateau@kde.org> 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public License 0008 as published by the Free Software Foundation; either version 2 0009 of the License, or (at your option) any later version. 0010 0011 This program is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 GNU General Public License for more details. 0015 0016 You should have received a copy of the GNU General Public License 0017 along with this program; if not, write to the Free Software 0018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA. 0019 0020 */ 0021 // Self 0022 #include "cmsprofile_png.h" 0023 0024 // Local 0025 #include <gvdebug.h> 0026 #include "gwenview_lib_debug.h" 0027 0028 // KF 0029 0030 // Qt 0031 #include <QBuffer> 0032 0033 // lcms 0034 #include <lcms2.h> 0035 0036 // libpng 0037 #include <png.h> 0038 0039 namespace Gwenview 0040 { 0041 0042 namespace Cms 0043 { 0044 0045 static void readPngChunk(png_structp png_ptr, png_bytep data, png_size_t length) 0046 { 0047 auto in = (QIODevice *)png_get_io_ptr(png_ptr); 0048 0049 while (length) { 0050 int nr = in->read((char*)data, length); 0051 if (nr <= 0) { 0052 png_error(png_ptr, "Read Error"); 0053 return; 0054 } 0055 length -= nr; 0056 } 0057 } 0058 0059 cmsHPROFILE loadFromPngData(const QByteArray& data) 0060 { 0061 QBuffer buffer; 0062 buffer.setBuffer(const_cast<QByteArray*>(&data)); 0063 buffer.open(QIODevice::ReadOnly); 0064 0065 // Initialize the internal structures 0066 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); 0067 GV_RETURN_VALUE_IF_FAIL(png_ptr, nullptr); 0068 0069 png_infop info_ptr = png_create_info_struct(png_ptr); 0070 if (!info_ptr) { 0071 png_destroy_read_struct(&png_ptr, (png_infopp)nullptr, (png_infopp)nullptr); 0072 qCWarning(GWENVIEW_LIB_LOG) << "Could not create info_struct"; 0073 return nullptr; 0074 } 0075 0076 png_infop end_info = png_create_info_struct(png_ptr); 0077 if (!end_info) { 0078 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)nullptr); 0079 qCWarning(GWENVIEW_LIB_LOG) << "Could not create info_struct2"; 0080 return nullptr; 0081 } 0082 0083 // Catch errors 0084 if (setjmp(png_jmpbuf(png_ptr))) { 0085 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 0086 qCWarning(GWENVIEW_LIB_LOG) << "Error decoding png file"; 0087 return nullptr; 0088 } 0089 0090 // Initialize the special 0091 png_set_read_fn(png_ptr, &buffer, readPngChunk); 0092 0093 // read all PNG info up to image data 0094 png_read_info(png_ptr, info_ptr); 0095 0096 // Get profile 0097 png_charp profile_name; 0098 #if PNG_LIBPNG_VER_MAJOR >= 1 && PNG_LIBPNG_VER_MINOR >= 5 0099 png_bytep profile_data; 0100 #else 0101 png_charp profile_data; 0102 #endif 0103 int compression_type; 0104 png_uint_32 proflen; 0105 0106 cmsHPROFILE profile = nullptr; 0107 if (png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &proflen)) { 0108 profile = cmsOpenProfileFromMem(profile_data, proflen); 0109 } 0110 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 0111 return profile; 0112 } 0113 0114 } // namespace Cms 0115 } // namespace Gwenview