KHtml

qimageioloader.cpp
1 /*
2  Large image load library -- QImageIO decoder
3 
4  Copyright (C) 2007-2009 Allan Sandfeld Jensen <[email protected]>
5 
6  Permission is hereby granted, free of charge, to any person obtaining a copy
7  of this software and associated documentation files (the "Software"), to deal
8  in the Software without restriction, including without limitation the rights
9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  copies of the Software, and to permit persons to whom the Software is
11  furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20  AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 
23 */
24 
25 #include <QBuffer>
26 #include <QByteArray>
27 #include <QStringList>
28 #include <QImageReader>
29 
30 #include "qimageioloader.h"
31 #include "imageloader.h"
32 #include "kservice.h"
33 #include "kservicetypetrader.h"
34 #include "QDebug"
35 #include "imagemanager.h"
36 
37 namespace khtmlImLoad
38 {
39 
40 class QImageIOLoader: public ImageLoader
41 {
42  QByteArray array;
43  QImage image;
44 public:
45  QImageIOLoader()
46  {
47  }
48 
49  ~QImageIOLoader()
50  {
51  }
52 
53  int processData(uchar *data, int length) override
54  {
55  //Collect data in the buffer
56  int pos = array.size();
57  array.resize(array.size() + length);
58  memcpy(array.data() + pos, data, length);
59  return length;
60  }
61 
62  int processEOF() override
63  {
64  QBuffer buffer(&array);
65  buffer.open(QIODevice::ReadOnly);
66 
67  QByteArray qformat = QImageReader::imageFormat(&buffer);
68  QImageReader reader(&buffer, qformat);
69 
70  if (!reader.canRead()) {
71  return Error;
72  }
73 
74  QSize size = reader.size();
75  if (size.isValid()) {
76  if (ImageManager::isAcceptableSize(size.width(), size.height())) {
77  notifyImageInfo(size.width(), size.height());
78  } else {
79  return Error;
80  }
81  }
82 
83  const bool readSuccess = !reader.read(&image);
84  // It happens sometimes that even QImageReader said it failed to read
85  // it did actually read something,
86  // e.g. image from https://bugs.kde.org/show_bug.cgi?id=441554
87  // so if the image has a size, pretend it succeeded
88  if (!size.isValid()) {
89  if (!readSuccess) {
90  return Error;
91  }
92 
93  // Might be too late by now..
94  if (ImageManager::isAcceptableSize(image.width(), image.height())) {
95  notifyImageInfo(image.width(), image.height());
96  } else {
97  return Error;
98  }
99  }
100 
101  ImageFormat format;
102  if (!imageFormat(image, format)) {
103  return Error;
104  }
105  notifyAppendFrame(image.width(), image.height(), format);
106 
107  notifyQImage(1, &image);
108 
109  return Done;
110  }
111  bool imageFormat(QImage &image, ImageFormat &format)
112  {
113  switch (image.format()) {
115  format.type = ImageFormat::Image_RGB_32;
116  break;
118  format.type = ImageFormat::Image_ARGB_32_DontPremult;
119  break;
121  format.type = ImageFormat::Image_ARGB_32;
122  break;
124  format.type = ImageFormat::Image_Palette_8;
125  format.palette = image.colorTable();
126  break;
127  case QImage::Format_Mono:
130  format.type = ImageFormat::Image_Palette_8;
131  format.palette = image.colorTable();
132  break;
134  default:
135  // unsupported formats
136  return false;
137  }
138  return true;
139  }
140 };
141 
142 static const char *const positiveList[] = {
143  "BMP", "TIFF", "JP2", "PNM", "EXR", "XBM", "XPM", "ICO", "SVG", "SVGZ", nullptr
144 };
145 
146 bool isSupportedFormat(QString format)
147 {
148  QStringList pList;
149  for (int i = 0; positiveList[i]; i++) {
150  pList.append(QString::fromLatin1(positiveList[i]));
151  }
152 
153  return pList.contains(format, Qt::CaseInsensitive);
154 }
155 
156 static QStringList s_formats;
157 
158 ImageLoaderProvider::Type QImageIOLoaderProvider::type()
159 {
160  return Foreign;
161 }
162 
163 const QStringList &QImageIOLoaderProvider::mimeTypes()
164 {
165  if (!s_formats.isEmpty()) {
166  return s_formats;
167  }
168 
169 // QList<QByteArray> formats = QImageIOReader::supportedFormats();
170  KService::List services = KServiceTypeTrader::self()->query("QImageIOPlugins");
171 
172  foreach (const KService::Ptr &service, services) {
173  QStringList formats = service->property("X-KDE-ImageFormat").toStringList();
174  QString mimetype = service->property("X-KDE-MimeType").toString();
175  bool positive = false;
176  foreach (const QString &format, formats) {
177  if (isSupportedFormat(format)) {
178  positive = true;
179  break;
180  }
181  }
182  if (!positive) {
183  continue;
184  }
185  if (!mimetype.isEmpty()) {
186  s_formats.append(mimetype);
187  // qCDebug(KHTML_LOG) << "QImageIO - Format supported: " << mimetype;
188  }
189  }
190  return s_formats;
191 }
192 
193 ImageLoader *QImageIOLoaderProvider::loaderFor(const QByteArray &prefix)
194 {
195  QByteArray pref = prefix;
196  QBuffer prefixBuffer(&pref);
197  prefixBuffer.open(QIODevice::ReadOnly);
198  QByteArray format = QImageReader::imageFormat(&prefixBuffer);
199  prefixBuffer.close();
200  if (format.isEmpty() || !isSupportedFormat(format)) {
201  return nullptr;
202  } else
203  // qCDebug(KHTML_LOG) << "QImageIO - Format guessed: " << format;
204 
205  {
206  return new QImageIOLoader;
207  }
208 }
209 
210 } // namespace
void notifyImageInfo(int width, int height)
Call to declare canvas geometry and format.
Definition: imageloader.h:53
QImage convertToFormat(QImage::Format format, Qt::ImageConversionFlags flags) const &const
bool isValid() const const
int width() const const
static KServiceTypeTrader * self()
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QImage::Format imageFormat() const const
void resize(int size)
void append(const T &value)
int width() const const
CaseInsensitive
bool isEmpty() const const
bool isEmpty() const const
KIOCORE_EXPORT MimetypeJob * mimetype(const QUrl &url, JobFlags flags=DefaultFlags)
void notifyAppendFrame(int fwidth, int fheight, const ImageFormat &format)
Call to declare frame geometry, should be called for each frame.
Definition: imageloader.h:61
KService::List query(const QString &servicetype, const QString &constraint=QString()) const
int height() const const
char * data()
QString fromLatin1(const char *str, int size)
int height() const const
int size() const const
QImage::Format format() const const
QVector< QRgb > colorTable() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:06 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.