* GuiImage:

- switch to QImage backend instead of QPixmap. In any case this was done internally by Qt for any image loading or transformation. This should relieve the X11 server a bit for big images.
- try to clear out the memory after a transformation by calling QImage::detach(). Unfortunately there seems to be a bug somewhere in Qt... see (http://bugzilla.lyx.org/show_bug.cgi?id=5002).

* GraphicsImage: get rid of scaledDimension()


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@26455 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Abdelrazak Younes 2008-09-19 11:27:24 +00:00
parent 703756f99c
commit 31c1982677
5 changed files with 64 additions and 61 deletions

View File

@ -23,7 +23,6 @@
#include "support/lstrings.h" // ascii_lowercase
#include <QPainter>
#include <QImage>
#include <QImageReader>
using namespace std;
@ -39,9 +38,14 @@ Image * GuiImage::newImage()
}
GuiImage::GuiImage() : is_transformed_(false)
{}
GuiImage::GuiImage(GuiImage const & other)
: Image(other), original_(other.original_),
transformed_(other.transformed_), is_transformed_(other.is_transformed_)
transformed_(other.transformed_), is_transformed_(other.is_transformed_),
fname_(other.fname_)
{}
@ -51,6 +55,12 @@ Image * GuiImage::clone() const
}
QImage const & GuiImage::image() const
{
return is_transformed_ ? transformed_ : original_;
}
unsigned int GuiImage::width() const
{
return is_transformed_ ? transformed_.width() : original_.width();
@ -69,13 +79,18 @@ bool GuiImage::load(FileName const & filename)
LYXERR(Debug::GRAPHICS, "Image is loaded already!");
return false;
}
fname_ = toqstr(filename.absFilename());
return load();
}
bool GuiImage::load()
{
if (!original_.load(fname_)) {
LYXERR(Debug::GRAPHICS, "Unable to open image");
return false;
}
original_.detach();
return true;
}
@ -86,7 +101,7 @@ bool GuiImage::setPixmap(Params const & params)
return false;
if (original_.isNull()) {
if (!original_.load(fname_))
if (!load())
return false;
}
@ -95,10 +110,13 @@ bool GuiImage::setPixmap(Params const & params)
is_transformed_ |= scale(params);
// Clear the pixmap to save some memory.
if (is_transformed_)
original_ = QPixmap();
else
transformed_ = QPixmap();
if (is_transformed_) {
original_.detach();
original_ = QImage();
} else {
transformed_.detach();
transformed_ = QImage();
}
return true;
}
@ -113,22 +131,23 @@ bool GuiImage::clip(Params const & params)
int const new_width = params.bb.xr - params.bb.xl;
int const new_height = params.bb.yt - params.bb.yb;
QImage const & image = is_transformed_ ? transformed_ : original_;
// No need to check if the width, height are > 0 because the
// Bounding Box would be empty() in this case.
if (new_width > original_.width() || new_height > original_.height()) {
if (new_width > image.width() || new_height > image.height()) {
// Bounds are invalid.
return false;
}
if (new_width == original_.width() && new_height == original_.height())
if (new_width == image.width() && new_height == image.height())
return false;
int const xoffset_l = params.bb.xl;
int const yoffset_t = (original_.height() > int(params.bb.yt) ?
original_.height() - params.bb.yt : 0);
int const yoffset_t = (image.height() > int(params.bb.yt))
? image.height() - params.bb.yt : 0;
transformed_ = original_.copy(xoffset_l, yoffset_t,
new_width, new_height);
transformed_ = image.copy(xoffset_l, yoffset_t, new_width, new_height);
return true;
}
@ -138,30 +157,37 @@ bool GuiImage::rotate(Params const & params)
if (!params.angle)
return false;
if (!is_transformed_)
transformed_ = original_;
QImage const & image = is_transformed_ ? transformed_ : original_;
QMatrix m;
m.rotate(-params.angle);
transformed_ = transformed_.transformed(m);
m.rotate(- params.angle);
transformed_ = image.transformed(m);
return true;
}
bool GuiImage::scale(Params const & params)
{
Dimension dim = scaledDimension(params);
QImage const & image = is_transformed_ ? transformed_ : original_;
if (dim.width() == width() && dim.height() == height())
unsigned int w = image.width();
unsigned int h = image.height();
// scale only when value > 0
if (params.scale > 0) {
w = (w * params.scale) / 100;
h = (h * params.scale) / 100;
}
LYXERR(Debug::GRAPHICS, "\n\tparams.scale : " << params.scale
<< "\n\twidth : " << w
<< "\n\theight : " << h);
if (w == image.width() && h == image.height())
return false;
if (!is_transformed_)
transformed_ = original_;
QMatrix m;
m.scale(double(dim.width()) / width(), double(dim.height()) / height());
transformed_ = transformed_.transformed(m);
m.scale(double(w) / image.width(), double(h) / image.height());
transformed_ = image.transformed(m);
return true;
}

View File

@ -15,7 +15,7 @@
#include "graphics/GraphicsImage.h"
#include <QPixmap>
#include <QImage>
#include <QString>
namespace lyx {
@ -27,9 +27,8 @@ public:
/// Access to this class is through this static method.
static Image * newImage();
/// Retrieve the buffered pixmap.
QPixmap const & pixmap() const
{ return is_transformed_? transformed_ : original_; }
/// Retrieve the rendered image.
QImage const & image() const;
private:
/// Create a copy
@ -44,6 +43,7 @@ private:
* Load the image file into memory.
*/
bool load(support::FileName const & filename);
bool load();
/**
* Finishes the process of modifying transformed_, using
* \c params to decide on color, grayscale etc.
@ -59,16 +59,17 @@ private:
bool scale(Params const & params);
/// Access to the class is through newImage() and clone.
GuiImage() {}
GuiImage();
///
GuiImage(GuiImage const &);
/// The original loaded image.
QPixmap original_;
QImage original_;
/// The transformed image for display.
QPixmap transformed_;
/// Buffer the pixmap itself
QImage transformed_;
///
bool is_transformed_;
///
QString fname_;

View File

@ -263,7 +263,7 @@ void GuiPainter::image(int x, int y, int w, int h, graphics::Image const & i)
if (!isDrawingEnabled())
return;
drawPixmap(x, y, qlimage.pixmap(), 0, 0, w, h);
drawImage(x, y, qlimage.image(), 0, 0, w, h);
}

View File

@ -25,23 +25,5 @@ namespace graphics {
// instance of a viable derived class.
boost::function<Image *()> Image::newImage;
Dimension Image::scaledDimension(Params const & params) const
{
// scale only when value > 0
unsigned int w = width();
unsigned int h = height();
if (params.scale) {
w = (w * params.scale) / 100;
h = (h * params.scale) / 100;
}
LYXERR(Debug::GRAPHICS, "graphics::Image::getScaledDimensions()"
<< "\n\tparams.scale : " << params.scale
<< "\n\twidth : " << w
<< "\n\theight : " << h);
return Dimension(w, h, 0);
}
} // namespace graphics
} // namespace lyx

View File

@ -85,12 +85,6 @@ protected:
Image() {}
/// Don't copy the signal finishedLoading
Image(Image const &) {}
/** Uses the params to ascertain the dimensions of the scaled image.
* Returned as Dimension(width, height, 0 descend).
* If something goes wrong, returns make_pair(getWidth(), getHeight(), 0)
*/
Dimension scaledDimension(Params const & params) const;
};