Files
wxWidgets/samples/image/image.cpp
Vadim Zeitlin f6b4a1b98d Don't use wxWindow::ClearBackground() in the image sample and explain why.
Painting on both wxPaintDC and wxClientDC simultaneously doesn't work well,
e.g. under Windows the client DC can be actually erased after we finished
painting the window contents, overwriting it.

Simply use wxDC::Clear() instead of wxWindow::ClearBackground() to avoid this
and document the danger of using ClearBackground() from EVT_PAINT handler.

Closes #10700.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64277 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2010-05-10 21:02:30 +00:00

857 lines
26 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: samples/image/image.cpp
// Purpose: sample showing operations with wxImage
// Author: Robert Roebling
// Modified by: Francesco Montorsi
// Created: 1998
// RCS-ID: $Id$
// Copyright: (c) 1998-2005 Robert Roebling
// (c) 2005-2009 Vadim Zeitlin
// License: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/image.h"
#include "wx/file.h"
#include "wx/filename.h"
#include "wx/mstream.h"
#include "wx/wfstream.h"
#include "wx/quantize.h"
#include "wx/stopwatch.h"
#if wxUSE_CLIPBOARD
#include "wx/dataobj.h"
#include "wx/clipbrd.h"
#endif // wxUSE_CLIPBOARD
#if defined(__WXMSW__)
#ifdef wxHAVE_RAW_BITMAP
#include "wx/rawbmp.h"
#endif
#endif
#if defined(__WXMAC__) || defined(__WXGTK__)
#define wxHAVE_RAW_BITMAP
#include "wx/rawbmp.h"
#endif
#include "canvas.h"
#ifndef __WXMSW__
#include "../sample.xpm"
#endif
// ============================================================================
// declarations
// ============================================================================
//-----------------------------------------------------------------------------
// MyApp
//-----------------------------------------------------------------------------
class MyApp: public wxApp
{
public:
virtual bool OnInit();
};
// ----------------------------------------------------------------------------
// MyFrame
// ----------------------------------------------------------------------------
class MyFrame: public wxFrame
{
public:
MyFrame();
void OnAbout( wxCommandEvent &event );
void OnNewFrame( wxCommandEvent &event );
void OnImageInfo( wxCommandEvent &event );
void OnThumbnail( wxCommandEvent &event );
#ifdef wxHAVE_RAW_BITMAP
void OnTestRawBitmap( wxCommandEvent &event );
#endif // wxHAVE_RAW_BITMAP
void OnQuit( wxCommandEvent &event );
#if wxUSE_CLIPBOARD
void OnCopy(wxCommandEvent& event);
void OnPaste(wxCommandEvent& event);
#endif // wxUSE_CLIPBOARD
MyCanvas *m_canvas;
private:
// ask user for the file name and try to load an image from it
//
// return the file path on success, empty string if we failed to load the
// image or were cancelled by user
static wxString LoadUserImage(wxImage& image);
DECLARE_DYNAMIC_CLASS(MyFrame)
DECLARE_EVENT_TABLE()
};
// ----------------------------------------------------------------------------
// Frame used for showing a standalone image
// ----------------------------------------------------------------------------
enum
{
ID_ROTATE_LEFT = wxID_HIGHEST+1,
ID_ROTATE_RIGHT,
ID_RESIZE,
ID_PAINT_BG
};
class MyImageFrame : public wxFrame
{
public:
MyImageFrame(wxFrame *parent, const wxString& desc, const wxImage& image)
{
Create(parent, desc, wxBitmap(image), image.GetImageCount(desc));
}
MyImageFrame(wxFrame *parent, const wxString& desc, const wxBitmap& bitmap)
{
Create(parent, desc, bitmap);
}
private:
bool Create(wxFrame *parent,
const wxString& desc,
const wxBitmap& bitmap,
int numImages = 1)
{
if ( !wxFrame::Create(parent, wxID_ANY,
wxString::Format(wxT("Image from %s"), desc),
wxDefaultPosition, wxDefaultSize,
wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE) )
return false;
m_bitmap = bitmap;
m_zoom = 1.;
wxMenu *menu = new wxMenu;
menu->Append(wxID_SAVE);
menu->AppendSeparator();
menu->AppendCheckItem(ID_PAINT_BG, wxT("&Paint background"),
"Uncheck this for transparent images");
menu->AppendSeparator();
menu->Append(ID_RESIZE, wxT("&Fit to window\tCtrl-F"));
menu->Append(wxID_ZOOM_IN, "Zoom &in\tCtrl-+");
menu->Append(wxID_ZOOM_OUT, "Zoom &out\tCtrl--");
menu->Append(wxID_ZOOM_100, "Reset zoom to &100%\tCtrl-1");
menu->AppendSeparator();
menu->Append(ID_ROTATE_LEFT, wxT("Rotate &left\tCtrl-L"));
menu->Append(ID_ROTATE_RIGHT, wxT("Rotate &right\tCtrl-R"));
wxMenuBar *mbar = new wxMenuBar;
mbar->Append(menu, wxT("&Image"));
SetMenuBar(mbar);
mbar->Check(ID_PAINT_BG, true);
CreateStatusBar(2);
if ( numImages != 1 )
SetStatusText(wxString::Format("%d images", numImages), 1);
SetClientSize(bitmap.GetWidth(), bitmap.GetHeight());
UpdateStatusBar();
Show();
return true;
}
void OnEraseBackground(wxEraseEvent& WXUNUSED(event))
{
// do nothing here to be able to see how transparent images are shown
}
void OnPaint(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc(this);
if ( GetMenuBar()->IsChecked(ID_PAINT_BG) )
dc.Clear();
dc.SetUserScale(m_zoom, m_zoom);
const wxSize size = GetClientSize();
dc.DrawBitmap
(
m_bitmap,
dc.DeviceToLogicalX((size.x - m_zoom*m_bitmap.GetWidth())/2),
dc.DeviceToLogicalY((size.y - m_zoom*m_bitmap.GetHeight())/2),
true /* use mask */
);
}
void OnSave(wxCommandEvent& WXUNUSED(event))
{
#if wxUSE_FILEDLG
wxImage image = m_bitmap.ConvertToImage();
wxString savefilename = wxFileSelector( wxT("Save Image"),
wxEmptyString,
wxEmptyString,
(const wxChar *)NULL,
wxT("BMP files (*.bmp)|*.bmp|")
#if wxUSE_LIBPNG
wxT("PNG files (*.png)|*.png|")
#endif
#if wxUSE_LIBJPEG
wxT("JPEG files (*.jpg)|*.jpg|")
#endif
#if wxUSE_GIF
wxT("GIF files (*.gif)|*.gif|")
#endif
#if wxUSE_LIBTIFF
wxT("TIFF files (*.tif)|*.tif|")
#endif
#if wxUSE_PCX
wxT("PCX files (*.pcx)|*.pcx|")
#endif
wxT("ICO files (*.ico)|*.ico|")
wxT("CUR files (*.cur)|*.cur"),
wxFD_SAVE,
this);
if ( savefilename.empty() )
return;
wxString extension;
wxFileName::SplitPath(savefilename, NULL, NULL, &extension);
bool saved = false;
if ( extension == wxT("bmp") )
{
static const int bppvalues[] =
{
wxBMP_1BPP,
wxBMP_1BPP_BW,
wxBMP_4BPP,
wxBMP_8BPP,
wxBMP_8BPP_GREY,
wxBMP_8BPP_RED,
wxBMP_8BPP_PALETTE,
wxBMP_24BPP
};
const wxString bppchoices[] =
{
wxT("1 bpp color"),
wxT("1 bpp B&W"),
wxT("4 bpp color"),
wxT("8 bpp color"),
wxT("8 bpp greyscale"),
wxT("8 bpp red"),
wxT("8 bpp own palette"),
wxT("24 bpp")
};
int bppselection = wxGetSingleChoiceIndex(wxT("Set BMP BPP"),
wxT("Image sample: save file"),
WXSIZEOF(bppchoices),
bppchoices,
this);
if ( bppselection != -1 )
{
int format = bppvalues[bppselection];
image.SetOption(wxIMAGE_OPTION_BMP_FORMAT, format);
if ( format == wxBMP_8BPP_PALETTE )
{
unsigned char *cmap = new unsigned char [256];
for ( int i = 0; i < 256; i++ )
cmap[i] = (unsigned char)i;
image.SetPalette(wxPalette(256, cmap, cmap, cmap));
delete[] cmap;
}
}
}
#if wxUSE_LIBPNG
else if ( extension == wxT("png") )
{
static const int pngvalues[] =
{
wxPNG_TYPE_COLOUR,
wxPNG_TYPE_COLOUR,
wxPNG_TYPE_GREY,
wxPNG_TYPE_GREY,
wxPNG_TYPE_GREY_RED,
wxPNG_TYPE_GREY_RED,
};
const wxString pngchoices[] =
{
wxT("Colour 8bpp"),
wxT("Colour 16bpp"),
wxT("Grey 8bpp"),
wxT("Grey 16bpp"),
wxT("Grey red 8bpp"),
wxT("Grey red 16bpp"),
};
int sel = wxGetSingleChoiceIndex(wxT("Set PNG format"),
wxT("Image sample: save file"),
WXSIZEOF(pngchoices),
pngchoices,
this);
if ( sel != -1 )
{
image.SetOption(wxIMAGE_OPTION_PNG_FORMAT, pngvalues[sel]);
image.SetOption(wxIMAGE_OPTION_PNG_BITDEPTH, sel % 2 ? 16 : 8);
// these values are taken from OptiPNG with -o3 switch
const wxString compressionChoices[] =
{
wxT("compression = 9, memory = 8, strategy = 0, filter = 0"),
wxT("compression = 9, memory = 9, strategy = 0, filter = 0"),
wxT("compression = 9, memory = 8, strategy = 1, filter = 0"),
wxT("compression = 9, memory = 9, strategy = 1, filter = 0"),
wxT("compression = 1, memory = 8, strategy = 2, filter = 0"),
wxT("compression = 1, memory = 9, strategy = 2, filter = 0"),
wxT("compression = 9, memory = 8, strategy = 0, filter = 5"),
wxT("compression = 9, memory = 9, strategy = 0, filter = 5"),
wxT("compression = 9, memory = 8, strategy = 1, filter = 5"),
wxT("compression = 9, memory = 9, strategy = 1, filter = 5"),
wxT("compression = 1, memory = 8, strategy = 2, filter = 5"),
wxT("compression = 1, memory = 9, strategy = 2, filter = 5"),
};
int sel = wxGetSingleChoiceIndex(wxT("Select compression option (Cancel to use default)\n"),
wxT("PNG Compression Options"),
WXSIZEOF(compressionChoices),
compressionChoices,
this);
if (sel != -1)
{
const int zc[] = {9, 9, 9, 9, 1, 1, 9, 9, 9, 9, 1, 1};
const int zm[] = {8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9};
const int zs[] = {0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2};
const int f[] = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8};
image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_LEVEL , zc[sel]);
image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_MEM_LEVEL , zm[sel]);
image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_STRATEGY , zs[sel]);
image.SetOption(wxIMAGE_OPTION_PNG_FILTER , f[sel]);
image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_BUFFER_SIZE, 1048576); // 1 MB
}
}
}
#endif // wxUSE_LIBPNG
else if ( extension == wxT("cur") )
{
image.Rescale(32,32);
image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, 0);
image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, 0);
// This shows how you can save an image with explicitly
// specified image format:
saved = image.SaveFile(savefilename, wxBITMAP_TYPE_CUR);
}
if ( !saved )
{
// This one guesses image format from filename extension
// (it may fail if the extension is not recognized):
image.SaveFile(savefilename);
}
#endif // wxUSE_FILEDLG
}
void OnResize(wxCommandEvent& WXUNUSED(event))
{
wxImage img(m_bitmap.ConvertToImage());
const wxSize size = GetClientSize();
img.Rescale(size.x, size.y, wxIMAGE_QUALITY_HIGH);
m_bitmap = wxBitmap(img);
UpdateStatusBar();
}
void OnZoom(wxCommandEvent& event)
{
if ( event.GetId() == wxID_ZOOM_IN )
m_zoom *= 1.2;
else if ( event.GetId() == wxID_ZOOM_OUT )
m_zoom /= 1.2;
else // wxID_ZOOM_100
m_zoom = 1.;
UpdateStatusBar();
}
void OnRotate(wxCommandEvent& event)
{
double angle = 5;
if ( event.GetId() == ID_ROTATE_LEFT )
angle = -angle;
wxImage img(m_bitmap.ConvertToImage());
img = img.Rotate(angle, wxPoint(img.GetWidth() / 2, img.GetHeight() / 2));
if ( !img.Ok() )
{
wxLogWarning(wxT("Rotation failed"));
return;
}
m_bitmap = wxBitmap(img);
UpdateStatusBar();
}
void UpdateStatusBar()
{
wxLogStatus(this, wxT("Image size: (%d, %d), zoom %.2f"),
m_bitmap.GetWidth(),
m_bitmap.GetHeight(),
m_zoom);
Refresh();
}
wxBitmap m_bitmap;
double m_zoom;
DECLARE_EVENT_TABLE()
};
#ifdef wxHAVE_RAW_BITMAP
#include "wx/rawbmp.h"
class MyRawBitmapFrame : public wxFrame
{
public:
enum
{
BORDER = 15,
SIZE = 150,
REAL_SIZE = SIZE - 2*BORDER
};
MyRawBitmapFrame(wxFrame *parent)
: wxFrame(parent, wxID_ANY, wxT("Raw bitmaps (how exciting)")),
m_bitmap(SIZE, SIZE, 24),
m_alphaBitmap(SIZE, SIZE, 32)
{
SetClientSize(SIZE, SIZE*2+25);
InitAlphaBitmap();
InitBitmap();
}
void InitAlphaBitmap()
{
// First, clear the whole bitmap by making it alpha
{
wxAlphaPixelData data( m_alphaBitmap, wxPoint(0,0), wxSize(SIZE, SIZE) );
if ( !data )
{
wxLogError(wxT("Failed to gain raw access to bitmap data"));
return;
}
wxAlphaPixelData::Iterator p(data);
for ( int y = 0; y < SIZE; ++y )
{
wxAlphaPixelData::Iterator rowStart = p;
for ( int x = 0; x < SIZE; ++x )
{
p.Alpha() = 0;
++p; // same as p.OffsetX(1)
}
p = rowStart;
p.OffsetY(data, 1);
}
}
// Then, draw colourful alpha-blended stripes
wxAlphaPixelData data(m_alphaBitmap, wxPoint(BORDER, BORDER),
wxSize(REAL_SIZE, REAL_SIZE));
if ( !data )
{
wxLogError(wxT("Failed to gain raw access to bitmap data"));
return;
}
wxAlphaPixelData::Iterator p(data);
for ( int y = 0; y < REAL_SIZE; ++y )
{
wxAlphaPixelData::Iterator rowStart = p;
int r = y < REAL_SIZE/3 ? 255 : 0,
g = (REAL_SIZE/3 <= y) && (y < 2*(REAL_SIZE/3)) ? 255 : 0,
b = 2*(REAL_SIZE/3) <= y ? 255 : 0;
for ( int x = 0; x < REAL_SIZE; ++x )
{
// note that RGB must be premultiplied by alpha
unsigned a = (wxAlphaPixelData::Iterator::ChannelType)((x*255.)/REAL_SIZE);
p.Red() = r * a / 256;
p.Green() = g * a / 256;
p.Blue() = b * a / 256;
p.Alpha() = a;
++p; // same as p.OffsetX(1)
}
p = rowStart;
p.OffsetY(data, 1);
}
}
void InitBitmap()
{
// draw some colourful stripes without alpha
wxNativePixelData data(m_bitmap);
if ( !data )
{
wxLogError(wxT("Failed to gain raw access to bitmap data"));
return;
}
wxNativePixelData::Iterator p(data);
for ( int y = 0; y < SIZE; ++y )
{
wxNativePixelData::Iterator rowStart = p;
int r = y < SIZE/3 ? 255 : 0,
g = (SIZE/3 <= y) && (y < 2*(SIZE/3)) ? 255 : 0,
b = 2*(SIZE/3) <= y ? 255 : 0;
for ( int x = 0; x < SIZE; ++x )
{
p.Red() = r;
p.Green() = g;
p.Blue() = b;
++p; // same as p.OffsetX(1)
}
p = rowStart;
p.OffsetY(data, 1);
}
}
void OnPaint(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc( this );
dc.DrawText(wxT("This is alpha and raw bitmap test"), 0, BORDER);
dc.DrawText(wxT("This is alpha and raw bitmap test"), 0, SIZE/2 - BORDER);
dc.DrawText(wxT("This is alpha and raw bitmap test"), 0, SIZE - 2*BORDER);
dc.DrawBitmap( m_alphaBitmap, 0, 0, true /* use mask */ );
dc.DrawText(wxT("Raw bitmap access without alpha"), 0, SIZE+5);
dc.DrawBitmap( m_bitmap, 0, SIZE+5+dc.GetCharHeight());
}
private:
wxBitmap m_bitmap;
wxBitmap m_alphaBitmap;
DECLARE_EVENT_TABLE()
};
#endif // wxHAVE_RAW_BITMAP
// ============================================================================
// implementations
// ============================================================================
//-----------------------------------------------------------------------------
// MyImageFrame
//-----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(MyImageFrame, wxFrame)
EVT_ERASE_BACKGROUND(MyImageFrame::OnEraseBackground)
EVT_PAINT(MyImageFrame::OnPaint)
EVT_MENU(wxID_SAVE, MyImageFrame::OnSave)
EVT_MENU_RANGE(ID_ROTATE_LEFT, ID_ROTATE_RIGHT, MyImageFrame::OnRotate)
EVT_MENU(ID_RESIZE, MyImageFrame::OnResize)
EVT_MENU(wxID_ZOOM_IN, MyImageFrame::OnZoom)
EVT_MENU(wxID_ZOOM_OUT, MyImageFrame::OnZoom)
EVT_MENU(wxID_ZOOM_100, MyImageFrame::OnZoom)
END_EVENT_TABLE()
//-----------------------------------------------------------------------------
// MyRawBitmapFrame
//-----------------------------------------------------------------------------
#ifdef wxHAVE_RAW_BITMAP
BEGIN_EVENT_TABLE(MyRawBitmapFrame, wxFrame)
EVT_PAINT(MyRawBitmapFrame::OnPaint)
END_EVENT_TABLE()
#endif // wxHAVE_RAW_BITMAP
//-----------------------------------------------------------------------------
// MyFrame
//-----------------------------------------------------------------------------
enum
{
ID_QUIT = wxID_EXIT,
ID_ABOUT = wxID_ABOUT,
ID_NEW = 100,
ID_INFO,
ID_SHOWRAW,
ID_SHOWTHUMBNAIL
};
IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU (ID_ABOUT, MyFrame::OnAbout)
EVT_MENU (ID_QUIT, MyFrame::OnQuit)
EVT_MENU (ID_NEW, MyFrame::OnNewFrame)
EVT_MENU (ID_INFO, MyFrame::OnImageInfo)
EVT_MENU (ID_SHOWTHUMBNAIL, MyFrame::OnThumbnail)
#ifdef wxHAVE_RAW_BITMAP
EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap)
#endif
#if wxUSE_CLIPBOARD
EVT_MENU(wxID_COPY, MyFrame::OnCopy)
EVT_MENU(wxID_PASTE, MyFrame::OnPaste)
#endif // wxUSE_CLIPBOARD
END_EVENT_TABLE()
MyFrame::MyFrame()
: wxFrame( (wxFrame *)NULL, wxID_ANY, wxT("wxImage sample"),
wxPoint(20, 20), wxSize(950, 700) )
{
SetIcon(wxICON(sample));
wxMenuBar *menu_bar = new wxMenuBar();
wxMenu *menuImage = new wxMenu;
menuImage->Append( ID_NEW, wxT("&Show any image...\tCtrl-O"));
menuImage->Append( ID_INFO, wxT("Show image &information...\tCtrl-I"));
#ifdef wxHAVE_RAW_BITMAP
menuImage->AppendSeparator();
menuImage->Append( ID_SHOWRAW, wxT("Test &raw bitmap...\tCtrl-R"));
#endif
menuImage->AppendSeparator();
menuImage->Append( ID_SHOWTHUMBNAIL, wxT("Test &thumbnail...\tCtrl-T"),
"Test scaling the image during load (try with JPEG)");
menuImage->AppendSeparator();
menuImage->Append( ID_ABOUT, wxT("&About..."));
menuImage->AppendSeparator();
menuImage->Append( ID_QUIT, wxT("E&xit\tCtrl-Q"));
menu_bar->Append(menuImage, wxT("&Image"));
#if wxUSE_CLIPBOARD
wxMenu *menuClipboard = new wxMenu;
menuClipboard->Append(wxID_COPY, wxT("&Copy test image\tCtrl-C"));
menuClipboard->Append(wxID_PASTE, wxT("&Paste image\tCtrl-V"));
menu_bar->Append(menuClipboard, wxT("&Clipboard"));
#endif // wxUSE_CLIPBOARD
SetMenuBar( menu_bar );
#if wxUSE_STATUSBAR
CreateStatusBar(2);
int widths[] = { -1, 100 };
SetStatusWidths( 2, widths );
#endif // wxUSE_STATUSBAR
m_canvas = new MyCanvas( this, wxID_ANY, wxPoint(0,0), wxSize(10,10) );
// 500 width * 2750 height
m_canvas->SetScrollbars( 10, 10, 50, 275 );
}
void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) )
{
Close( true );
}
void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) )
{
(void)wxMessageBox( "wxImage demo\n"
"(c) Robert Roebling 1998-2005"
"(c) Vadim Zeitlin 2005-2009",
"About wxImage Demo",
wxICON_INFORMATION | wxOK );
}
wxString MyFrame::LoadUserImage(wxImage& image)
{
wxString filename;
#if wxUSE_FILEDLG
filename = wxLoadFileSelector(wxT("image"), wxEmptyString);
if ( !filename.empty() )
{
if ( !image.LoadFile(filename) )
{
wxLogError(wxT("Couldn't load image from '%s'."), filename.c_str());
return wxEmptyString;
}
}
#endif // wxUSE_FILEDLG
return filename;
}
void MyFrame::OnNewFrame( wxCommandEvent &WXUNUSED(event) )
{
wxImage image;
wxString filename = LoadUserImage(image);
if ( !filename.empty() )
new MyImageFrame(this, filename, image);
}
void MyFrame::OnImageInfo( wxCommandEvent &WXUNUSED(event) )
{
wxImage image;
if ( !LoadUserImage(image).empty() )
{
// TODO: show more information about the file
wxString info = wxString::Format("Image size: %dx%d",
image.GetWidth(),
image.GetHeight());
int xres = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX),
yres = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY);
if ( xres || yres )
{
info += wxString::Format("\nResolution: %dx%d", xres, yres);
switch ( image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONUNIT) )
{
default:
wxFAIL_MSG( "unknown image resolution units" );
// fall through
case wxIMAGE_RESOLUTION_NONE:
info += " in default units";
break;
case wxIMAGE_RESOLUTION_INCHES:
info += " in";
break;
case wxIMAGE_RESOLUTION_CM:
info += " cm";
break;
}
}
wxLogMessage("%s", info);
}
}
#ifdef wxHAVE_RAW_BITMAP
void MyFrame::OnTestRawBitmap( wxCommandEvent &WXUNUSED(event) )
{
(new MyRawBitmapFrame(this))->Show();
}
#endif // wxHAVE_RAW_BITMAP
#if wxUSE_CLIPBOARD
void MyFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
{
wxBitmapDataObject *dobjBmp = new wxBitmapDataObject;
dobjBmp->SetBitmap(m_canvas->my_horse_png);
wxTheClipboard->Open();
if ( !wxTheClipboard->SetData(dobjBmp) )
{
wxLogError(wxT("Failed to copy bitmap to clipboard"));
}
wxTheClipboard->Close();
}
void MyFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
{
wxBitmapDataObject dobjBmp;
wxTheClipboard->Open();
if ( !wxTheClipboard->GetData(dobjBmp) )
{
wxLogMessage(wxT("No bitmap data in the clipboard"));
}
else
{
new MyImageFrame(this, wxT("Clipboard"), dobjBmp.GetBitmap());
}
wxTheClipboard->Close();
}
#endif // wxUSE_CLIPBOARD
void MyFrame::OnThumbnail( wxCommandEvent &WXUNUSED(event) )
{
#if wxUSE_FILEDLG
wxString filename = wxLoadFileSelector(wxT("image"), wxEmptyString, wxEmptyString, this);
if ( filename.empty() )
return;
static const int THUMBNAIL_WIDTH = 320;
static const int THUMBNAIL_HEIGHT = 240;
wxImage image;
image.SetOption(wxIMAGE_OPTION_MAX_WIDTH, THUMBNAIL_WIDTH);
image.SetOption(wxIMAGE_OPTION_MAX_HEIGHT, THUMBNAIL_HEIGHT);
wxStopWatch sw;
if ( !image.LoadFile(filename) )
{
wxLogError(wxT("Couldn't load image from '%s'."), filename.c_str());
return;
}
const long loadTime = sw.Time();
MyImageFrame * const frame = new MyImageFrame(this, filename, image);
wxLogStatus(frame, "Loaded \"%s\" in %ldms", filename, loadTime);
#else
wxLogError( wxT("Couldn't create file selector dialog") );
return;
#endif // wxUSE_FILEDLG
}
//-----------------------------------------------------------------------------
// MyApp
//-----------------------------------------------------------------------------
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
if ( !wxApp::OnInit() )
return false;
wxInitAllImageHandlers();
wxFrame *frame = new MyFrame();
frame->Show( true );
return true;
}