Rescaling Gtk::Image
- From: Sohail Somani <sohail taggedtype net>
- To: gtkmm-list gnome org
- Subject: Rescaling Gtk::Image
- Date: Mon, 23 Jun 2008 22:17:25 -0700
Looking for any feedback. This code works just fine for my purposes but
I was kind of hoping for a Gtk review. Thanks in advance!
Originally posted here:
http://uint32t.blogspot.com/2008/06/automatically-rescale-gtkimage-and.html
/*
Problem:
Using GTK, display an image in a window and rescale when the window
resizes preserving the aspect ratio.
Analysis:
Gtk provides Gtk::Image which works on a Gdk::Pixbuf (pixel buffer)
which allows rescaling but without preserving aspect ratio.
Summary of solution:
Use a Gtk::Image embedded in a Gtk::AspectFrame and resize image
using dimensions determined by Gtk::AspectFrame. The AspectFrame
knows how to maintain a ratio so it does the messy work for us.
*/
#include <gtkmm.h>
#include <iostream>
/// This Widget only scales the image but does not preserve
/// aspect ratios.
struct ScalingImage : public Gtk::Image
{
explicit
ScalingImage(Glib::RefPtr<Gdk::Pixbuf> pixbuf,
Gdk::InterpType interp = Gdk::INTERP_BILINEAR):
Gtk::Image(pixbuf),
m_original(pixbuf),
m_interp(interp),
m_sized(false)
{
}
protected:
virtual
void
on_size_allocate(Gtk::Allocation & r)
{
// This event is fired on all Widgets when their rectangle gets
// resized. So we rescale our image. But rescaling our image fires
// another resize event, and another, and another... You see the
// problem!
//
// The most straightforward solution is to not rescale the image
// the second time the event is fired. Hence the m_size toggle.
//
// Ideally I'd not like to do this but this was the best way I
// found!
if(!m_sized)
{
Glib::RefPtr<Gdk::Pixbuf> scaled =
m_original->scale_simple(r.get_width(),
r.get_height(),
m_interp);
// Reset the image to be the new scaled image which
// will cause the second size-allocate signal
Gtk::Image::set(scaled);
// Make sure we don't treat it as a rescale request
// next time
m_sized = true;
}
else
{
// Reaction to set above. Call the base class's on_size_allocate
// function. Shouldn't I have to call this above too? Maybe it
// isn't necessary since it gets called anyway.
Gtk::Image::on_size_allocate(r);
// Treat next resize event as a rescale
m_sized = false;
}
}
private:
Glib::RefPtr<Gdk::Pixbuf> m_original;
Gdk::InterpType m_interp;
bool m_sized;
};
/// This widget automatically scales the image but preserves the
/// aspect ratio of the original image. This is accomplished via use
/// of the AspectFrame class
///
/// Ideally would like this to be a Gtk::Image subclass.
struct AspectPreservingScalingImage : public Gtk::AspectFrame
{
explicit
AspectPreservingScalingImage(Glib::RefPtr<Gdk::Pixbuf> const & pixbuf,
Gdk::InterpType interp =
Gdk::INTERP_BILINEAR):
m_img(pixbuf,interp)
{
set(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER,
// Aspect ratio of frame
pixbuf->get_width()/float(pixbuf->get_height()));
// This makes it appear as if there is no frame
set_shadow_type(Gtk::SHADOW_NONE);
// This allows a minimum size
set_size_request(pixbuf->get_width()/2,pixbuf->get_height()/2);
// Finally, add the image to be managed
add(m_img);
}
private:
ScalingImage m_img;
};
int main(int argc, char* argv[])
{
if(argc != 2)
{
std::cout << "Usage: " << argv[0] << " <image-file>" << std::endl;
return 1;
}
Gtk::Main kit(argc,argv);
Gtk::Window win;
Gtk::VBox box;
win.add(box);
Gtk::LinkButton
lb("http://www.utahskies.org/image_library/deepsky/constellations/orionwa.jpg");
AspectPreservingScalingImage
apsi(Gdk::Pixbuf::create_from_file(argv[1]));
box.pack_start(lb,Gtk::PACK_SHRINK);
box.pack_start(apsi);
struct launch_browser
{
static
void
doit(Glib::ustring const & addr)
{
std::string command("firefox ");
command += addr.c_str();
std::system(command.c_str());
}
};
lb.signal_clicked().connect
(
sigc::bind(
sigc::ptr_fun(launch_browser::doit),
lb.get_uri()
)
);
win.show_all();
Gtk::Main::run(win);
}
--
Sohail Somani
http://uint32t.blogspot.com
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]