]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiImage.cpp
9f45680e5d54ef6fc1eab6031d595676a28dad18
[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 "Format.h"
18
19 #include "graphics/GraphicsParams.h"
20
21 #include "support/debug.h"
22 #include "support/FileName.h"
23 #include "support/lstrings.h"       // ascii_lowercase
24
25 #include <QPainter>
26 #include <QImage>
27 #include <QImageReader>
28
29 using namespace std;
30 using namespace lyx::support;
31
32 namespace lyx {
33 namespace graphics {
34
35 /// Access to this class is through this static method.
36 Image * GuiImage::newImage()
37 {
38         return new GuiImage;
39 }
40
41
42 GuiImage::GuiImage(GuiImage const & other)
43         : Image(other), original_(other.original_),
44           transformed_(other.transformed_),
45           transformed_pixmap_(other.transformed_pixmap_)
46 {}
47
48
49 Image * GuiImage::clone() const
50 {
51         return new GuiImage(*this);
52 }
53
54
55 unsigned int GuiImage::width() const
56 {
57         return transformed_.width();
58 }
59
60
61 unsigned int GuiImage::height() const
62 {
63         return transformed_.height();
64 }
65
66
67 bool GuiImage::load(FileName const & filename)
68 {
69         if (!original_.isNull()) {
70                 LYXERR(Debug::GRAPHICS, "Image is loaded already!");
71                 return false;
72         }
73
74         if (!original_.load(toqstr(filename.absFilename()))) {
75                 LYXERR(Debug::GRAPHICS, "Unable to open image");
76                 return false;
77         }
78         transformed_ = original_;
79         return true;
80 }
81
82
83 // This code is taken from KImageEffect::toGray
84 static QImage & toGray(QImage & img)
85 {
86         if (img.width() == 0 || img.height() == 0)
87                 return img;
88
89         int const pixels = img.depth() > 8 ?
90                 img.width() * img.height() : img.numColors();
91
92         unsigned int *data = img.depth() > 8 ?
93                 reinterpret_cast<unsigned int *>(img.bits()) :
94                 reinterpret_cast<unsigned int *>(&img.colorTable()[0]);
95
96         for(int i = 0; i < pixels; ++i){
97                 int const val = qGray(data[i]);
98                 data[i] = qRgba(val, val, val, qAlpha(data[i]));
99         }
100         return img;
101 }
102
103
104 bool GuiImage::setPixmap(Params const & params)
105 {
106         if (original_.isNull() || params.display == NoDisplay)
107                 return false;
108
109         switch (params.display) {
110         case GrayscaleDisplay: {
111                 toGray(transformed_);
112                 break;
113         }
114
115         case MonochromeDisplay: {
116                 transformed_.convertToFormat(transformed_.format(), Qt::MonoOnly);
117                 break;
118         }
119
120         default:
121                 break;
122         }
123
124         transformed_pixmap_ = QPixmap::fromImage(transformed_);
125         return true;
126 }
127
128
129 void GuiImage::clip(Params const & params)
130 {
131         if (transformed_.isNull())
132                 return;
133
134         if (params.bb.empty())
135                 // No clipping is necessary.
136                 return;
137
138         int const new_width  = params.bb.xr - params.bb.xl;
139         int const new_height = params.bb.yt - params.bb.yb;
140
141         // No need to check if the width, height are > 0 because the
142         // Bounding Box would be empty() in this case.
143         if (new_width > original_.width() || new_height > original_.height()) {
144                 // Bounds are invalid.
145                 return;
146         }
147
148         if (new_width == original_.width() && new_height == original_.height())
149                 return;
150
151         int const xoffset_l = params.bb.xl;
152         int const yoffset_t = (original_.height() > int(params.bb.yt) ?
153                                original_.height() - params.bb.yt : 0);
154
155         transformed_ = original_.copy(xoffset_l, yoffset_t,
156                                       new_width, new_height);
157 }
158
159
160 void GuiImage::rotate(Params const & params)
161 {
162         if (transformed_.isNull())
163                 return;
164
165         if (!params.angle)
166                 return;
167
168         QMatrix m;
169         m.rotate(-params.angle);
170
171         transformed_ = transformed_.transformed(m);
172 }
173
174
175 void GuiImage::scale(Params const & params)
176 {
177         if (transformed_.isNull())
178                 return;
179
180         Dimension dim = scaledDimension(params);
181
182         if (dim.width() == width() && dim.height() == height())
183                 return;
184
185         QMatrix m;
186         m.scale(double(dim.width()) / width(), double(dim.height()) / height());
187         transformed_ = transformed_.transformed(m);
188 }
189
190 } // namespace graphics
191 } // lyx