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
29 #include <QImageReader>
31 #include <boost/bind.hpp>
32 #include <boost/tuple/tuple.hpp>
34 using lyx::support::ascii_lowercase;
43 QPictureIO StaticPicture;
48 /// Access to this class is through this static method.
49 Image::ImagePtr GuiImage::newImage()
52 ptr.reset(new GuiImage);
57 /// Return the list of loadable formats.
58 Image::FormatList GuiImage::loadableFormats()
60 static FormatList fmts;
65 // The formats recognised by LyX
66 Formats::const_iterator begin = formats.begin();
67 Formats::const_iterator end = formats.end();
70 // LYXERR(Debug::GRAPHICS)
71 // << "D:/msys/home/yns/src/lyx-devel/lib/images/banner.png mis of format: "
72 // << fromqstr(Pic.pictureFormat("D:/msys/home/yns/src/lyx-devel/lib/images/banner.png"))
74 // if (Pic.pictureFormat("D:/msys/home/yns/src/lyx-devel/lib/images/banner.png"))
75 // LYXERR(Debug::GRAPHICS)
76 // << "pictureFormat not returned NULL\n" << endl;
77 // << "Supported formats are: " << Pic.inputFormats() << endl;
79 QList<QByteArray> qt_formats = QImageReader::supportedImageFormats ();
81 LYXERR(Debug::GRAPHICS)
82 << "\nThe image loader can load the following directly:\n";
84 if (qt_formats.empty())
85 LYXERR(Debug::GRAPHICS)
86 << "\nQt4 Problem: No Format available!" << endl;
88 for (QList<QByteArray>::const_iterator it =qt_formats.begin(); it != qt_formats.end(); ++it) {
90 LYXERR(Debug::GRAPHICS) << (const char *) *it << ", ";
92 string ext = ascii_lowercase((const char *) *it);
98 Formats::const_iterator fit =
100 bind(equal_to<string>(),
101 bind(&Format::extension, _1),
104 fmts.push_back(fit->name());
107 if (lyxerr.debugging()) {
108 LYXERR(Debug::GRAPHICS)
109 << "\nOf these, LyX recognises the following formats:\n";
111 FormatList::const_iterator fbegin = fmts.begin();
112 FormatList::const_iterator fend = fmts.end();
113 for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
115 LYXERR(Debug::GRAPHICS) << ", ";
116 LYXERR(Debug::GRAPHICS) << *fit;
118 LYXERR(Debug::GRAPHICS) << '\n' << endl;
125 GuiImage::GuiImage(GuiImage const & other)
126 : Image(other), original_(other.original_),
127 transformed_(other.transformed_),
128 transformed_pixmap_(other.transformed_pixmap_)
132 Image * GuiImage::clone_impl() const
134 return new GuiImage(*this);
138 unsigned int GuiImage::getWidth_impl() const
140 return transformed_.width();
144 unsigned int GuiImage::getHeight_impl() const
146 return transformed_.height();
150 void GuiImage::load_impl(support::FileName const & filename)
152 if (!original_.isNull()) {
153 LYXERR(Debug::GRAPHICS)
154 << "Image is loaded already!" << endl;
155 finishedLoading(false);
159 if (!original_.load(toqstr(filename.absFilename()))) {
160 LYXERR(Debug::GRAPHICS)
161 << "Unable to open image" << endl;
162 finishedLoading(false);
165 transformed_ = original_;
166 finishedLoading(true);
172 // This code is taken from KImageEffect::toGray
173 QImage & toGray(QImage & img)
175 if (img.width() == 0 || img.height() == 0)
178 int const pixels = img.depth() > 8 ?
179 img.width() * img.height() : img.numColors();
181 unsigned int *data = img.depth() > 8 ?
182 reinterpret_cast<unsigned int *>(img.bits()) :
183 reinterpret_cast<unsigned int *>(&img.colorTable()[0]);
185 for(int i = 0; i < pixels; ++i){
186 int const val = qGray(data[i]);
187 data[i] = qRgba(val, val, val, qAlpha(data[i]));
195 bool GuiImage::setPixmap_impl(Params const & params)
197 if (original_.isNull() || params.display == NoDisplay)
200 switch (params.display) {
201 case GrayscaleDisplay: {
202 toGray(transformed_);
206 case MonochromeDisplay: {
207 transformed_.convertToFormat(transformed_.format(), Qt::MonoOnly);
215 transformed_pixmap_ = QPixmap::fromImage(transformed_);
220 void GuiImage::clip_impl(Params const & params)
222 if (transformed_.isNull())
225 if (params.bb.empty())
226 // No clipping is necessary.
229 int const new_width = params.bb.xr - params.bb.xl;
230 int const new_height = params.bb.yt - params.bb.yb;
232 // No need to check if the width, height are > 0 because the
233 // Bounding Box would be empty() in this case.
234 if (new_width > original_.width() || new_height > original_.height()) {
235 // Bounds are invalid.
239 if (new_width == original_.width() && new_height == original_.height())
242 int const xoffset_l = params.bb.xl;
243 int const yoffset_t = (original_.height() > int(params.bb.yt) ?
244 original_.height() - params.bb.yt : 0);
246 transformed_ = original_.copy(xoffset_l, yoffset_t,
247 new_width, new_height);
251 void GuiImage::rotate_impl(Params const & params)
253 if (transformed_.isNull())
260 m.rotate(-params.angle);
262 transformed_ = transformed_.transformed(m);
266 void GuiImage::scale_impl(Params const & params)
268 if (transformed_.isNull())
273 boost::tie(width, height) = getScaledDimensions(params);
275 if (width == getWidth() && height == getHeight())
279 m.scale(double(width) / getWidth(), double(height) / getHeight());
280 transformed_ = transformed_.transformed(m);
283 } // namespace graphics