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"
20 #include "graphics/GraphicsParams.h"
22 #include "support/FileName.h"
23 #include "support/lstrings.h" // ascii_lowercase
27 #include <QImageReader>
29 #include <boost/bind.hpp>
30 #include <boost/tuple/tuple.hpp>
32 using lyx::support::ascii_lowercase;
44 /// Access to this class is through this static method.
45 Image * GuiImage::newImage()
51 /// Return the list of loadable formats.
52 Image::FormatList GuiImage::loadableFormats()
54 static FormatList fmts;
59 // The formats recognised by LyX
60 Formats::const_iterator begin = formats.begin();
61 Formats::const_iterator end = formats.end();
64 // LYXERR(Debug::GRAPHICS,
65 // "D:/msys/home/yns/src/lyx-devel/lib/images/banner.png mis of format: "
66 // << fromqstr(Pic.pictureFormat("D:/msys/home/yns/src/lyx-devel/lib/images/banner.png")))
67 // if (Pic.pictureFormat("D:/msys/home/yns/src/lyx-devel/lib/images/banner.png"))
68 // LYXERR(Debug::GRAPHICS, "pictureFormat not returned NULL\n"
69 // << "Supported formats are: " << Pic.inputFormats());
71 QList<QByteArray> qt_formats = QImageReader::supportedImageFormats();
73 LYXERR(Debug::GRAPHICS,
74 "\nThe image loader can load the following directly:\n");
76 if (qt_formats.empty())
77 LYXERR(Debug::GRAPHICS, "\nQt4 Problem: No Format available!");
79 for (QList<QByteArray>::const_iterator it = qt_formats.begin(); it != qt_formats.end(); ++it) {
81 LYXERR(Debug::GRAPHICS, (const char *) *it << ", ");
83 string ext = ascii_lowercase((const char *) *it);
89 Formats::const_iterator fit =
91 bind(equal_to<string>(),
92 bind(&Format::extension, _1),
95 fmts.push_back(fit->name());
98 if (lyxerr.debugging()) {
99 LYXERR(Debug::GRAPHICS, "\nOf these, LyX recognises the following formats:");
101 FormatList::const_iterator fbegin = fmts.begin();
102 FormatList::const_iterator fend = fmts.end();
103 for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
105 LYXERR(Debug::GRAPHICS, ", ");
106 LYXERR(Debug::GRAPHICS, *fit);
108 LYXERR(Debug::GRAPHICS, '\n');
115 GuiImage::GuiImage(GuiImage const & other)
116 : Image(other), original_(other.original_),
117 transformed_(other.transformed_),
118 transformed_pixmap_(other.transformed_pixmap_)
122 Image * GuiImage::clone() const
124 return new GuiImage(*this);
128 unsigned int GuiImage::getWidth() const
130 return transformed_.width();
134 unsigned int GuiImage::getHeight() const
136 return transformed_.height();
140 void GuiImage::load(support::FileName const & filename)
142 if (!original_.isNull()) {
143 LYXERR(Debug::GRAPHICS, "Image is loaded already!");
144 finishedLoading(false);
148 if (!original_.load(toqstr(filename.absFilename()))) {
149 LYXERR(Debug::GRAPHICS, "Unable to open image");
150 finishedLoading(false);
153 transformed_ = original_;
154 finishedLoading(true);
158 // This code is taken from KImageEffect::toGray
159 static QImage & toGray(QImage & img)
161 if (img.width() == 0 || img.height() == 0)
164 int const pixels = img.depth() > 8 ?
165 img.width() * img.height() : img.numColors();
167 unsigned int *data = img.depth() > 8 ?
168 reinterpret_cast<unsigned int *>(img.bits()) :
169 reinterpret_cast<unsigned int *>(&img.colorTable()[0]);
171 for(int i = 0; i < pixels; ++i){
172 int const val = qGray(data[i]);
173 data[i] = qRgba(val, val, val, qAlpha(data[i]));
179 bool GuiImage::setPixmap(Params const & params)
181 if (original_.isNull() || params.display == NoDisplay)
184 switch (params.display) {
185 case GrayscaleDisplay: {
186 toGray(transformed_);
190 case MonochromeDisplay: {
191 transformed_.convertToFormat(transformed_.format(), Qt::MonoOnly);
199 transformed_pixmap_ = QPixmap::fromImage(transformed_);
204 void GuiImage::clip(Params const & params)
206 if (transformed_.isNull())
209 if (params.bb.empty())
210 // No clipping is necessary.
213 int const new_width = params.bb.xr - params.bb.xl;
214 int const new_height = params.bb.yt - params.bb.yb;
216 // No need to check if the width, height are > 0 because the
217 // Bounding Box would be empty() in this case.
218 if (new_width > original_.width() || new_height > original_.height()) {
219 // Bounds are invalid.
223 if (new_width == original_.width() && new_height == original_.height())
226 int const xoffset_l = params.bb.xl;
227 int const yoffset_t = (original_.height() > int(params.bb.yt) ?
228 original_.height() - params.bb.yt : 0);
230 transformed_ = original_.copy(xoffset_l, yoffset_t,
231 new_width, new_height);
235 void GuiImage::rotate(Params const & params)
237 if (transformed_.isNull())
244 m.rotate(-params.angle);
246 transformed_ = transformed_.transformed(m);
250 void GuiImage::scale(Params const & params)
252 if (transformed_.isNull())
257 boost::tie(width, height) = getScaledDimensions(params);
259 if (width == getWidth() && height == getHeight())
263 m.scale(double(width) / getWidth(), double(height) / getHeight());
264 transformed_ = transformed_.transformed(m);
267 } // namespace graphics