File indexing completed on 2024-05-12 15:38:29
0001 /* 0002 Large image load library -- QImageIO decoder 0003 0004 Copyright (C) 2007-2009 Allan Sandfeld Jensen <sandfeld@kde.org> 0005 0006 Permission is hereby granted, free of charge, to any person obtaining a copy 0007 of this software and associated documentation files (the "Software"), to deal 0008 in the Software without restriction, including without limitation the rights 0009 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 0010 copies of the Software, and to permit persons to whom the Software is 0011 furnished to do so, subject to the following conditions: 0012 0013 The above copyright notice and this permission notice shall be included in 0014 all copies or substantial portions of the Software. 0015 0016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0019 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 0020 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 0021 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 0022 0023 */ 0024 0025 #include <QBuffer> 0026 #include <QByteArray> 0027 #include <QStringList> 0028 #include <QImageReader> 0029 0030 #include "qimageioloader.h" 0031 #include "imageloader.h" 0032 #include "kservice.h" 0033 #include "kservicetypetrader.h" 0034 #include "QDebug" 0035 #include "imagemanager.h" 0036 0037 namespace khtmlImLoad 0038 { 0039 0040 class QImageIOLoader: public ImageLoader 0041 { 0042 QByteArray array; 0043 QImage image; 0044 public: 0045 QImageIOLoader() 0046 { 0047 } 0048 0049 ~QImageIOLoader() 0050 { 0051 } 0052 0053 int processData(uchar *data, int length) override 0054 { 0055 //Collect data in the buffer 0056 int pos = array.size(); 0057 array.resize(array.size() + length); 0058 memcpy(array.data() + pos, data, length); 0059 return length; 0060 } 0061 0062 int processEOF() override 0063 { 0064 QBuffer buffer(&array); 0065 buffer.open(QIODevice::ReadOnly); 0066 0067 QByteArray qformat = QImageReader::imageFormat(&buffer); 0068 QImageReader reader(&buffer, qformat); 0069 0070 if (!reader.canRead()) { 0071 return Error; 0072 } 0073 0074 QSize size = reader.size(); 0075 if (size.isValid()) { 0076 if (ImageManager::isAcceptableSize(size.width(), size.height())) { 0077 notifyImageInfo(size.width(), size.height()); 0078 } else { 0079 return Error; 0080 } 0081 } 0082 0083 const bool readSuccess = !reader.read(&image); 0084 // It happens sometimes that even QImageReader said it failed to read 0085 // it did actually read something, 0086 // e.g. image from https://bugs.kde.org/show_bug.cgi?id=441554 0087 // so if the image has a size, pretend it succeeded 0088 if (!size.isValid()) { 0089 if (!readSuccess) { 0090 return Error; 0091 } 0092 0093 // Might be too late by now.. 0094 if (ImageManager::isAcceptableSize(image.width(), image.height())) { 0095 notifyImageInfo(image.width(), image.height()); 0096 } else { 0097 return Error; 0098 } 0099 } 0100 0101 ImageFormat format; 0102 if (!imageFormat(image, format)) { 0103 return Error; 0104 } 0105 notifyAppendFrame(image.width(), image.height(), format); 0106 0107 notifyQImage(1, &image); 0108 0109 return Done; 0110 } 0111 bool imageFormat(QImage &image, ImageFormat &format) 0112 { 0113 switch (image.format()) { 0114 case QImage::Format_RGB32: 0115 format.type = ImageFormat::Image_RGB_32; 0116 break; 0117 case QImage::Format_ARGB32: 0118 format.type = ImageFormat::Image_ARGB_32_DontPremult; 0119 break; 0120 case QImage::Format_ARGB32_Premultiplied: 0121 format.type = ImageFormat::Image_ARGB_32; 0122 break; 0123 case QImage::Format_Indexed8: 0124 format.type = ImageFormat::Image_Palette_8; 0125 format.palette = image.colorTable(); 0126 break; 0127 case QImage::Format_Mono: 0128 case QImage::Format_MonoLSB: 0129 image = image.convertToFormat(QImage::Format_Indexed8); 0130 format.type = ImageFormat::Image_Palette_8; 0131 format.palette = image.colorTable(); 0132 break; 0133 case QImage::Format_Invalid: 0134 default: 0135 // unsupported formats 0136 return false; 0137 } 0138 return true; 0139 } 0140 }; 0141 0142 static const char *const positiveList[] = { 0143 "BMP", "TIFF", "JP2", "PNM", "EXR", "XBM", "XPM", "ICO", "SVG", "SVGZ", nullptr 0144 }; 0145 0146 bool isSupportedFormat(QString format) 0147 { 0148 QStringList pList; 0149 for (int i = 0; positiveList[i]; i++) { 0150 pList.append(QString::fromLatin1(positiveList[i])); 0151 } 0152 0153 return pList.contains(format, Qt::CaseInsensitive); 0154 } 0155 0156 static QStringList s_formats; 0157 0158 ImageLoaderProvider::Type QImageIOLoaderProvider::type() 0159 { 0160 return Foreign; 0161 } 0162 0163 const QStringList &QImageIOLoaderProvider::mimeTypes() 0164 { 0165 if (!s_formats.isEmpty()) { 0166 return s_formats; 0167 } 0168 0169 // QList<QByteArray> formats = QImageIOReader::supportedFormats(); 0170 KService::List services = KServiceTypeTrader::self()->query("QImageIOPlugins"); 0171 0172 foreach (const KService::Ptr &service, services) { 0173 QStringList formats = service->property("X-KDE-ImageFormat").toStringList(); 0174 QString mimetype = service->property("X-KDE-MimeType").toString(); 0175 bool positive = false; 0176 foreach (const QString &format, formats) { 0177 if (isSupportedFormat(format)) { 0178 positive = true; 0179 break; 0180 } 0181 } 0182 if (!positive) { 0183 continue; 0184 } 0185 if (!mimetype.isEmpty()) { 0186 s_formats.append(mimetype); 0187 // qCDebug(KHTML_LOG) << "QImageIO - Format supported: " << mimetype; 0188 } 0189 } 0190 return s_formats; 0191 } 0192 0193 ImageLoader *QImageIOLoaderProvider::loaderFor(const QByteArray &prefix) 0194 { 0195 QByteArray pref = prefix; 0196 QBuffer prefixBuffer(&pref); 0197 prefixBuffer.open(QIODevice::ReadOnly); 0198 QByteArray format = QImageReader::imageFormat(&prefixBuffer); 0199 prefixBuffer.close(); 0200 if (format.isEmpty() || !isSupportedFormat(format)) { 0201 return nullptr; 0202 } else 0203 // qCDebug(KHTML_LOG) << "QImageIO - Format guessed: " << format; 0204 0205 { 0206 return new QImageIOLoader; 0207 } 0208 } 0209 0210 } // namespace