]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiImage.cpp
cosmetics
[lyx.git] / src / frontends / qt4 / GuiImage.cpp
1 /**
2  * \file GuiImage.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  * \author John Levon
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiImage.h"
15 #include "qt_helpers.h"
16
17 #include "debug.h"
18 #include "Format.h"
19
20 #include "graphics/GraphicsParams.h"
21
22 #include "support/FileName.h"
23 #include "support/lstrings.h"       // ascii_lowercase
24
25 #include <QPainter>
26 #include <QImage>
27 #include <QImageReader>
28
29 #include <boost/bind.hpp>
30 #include <boost/tuple/tuple.hpp>
31
32 using lyx::support::ascii_lowercase;
33
34 using boost::bind;
35
36 using std::endl;
37 using std::equal_to;
38 using std::find_if;
39 using std::string;
40
41 namespace lyx {
42 namespace graphics {
43
44 /// Access to this class is through this static method.
45 Image::ImagePtr GuiImage::newImage()
46 {
47         ImagePtr ptr;
48         ptr.reset(new GuiImage);
49         return ptr;
50 }
51
52
53 /// Return the list of loadable formats.
54 Image::FormatList GuiImage::loadableFormats()
55 {
56         static FormatList fmts;
57
58         if (!fmts.empty())
59                 return fmts;
60
61         // The formats recognised by LyX
62         Formats::const_iterator begin = formats.begin();
63         Formats::const_iterator end   = formats.end();
64
65
66 //      LYXERR(Debug::GRAPHICS,
67 //              "D:/msys/home/yns/src/lyx-devel/lib/images/banner.png mis of format: "
68 //              << fromqstr(Pic.pictureFormat("D:/msys/home/yns/src/lyx-devel/lib/images/banner.png")))
69 //      if (Pic.pictureFormat("D:/msys/home/yns/src/lyx-devel/lib/images/banner.png"))
70 //              LYXERR(Debug::GRAPHICS, "pictureFormat not returned NULL\n"
71 //                      << "Supported formats are: " << Pic.inputFormats());
72
73         QList<QByteArray> qt_formats = QImageReader::supportedImageFormats();
74
75         LYXERR(Debug::GRAPHICS,
76                 "\nThe image loader can load the following directly:\n");
77
78         if (qt_formats.empty())
79                 LYXERR(Debug::GRAPHICS, "\nQt4 Problem: No Format available!");
80
81         for (QList<QByteArray>::const_iterator it = qt_formats.begin(); it != qt_formats.end(); ++it) {
82
83                 LYXERR(Debug::GRAPHICS, (const char *) *it << ", ");
84
85                 string ext = ascii_lowercase((const char *) *it);
86
87                 // special case
88                 if (ext == "jpeg")
89                         ext = "jpg";
90
91                 Formats::const_iterator fit =
92                         find_if(begin, end,
93                                 bind(equal_to<string>(),
94                                      bind(&Format::extension, _1),
95                                      ext));
96                 if (fit != end)
97                         fmts.push_back(fit->name());
98         }
99
100         if (lyxerr.debugging()) {
101                 LYXERR(Debug::GRAPHICS, "\nOf these, LyX recognises the following formats:");
102
103                 FormatList::const_iterator fbegin = fmts.begin();
104                 FormatList::const_iterator fend   = fmts.end();
105                 for (FormatList::const_iterator fit = fbegin; fit != fend; ++fit) {
106                         if (fit != fbegin)
107                                 LYXERR(Debug::GRAPHICS, ", ");
108                         LYXERR(Debug::GRAPHICS, *fit);
109                 }
110                 LYXERR(Debug::GRAPHICS, '\n');
111         }
112
113         return fmts;
114 }
115
116
117 GuiImage::GuiImage(GuiImage const & other)
118         : Image(other), original_(other.original_),
119           transformed_(other.transformed_),
120           transformed_pixmap_(other.transformed_pixmap_)
121 {}
122
123
124 Image * GuiImage::clone() const
125 {
126         return new GuiImage(*this);
127 }
128
129
130 unsigned int GuiImage::getWidth() const
131 {
132         return transformed_.width();
133 }
134
135
136 unsigned int GuiImage::getHeight() const
137 {
138         return transformed_.height();
139 }
140
141
142 void GuiImage::load(support::FileName const & filename)
143 {
144         if (!original_.isNull()) {
145                 LYXERR(Debug::GRAPHICS, "Image is loaded already!");
146                 finishedLoading(false);
147                 return;
148         }
149
150         if (!original_.load(toqstr(filename.absFilename()))) {
151                 LYXERR(Debug::GRAPHICS, "Unable to open image");
152                 finishedLoading(false);
153                 return;
154         }
155         transformed_ = original_;
156         finishedLoading(true);
157 }
158
159
160 // This code is taken from KImageEffect::toGray
161 static QImage & toGray(QImage & img)
162 {
163         if (img.width() == 0 || img.height() == 0)
164                 return img;
165
166         int const pixels = img.depth() > 8 ?
167                 img.width() * img.height() : img.numColors();
168
169         unsigned int *data = img.depth() > 8 ?
170                 reinterpret_cast<unsigned int *>(img.bits()) :
171                 reinterpret_cast<unsigned int *>(&img.colorTable()[0]);
172
173         for(int i = 0; i < pixels; ++i){
174                 int const val = qGray(data[i]);
175                 data[i] = qRgba(val, val, val, qAlpha(data[i]));
176         }
177         return img;
178 }
179
180
181 bool GuiImage::setPixmap(Params const & params)
182 {
183         if (original_.isNull() || params.display == NoDisplay)
184                 return false;
185
186         switch (params.display) {
187         case GrayscaleDisplay: {
188                 toGray(transformed_);
189                 break;
190         }
191
192         case MonochromeDisplay: {
193                 transformed_.convertToFormat(transformed_.format(), Qt::MonoOnly);
194                 break;
195         }
196
197         default:
198                 break;
199         }
200
201         transformed_pixmap_ = QPixmap::fromImage(transformed_);
202         return true;
203 }
204
205
206 void GuiImage::clip(Params const & params)
207 {
208         if (transformed_.isNull())
209                 return;
210
211         if (params.bb.empty())
212                 // No clipping is necessary.
213                 return;
214
215         int const new_width  = params.bb.xr - params.bb.xl;
216         int const new_height = params.bb.yt - params.bb.yb;
217
218         // No need to check if the width, height are > 0 because the
219         // Bounding Box would be empty() in this case.
220         if (new_width > original_.width() || new_height > original_.height()) {
221                 // Bounds are invalid.
222                 return;
223         }
224
225         if (new_width == original_.width() && new_height == original_.height())
226                 return;
227
228         int const xoffset_l = params.bb.xl;
229         int const yoffset_t = (original_.height() > int(params.bb.yt) ?
230                                original_.height() - params.bb.yt : 0);
231
232         transformed_ = original_.copy(xoffset_l, yoffset_t,
233                                       new_width, new_height);
234 }
235
236
237 void GuiImage::rotate(Params const & params)
238 {
239         if (transformed_.isNull())
240                 return;
241
242         if (!params.angle)
243                 return;
244
245         QMatrix m;
246         m.rotate(-params.angle);
247
248         transformed_ = transformed_.transformed(m);
249 }
250
251
252 void GuiImage::scale(Params const & params)
253 {
254         if (transformed_.isNull())
255                 return;
256
257         unsigned int width;
258         unsigned int height;
259         boost::tie(width, height) = getScaledDimensions(params);
260
261         if (width == getWidth() && height == getHeight())
262                 return;
263
264         QMatrix m;
265         m.scale(double(width) / getWidth(), double(height) / getHeight());
266         transformed_ = transformed_.transformed(m);
267 }
268
269 } // namespace graphics
270 } // lyx