3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
9 * Full author contact details are available in file CREDITS.
15 #include "qt_helpers.h"
19 #include "graphics/GraphicsParams.h"
21 #include "support/debug.h"
22 #include "support/FileName.h"
23 #include "support/lstrings.h" // ascii_lowercase
27 #include <QImageReader>
30 using namespace lyx::support;
35 /// Access to this class is through this static method.
36 Image * GuiImage::newImage()
42 /// Return the list of loadable formats.
43 Image::FormatList GuiImage::loadableFormats()
45 static FormatList fmts;
50 // The formats recognised by LyX
51 Formats::const_iterator begin = formats.begin();
52 Formats::const_iterator end = formats.end();
54 //LYXERR(Debug::GRAPHICS,
55 // "D:/msys/home/yns/src/lyx-devel/lib/images/banner.png mis of format: "
56 // << fromqstr(Pic.pictureFormat("D:/msys/.../banner.png")))
57 //if (Pic.pictureFormat("D:/msys/.../banner.png"))
58 // LYXERR(Debug::GRAPHICS, "pictureFormat not returned NULL\n"
59 // << "Supported formats are: " << Pic.inputFormats());
61 QList<QByteArray> qt_formats = QImageReader::supportedImageFormats();
63 LYXERR(Debug::GRAPHICS,
64 "\nThe image loader can load the following directly:\n");
66 if (qt_formats.empty())
67 LYXERR(Debug::GRAPHICS, "\nQt4 Problem: No Format available!");
69 for (QList<QByteArray>::const_iterator it = qt_formats.begin(); it != qt_formats.end(); ++it) {
71 LYXERR(Debug::GRAPHICS, (const char *) *it << ", ");
73 string ext = ascii_lowercase((const char *) *it);
79 for (Formats::const_iterator fit = begin; fit != end; ++fit)
80 if (fit->extension() == ext) {
81 fmts.push_back(fit->name());
86 if (lyxerr.debugging()) {
87 LYXERR(Debug::GRAPHICS, "Of these, LyX recognises the following formats:");
89 FormatList::const_iterator fbegin = fmts.begin();
90 FormatList::const_iterator fend = fmts.end();
91 for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
93 LYXERR(Debug::GRAPHICS, ", ");
94 LYXERR(Debug::GRAPHICS, *fit);
96 LYXERR(Debug::GRAPHICS, '\n');
103 GuiImage::GuiImage(GuiImage const & other)
104 : Image(other), original_(other.original_),
105 transformed_(other.transformed_),
106 transformed_pixmap_(other.transformed_pixmap_)
110 Image * GuiImage::clone() const
112 return new GuiImage(*this);
116 unsigned int GuiImage::width() const
118 return transformed_.width();
122 unsigned int GuiImage::height() const
124 return transformed_.height();
128 void GuiImage::load(FileName const & filename)
130 if (!original_.isNull()) {
131 LYXERR(Debug::GRAPHICS, "Image is loaded already!");
132 finishedLoading(false);
136 if (!original_.load(toqstr(filename.absFilename()))) {
137 LYXERR(Debug::GRAPHICS, "Unable to open image");
138 finishedLoading(false);
141 transformed_ = original_;
142 finishedLoading(true);
146 // This code is taken from KImageEffect::toGray
147 static QImage & toGray(QImage & img)
149 if (img.width() == 0 || img.height() == 0)
152 int const pixels = img.depth() > 8 ?
153 img.width() * img.height() : img.numColors();
155 unsigned int *data = img.depth() > 8 ?
156 reinterpret_cast<unsigned int *>(img.bits()) :
157 reinterpret_cast<unsigned int *>(&img.colorTable()[0]);
159 for(int i = 0; i < pixels; ++i){
160 int const val = qGray(data[i]);
161 data[i] = qRgba(val, val, val, qAlpha(data[i]));
167 bool GuiImage::setPixmap(Params const & params)
169 if (original_.isNull() || params.display == NoDisplay)
172 switch (params.display) {
173 case GrayscaleDisplay: {
174 toGray(transformed_);
178 case MonochromeDisplay: {
179 transformed_.convertToFormat(transformed_.format(), Qt::MonoOnly);
187 transformed_pixmap_ = QPixmap::fromImage(transformed_);
192 void GuiImage::clip(Params const & params)
194 if (transformed_.isNull())
197 if (params.bb.empty())
198 // No clipping is necessary.
201 int const new_width = params.bb.xr - params.bb.xl;
202 int const new_height = params.bb.yt - params.bb.yb;
204 // No need to check if the width, height are > 0 because the
205 // Bounding Box would be empty() in this case.
206 if (new_width > original_.width() || new_height > original_.height()) {
207 // Bounds are invalid.
211 if (new_width == original_.width() && new_height == original_.height())
214 int const xoffset_l = params.bb.xl;
215 int const yoffset_t = (original_.height() > int(params.bb.yt) ?
216 original_.height() - params.bb.yt : 0);
218 transformed_ = original_.copy(xoffset_l, yoffset_t,
219 new_width, new_height);
223 void GuiImage::rotate(Params const & params)
225 if (transformed_.isNull())
232 m.rotate(-params.angle);
234 transformed_ = transformed_.transformed(m);
238 void GuiImage::scale(Params const & params)
240 if (transformed_.isNull())
243 Dimension dim = scaledDimension(params);
245 if (dim.width() == width() && dim.height() == height())
249 m.scale(double(dim.width()) / width(), double(dim.height()) / height());
250 transformed_ = transformed_.transformed(m);
253 } // namespace graphics