]> git.saurik.com Git - wxWidgets.git/blame - samples/image/image.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / samples / image / image.cpp
CommitLineData
5a566d89
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: samples/image/image.cpp
3// Purpose: sample showing operations with wxImage
4// Author: Robert Roebling
09ddabf7 5// Modified by: Francesco Montorsi
5a566d89 6// Created: 1998
5a566d89 7// Copyright: (c) 1998-2005 Robert Roebling
a2bbedf0 8// (c) 2005-2009 Vadim Zeitlin
526954c5 9// Licence: wxWindows licence
5a566d89 10///////////////////////////////////////////////////////////////////////////////
01111366 11
3d05544e
JS
12// For compilers that support precompilation, includes "wx/wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
9061c15c 20 #include "wx/wx.h"
3d05544e
JS
21#endif
22
01111366 23#include "wx/image.h"
a23fd0e1 24#include "wx/file.h"
5a566d89 25#include "wx/filename.h"
0a470e5e 26#include "wx/graphics.h"
a8d4e3ac
VS
27#include "wx/mstream.h"
28#include "wx/wfstream.h"
1971d23c 29#include "wx/quantize.h"
0a470e5e 30#include "wx/scopedptr.h"
95706ac1 31#include "wx/stopwatch.h"
ccec9093 32#include "wx/versioninfo.h"
a23fd0e1 33
da9df1f5
VZ
34#if wxUSE_CLIPBOARD
35 #include "wx/dataobj.h"
36 #include "wx/clipbrd.h"
37#endif // wxUSE_CLIPBOARD
38
284f2b59 39#if defined(__WXMSW__)
481721e8 40 #ifdef wxHAVE_RAW_BITMAP
9b24b388 41 #include "wx/rawbmp.h"
481721e8 42 #endif
c698eae5 43#endif
a8d4e3ac 44
284f2b59
RR
45#if defined(__WXMAC__) || defined(__WXGTK__)
46 #define wxHAVE_RAW_BITMAP
47 #include "wx/rawbmp.h"
48#endif
49
09ddabf7 50#include "canvas.h"
01111366 51
e7092398 52#ifndef wxHAS_IMAGES_IN_RESOURCES
41f02b9a
FM
53 #include "../sample.xpm"
54#endif
01111366 55
09ddabf7
FM
56// ============================================================================
57// declarations
58// ============================================================================
01111366 59
09ddabf7
FM
60//-----------------------------------------------------------------------------
61// MyApp
62//-----------------------------------------------------------------------------
63
64class MyApp: public wxApp
01111366 65{
1d5b7a0b 66public:
09ddabf7 67 virtual bool OnInit();
01111366
RR
68};
69
09ddabf7 70// ----------------------------------------------------------------------------
01111366 71// MyFrame
09ddabf7 72// ----------------------------------------------------------------------------
18134a1c 73
01111366
RR
74class MyFrame: public wxFrame
75{
1d5b7a0b
VZ
76public:
77 MyFrame();
01111366 78
01111366 79 void OnAbout( wxCommandEvent &event );
ab0f0386 80 void OnNewFrame( wxCommandEvent &event );
37ba70a5 81 void OnImageInfo( wxCommandEvent &event );
95706ac1
VZ
82 void OnThumbnail( wxCommandEvent &event );
83
b3f04dc2
VZ
84#ifdef wxHAVE_RAW_BITMAP
85 void OnTestRawBitmap( wxCommandEvent &event );
86#endif // wxHAVE_RAW_BITMAP
0a470e5e
VZ
87#if wxUSE_GRAPHICS_CONTEXT
88 void OnTestGraphics(wxCommandEvent& event);
89#endif // wxUSE_GRAPHICS_CONTEXT
01111366 90 void OnQuit( wxCommandEvent &event );
1d5b7a0b 91
dd38c875 92#if wxUSE_CLIPBOARD
da9df1f5
VZ
93 void OnCopy(wxCommandEvent& event);
94 void OnPaste(wxCommandEvent& event);
95#endif // wxUSE_CLIPBOARD
96
01111366 97 MyCanvas *m_canvas;
1d5b7a0b 98
60a41aee 99private:
37ba70a5
VZ
100 // ask user for the file name and try to load an image from it
101 //
102 // return the file path on success, empty string if we failed to load the
103 // image or were cancelled by user
104 static wxString LoadUserImage(wxImage& image);
105
106
1d5b7a0b
VZ
107 DECLARE_DYNAMIC_CLASS(MyFrame)
108 DECLARE_EVENT_TABLE()
01111366
RR
109};
110
1d8acb7d
VZ
111// ----------------------------------------------------------------------------
112// Frame used for showing a standalone image
113// ----------------------------------------------------------------------------
114
115enum
116{
8b6264b4 117 ID_ROTATE_LEFT = wxID_HIGHEST+1,
05a8831a 118 ID_ROTATE_RIGHT,
8b6264b4
FM
119 ID_RESIZE,
120 ID_PAINT_BG
1d8acb7d
VZ
121};
122
ab0f0386
VZ
123class MyImageFrame : public wxFrame
124{
125public:
85fcb94f
VZ
126 MyImageFrame(wxFrame *parent, const wxString& desc, const wxImage& image)
127 {
128 Create(parent, desc, wxBitmap(image), image.GetImageCount(desc));
129 }
130
1d8acb7d 131 MyImageFrame(wxFrame *parent, const wxString& desc, const wxBitmap& bitmap)
ab0f0386 132 {
85fcb94f
VZ
133 Create(parent, desc, bitmap);
134 }
135
a2bbedf0 136private:
85fcb94f
VZ
137 bool Create(wxFrame *parent,
138 const wxString& desc,
139 const wxBitmap& bitmap,
140 int numImages = 1)
141 {
142 if ( !wxFrame::Create(parent, wxID_ANY,
9a83f860 143 wxString::Format(wxT("Image from %s"), desc),
85fcb94f
VZ
144 wxDefaultPosition, wxDefaultSize,
145 wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE) )
146 return false;
147
148 m_bitmap = bitmap;
a2bbedf0 149 m_zoom = 1.;
85fcb94f 150
1d8acb7d 151 wxMenu *menu = new wxMenu;
e3e7f6e5 152 menu->Append(wxID_SAVEAS);
1d8acb7d 153 menu->AppendSeparator();
9a83f860 154 menu->AppendCheckItem(ID_PAINT_BG, wxT("&Paint background"),
437950ce 155 "Uncheck this for transparent images");
8b6264b4 156 menu->AppendSeparator();
9a83f860 157 menu->Append(ID_RESIZE, wxT("&Fit to window\tCtrl-F"));
a2bbedf0
VZ
158 menu->Append(wxID_ZOOM_IN, "Zoom &in\tCtrl-+");
159 menu->Append(wxID_ZOOM_OUT, "Zoom &out\tCtrl--");
160 menu->Append(wxID_ZOOM_100, "Reset zoom to &100%\tCtrl-1");
05a8831a 161 menu->AppendSeparator();
9a83f860
VZ
162 menu->Append(ID_ROTATE_LEFT, wxT("Rotate &left\tCtrl-L"));
163 menu->Append(ID_ROTATE_RIGHT, wxT("Rotate &right\tCtrl-R"));
1d8acb7d
VZ
164
165 wxMenuBar *mbar = new wxMenuBar;
9a83f860 166 mbar->Append(menu, wxT("&Image"));
1d8acb7d
VZ
167 SetMenuBar(mbar);
168
437950ce
VZ
169 mbar->Check(ID_PAINT_BG, true);
170
85fcb94f
VZ
171 CreateStatusBar(2);
172 if ( numImages != 1 )
173 SetStatusText(wxString::Format("%d images", numImages), 1);
05a8831a 174
ab0f0386 175 SetClientSize(bitmap.GetWidth(), bitmap.GetHeight());
05a8831a
VZ
176
177 UpdateStatusBar();
8b6264b4 178
85fcb94f
VZ
179 Show();
180
181 return true;
ab0f0386
VZ
182 }
183
0c543b7a
VZ
184 void OnEraseBackground(wxEraseEvent& WXUNUSED(event))
185 {
186 // do nothing here to be able to see how transparent images are shown
187 }
188
ab0f0386
VZ
189 void OnPaint(wxPaintEvent& WXUNUSED(event))
190 {
05a8831a 191 wxPaintDC dc(this);
8b6264b4 192
437950ce 193 if ( GetMenuBar()->IsChecked(ID_PAINT_BG) )
f6b4a1b9 194 dc.Clear();
8b6264b4 195
a2bbedf0
VZ
196 dc.SetUserScale(m_zoom, m_zoom);
197
05a8831a 198 const wxSize size = GetClientSize();
a2bbedf0
VZ
199 dc.DrawBitmap
200 (
201 m_bitmap,
202 dc.DeviceToLogicalX((size.x - m_zoom*m_bitmap.GetWidth())/2),
203 dc.DeviceToLogicalY((size.y - m_zoom*m_bitmap.GetHeight())/2),
204 true /* use mask */
205 );
ab0f0386
VZ
206 }
207
1d8acb7d 208 void OnSave(wxCommandEvent& WXUNUSED(event))
1971d23c 209 {
71307412 210#if wxUSE_FILEDLG
368d59f0 211 wxImage image = m_bitmap.ConvertToImage();
1971d23c 212
4693b20c 213 wxString savefilename = wxFileSelector( wxT("Save Image"),
71307412
WS
214 wxEmptyString,
215 wxEmptyString,
e3e7f6e5 216 wxEmptyString,
d0ee33f5 217 wxT("BMP files (*.bmp)|*.bmp|")
c8688139 218#if wxUSE_LIBPNG
d0ee33f5 219 wxT("PNG files (*.png)|*.png|")
c8688139
VZ
220#endif
221#if wxUSE_LIBJPEG
d0ee33f5 222 wxT("JPEG files (*.jpg)|*.jpg|")
c8688139
VZ
223#endif
224#if wxUSE_GIF
d0ee33f5 225 wxT("GIF files (*.gif)|*.gif|")
c8688139
VZ
226#endif
227#if wxUSE_LIBTIFF
d0ee33f5 228 wxT("TIFF files (*.tif)|*.tif|")
c8688139
VZ
229#endif
230#if wxUSE_PCX
d0ee33f5 231 wxT("PCX files (*.pcx)|*.pcx|")
e3e7f6e5
VZ
232#endif
233#if wxUSE_XPM
234 wxT("X PixMap files (*.xpm)|*.xpm|")
c8688139 235#endif
d0ee33f5
WS
236 wxT("ICO files (*.ico)|*.ico|")
237 wxT("CUR files (*.cur)|*.cur"),
e3e7f6e5 238 wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
47f797bd 239 this);
1971d23c
VZ
240
241 if ( savefilename.empty() )
242 return;
243
5a566d89
VZ
244 wxString extension;
245 wxFileName::SplitPath(savefilename, NULL, NULL, &extension);
1971d23c 246
5a566d89 247 bool saved = false;
9a83f860 248 if ( extension == wxT("bmp") )
5a566d89
VZ
249 {
250 static const int bppvalues[] =
251 {
252 wxBMP_1BPP,
253 wxBMP_1BPP_BW,
254 wxBMP_4BPP,
255 wxBMP_8BPP,
256 wxBMP_8BPP_GREY,
257 wxBMP_8BPP_RED,
258 wxBMP_8BPP_PALETTE,
259 wxBMP_24BPP
260 };
261
24207dfc 262 const wxString bppchoices[] =
5a566d89 263 {
9a83f860
VZ
264 wxT("1 bpp color"),
265 wxT("1 bpp B&W"),
266 wxT("4 bpp color"),
267 wxT("8 bpp color"),
268 wxT("8 bpp greyscale"),
269 wxT("8 bpp red"),
270 wxT("8 bpp own palette"),
271 wxT("24 bpp")
5a566d89
VZ
272 };
273
9a83f860
VZ
274 int bppselection = wxGetSingleChoiceIndex(wxT("Set BMP BPP"),
275 wxT("Image sample: save file"),
09ddabf7
FM
276 WXSIZEOF(bppchoices),
277 bppchoices,
278 this);
5a566d89
VZ
279 if ( bppselection != -1 )
280 {
281 int format = bppvalues[bppselection];
282 image.SetOption(wxIMAGE_OPTION_BMP_FORMAT, format);
283
284 if ( format == wxBMP_8BPP_PALETTE )
285 {
286 unsigned char *cmap = new unsigned char [256];
287 for ( int i = 0; i < 256; i++ )
288 cmap[i] = (unsigned char)i;
289 image.SetPalette(wxPalette(256, cmap, cmap, cmap));
290
d0ee33f5 291 delete[] cmap;
5a566d89
VZ
292 }
293 }
1971d23c 294 }
c8688139 295#if wxUSE_LIBPNG
9a83f860 296 else if ( extension == wxT("png") )
5a566d89
VZ
297 {
298 static const int pngvalues[] =
299 {
300 wxPNG_TYPE_COLOUR,
301 wxPNG_TYPE_COLOUR,
302 wxPNG_TYPE_GREY,
303 wxPNG_TYPE_GREY,
304 wxPNG_TYPE_GREY_RED,
305 wxPNG_TYPE_GREY_RED,
306 };
307
24207dfc 308 const wxString pngchoices[] =
5a566d89 309 {
9a83f860
VZ
310 wxT("Colour 8bpp"),
311 wxT("Colour 16bpp"),
312 wxT("Grey 8bpp"),
313 wxT("Grey 16bpp"),
314 wxT("Grey red 8bpp"),
315 wxT("Grey red 16bpp"),
5a566d89
VZ
316 };
317
9a83f860
VZ
318 int sel = wxGetSingleChoiceIndex(wxT("Set PNG format"),
319 wxT("Image sample: save file"),
09ddabf7
FM
320 WXSIZEOF(pngchoices),
321 pngchoices,
322 this);
5a566d89
VZ
323 if ( sel != -1 )
324 {
325 image.SetOption(wxIMAGE_OPTION_PNG_FORMAT, pngvalues[sel]);
326 image.SetOption(wxIMAGE_OPTION_PNG_BITDEPTH, sel % 2 ? 16 : 8);
d19ce8c4
FM
327
328 // these values are taken from OptiPNG with -o3 switch
329 const wxString compressionChoices[] =
330 {
9a83f860
VZ
331 wxT("compression = 9, memory = 8, strategy = 0, filter = 0"),
332 wxT("compression = 9, memory = 9, strategy = 0, filter = 0"),
333 wxT("compression = 9, memory = 8, strategy = 1, filter = 0"),
334 wxT("compression = 9, memory = 9, strategy = 1, filter = 0"),
335 wxT("compression = 1, memory = 8, strategy = 2, filter = 0"),
336 wxT("compression = 1, memory = 9, strategy = 2, filter = 0"),
337 wxT("compression = 9, memory = 8, strategy = 0, filter = 5"),
338 wxT("compression = 9, memory = 9, strategy = 0, filter = 5"),
339 wxT("compression = 9, memory = 8, strategy = 1, filter = 5"),
340 wxT("compression = 9, memory = 9, strategy = 1, filter = 5"),
341 wxT("compression = 1, memory = 8, strategy = 2, filter = 5"),
342 wxT("compression = 1, memory = 9, strategy = 2, filter = 5"),
d19ce8c4
FM
343 };
344
9a83f860
VZ
345 int sel = wxGetSingleChoiceIndex(wxT("Select compression option (Cancel to use default)\n"),
346 wxT("PNG Compression Options"),
d19ce8c4
FM
347 WXSIZEOF(compressionChoices),
348 compressionChoices,
349 this);
350 if (sel != -1)
351 {
352 const int zc[] = {9, 9, 9, 9, 1, 1, 9, 9, 9, 9, 1, 1};
353 const int zm[] = {8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9};
354 const int zs[] = {0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2};
355 const int f[] = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
356 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8};
357
358 image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_LEVEL , zc[sel]);
359 image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_MEM_LEVEL , zm[sel]);
360 image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_STRATEGY , zs[sel]);
361 image.SetOption(wxIMAGE_OPTION_PNG_FILTER , f[sel]);
362 image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_BUFFER_SIZE, 1048576); // 1 MB
363 }
5a566d89
VZ
364 }
365 }
c8688139 366#endif // wxUSE_LIBPNG
9a83f860 367 else if ( extension == wxT("cur") )
45647dcf 368 {
51b07644
VZ
369 image.Rescale(32,32);
370 image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, 0);
45647dcf
VS
371 image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, 0);
372 // This shows how you can save an image with explicitly
373 // specified image format:
5a566d89 374 saved = image.SaveFile(savefilename, wxBITMAP_TYPE_CUR);
45647dcf 375 }
5a566d89
VZ
376
377 if ( !saved )
45647dcf
VS
378 {
379 // This one guesses image format from filename extension
380 // (it may fail if the extension is not recognized):
5a566d89 381 image.SaveFile(savefilename);
45647dcf 382 }
71307412 383#endif // wxUSE_FILEDLG
1971d23c
VZ
384 }
385
05a8831a
VZ
386 void OnResize(wxCommandEvent& WXUNUSED(event))
387 {
388 wxImage img(m_bitmap.ConvertToImage());
389
390 const wxSize size = GetClientSize();
391 img.Rescale(size.x, size.y, wxIMAGE_QUALITY_HIGH);
392 m_bitmap = wxBitmap(img);
393
394 UpdateStatusBar();
a2bbedf0
VZ
395 }
396
397 void OnZoom(wxCommandEvent& event)
398 {
399 if ( event.GetId() == wxID_ZOOM_IN )
400 m_zoom *= 1.2;
401 else if ( event.GetId() == wxID_ZOOM_OUT )
402 m_zoom /= 1.2;
403 else // wxID_ZOOM_100
404 m_zoom = 1.;
405
406 UpdateStatusBar();
05a8831a
VZ
407 }
408
1d8acb7d
VZ
409 void OnRotate(wxCommandEvent& event)
410 {
411 double angle = 5;
412 if ( event.GetId() == ID_ROTATE_LEFT )
413 angle = -angle;
414
415 wxImage img(m_bitmap.ConvertToImage());
05a8831a 416 img = img.Rotate(angle, wxPoint(img.GetWidth() / 2, img.GetHeight() / 2));
a1b806b9 417 if ( !img.IsOk() )
1d8acb7d 418 {
9a83f860 419 wxLogWarning(wxT("Rotation failed"));
1d8acb7d
VZ
420 return;
421 }
422
423 m_bitmap = wxBitmap(img);
05a8831a
VZ
424
425 UpdateStatusBar();
1d8acb7d
VZ
426 }
427
05a8831a
VZ
428 void UpdateStatusBar()
429 {
9a83f860 430 wxLogStatus(this, wxT("Image size: (%d, %d), zoom %.2f"),
05a8831a 431 m_bitmap.GetWidth(),
a2bbedf0
VZ
432 m_bitmap.GetHeight(),
433 m_zoom);
434 Refresh();
05a8831a
VZ
435 }
436
ab0f0386 437 wxBitmap m_bitmap;
a2bbedf0 438 double m_zoom;
ab0f0386
VZ
439
440 DECLARE_EVENT_TABLE()
441};
442
b3f04dc2
VZ
443#ifdef wxHAVE_RAW_BITMAP
444
445#include "wx/rawbmp.h"
446
447class MyRawBitmapFrame : public wxFrame
448{
449public:
450 enum
451 {
452 BORDER = 15,
453 SIZE = 150,
454 REAL_SIZE = SIZE - 2*BORDER
455 };
456
457 MyRawBitmapFrame(wxFrame *parent)
9a83f860 458 : wxFrame(parent, wxID_ANY, wxT("Raw bitmaps (how exciting)")),
09ddabf7
FM
459 m_bitmap(SIZE, SIZE, 24),
460 m_alphaBitmap(SIZE, SIZE, 32)
b3f04dc2 461 {
8ef08948 462 SetClientSize(SIZE, SIZE*2+25);
b3f04dc2 463
8ef08948
RD
464 InitAlphaBitmap();
465 InitBitmap();
66df4ec6 466
8ef08948
RD
467 }
468
469 void InitAlphaBitmap()
470 {
6e5551ad
RR
471 // First, clear the whole bitmap by making it alpha
472 {
8ef08948 473 wxAlphaPixelData data( m_alphaBitmap, wxPoint(0,0), wxSize(SIZE, SIZE) );
6e5551ad
RR
474 if ( !data )
475 {
9a83f860 476 wxLogError(wxT("Failed to gain raw access to bitmap data"));
6e5551ad
RR
477 return;
478 }
8ef08948 479 wxAlphaPixelData::Iterator p(data);
6e5551ad
RR
480 for ( int y = 0; y < SIZE; ++y )
481 {
8ef08948 482 wxAlphaPixelData::Iterator rowStart = p;
6e5551ad
RR
483 for ( int x = 0; x < SIZE; ++x )
484 {
485 p.Alpha() = 0;
486 ++p; // same as p.OffsetX(1)
487 }
488 p = rowStart;
489 p.OffsetY(data, 1);
490 }
491 }
095980e1 492
6e5551ad 493 // Then, draw colourful alpha-blended stripes
8ef08948 494 wxAlphaPixelData data(m_alphaBitmap, wxPoint(BORDER, BORDER),
09ddabf7 495 wxSize(REAL_SIZE, REAL_SIZE));
b3f04dc2
VZ
496 if ( !data )
497 {
9a83f860 498 wxLogError(wxT("Failed to gain raw access to bitmap data"));
b3f04dc2
VZ
499 return;
500 }
501
8ef08948 502 wxAlphaPixelData::Iterator p(data);
b3f04dc2 503
b3f04dc2
VZ
504 for ( int y = 0; y < REAL_SIZE; ++y )
505 {
8ef08948 506 wxAlphaPixelData::Iterator rowStart = p;
b3f04dc2
VZ
507
508 int r = y < REAL_SIZE/3 ? 255 : 0,
509 g = (REAL_SIZE/3 <= y) && (y < 2*(REAL_SIZE/3)) ? 255 : 0,
510 b = 2*(REAL_SIZE/3) <= y ? 255 : 0;
511
512 for ( int x = 0; x < REAL_SIZE; ++x )
513 {
b068dfe2 514 // note that RGB must be premultiplied by alpha
8ef08948 515 unsigned a = (wxAlphaPixelData::Iterator::ChannelType)((x*255.)/REAL_SIZE);
5c99abbe
MW
516 p.Red() = r * a / 256;
517 p.Green() = g * a / 256;
518 p.Blue() = b * a / 256;
b068dfe2 519 p.Alpha() = a;
b3f04dc2
VZ
520
521 ++p; // same as p.OffsetX(1)
522 }
523
524 p = rowStart;
1d2f48b6 525 p.OffsetY(data, 1);
b3f04dc2
VZ
526 }
527 }
528
8ef08948
RD
529 void InitBitmap()
530 {
531 // draw some colourful stripes without alpha
532 wxNativePixelData data(m_bitmap);
533 if ( !data )
534 {
9a83f860 535 wxLogError(wxT("Failed to gain raw access to bitmap data"));
8ef08948
RD
536 return;
537 }
538
539 wxNativePixelData::Iterator p(data);
540 for ( int y = 0; y < SIZE; ++y )
541 {
542 wxNativePixelData::Iterator rowStart = p;
543
544 int r = y < SIZE/3 ? 255 : 0,
545 g = (SIZE/3 <= y) && (y < 2*(SIZE/3)) ? 255 : 0,
546 b = 2*(SIZE/3) <= y ? 255 : 0;
547
548 for ( int x = 0; x < SIZE; ++x )
549 {
550 p.Red() = r;
551 p.Green() = g;
552 p.Blue() = b;
553 ++p; // same as p.OffsetX(1)
554 }
555
556 p = rowStart;
557 p.OffsetY(data, 1);
558 }
559 }
560
b3f04dc2
VZ
561 void OnPaint(wxPaintEvent& WXUNUSED(event))
562 {
563 wxPaintDC dc( this );
9a83f860
VZ
564 dc.DrawText(wxT("This is alpha and raw bitmap test"), 0, BORDER);
565 dc.DrawText(wxT("This is alpha and raw bitmap test"), 0, SIZE/2 - BORDER);
566 dc.DrawText(wxT("This is alpha and raw bitmap test"), 0, SIZE - 2*BORDER);
8ef08948
RD
567 dc.DrawBitmap( m_alphaBitmap, 0, 0, true /* use mask */ );
568
9a83f860 569 dc.DrawText(wxT("Raw bitmap access without alpha"), 0, SIZE+5);
8ef08948 570 dc.DrawBitmap( m_bitmap, 0, SIZE+5+dc.GetCharHeight());
b3f04dc2
VZ
571 }
572
573private:
574 wxBitmap m_bitmap;
8ef08948 575 wxBitmap m_alphaBitmap;
b3f04dc2
VZ
576
577 DECLARE_EVENT_TABLE()
578};
579
580#endif // wxHAVE_RAW_BITMAP
581
01111366 582
09ddabf7
FM
583// ============================================================================
584// implementations
585// ============================================================================
01111366 586
09ddabf7
FM
587//-----------------------------------------------------------------------------
588// MyImageFrame
589//-----------------------------------------------------------------------------
01111366 590
ab0f0386 591BEGIN_EVENT_TABLE(MyImageFrame, wxFrame)
0c543b7a
VZ
592 EVT_ERASE_BACKGROUND(MyImageFrame::OnEraseBackground)
593 EVT_PAINT(MyImageFrame::OnPaint)
1d8acb7d 594
e3e7f6e5 595 EVT_MENU(wxID_SAVEAS, MyImageFrame::OnSave)
1d8acb7d 596 EVT_MENU_RANGE(ID_ROTATE_LEFT, ID_ROTATE_RIGHT, MyImageFrame::OnRotate)
05a8831a 597 EVT_MENU(ID_RESIZE, MyImageFrame::OnResize)
a2bbedf0
VZ
598
599 EVT_MENU(wxID_ZOOM_IN, MyImageFrame::OnZoom)
600 EVT_MENU(wxID_ZOOM_OUT, MyImageFrame::OnZoom)
601 EVT_MENU(wxID_ZOOM_100, MyImageFrame::OnZoom)
ab0f0386
VZ
602END_EVENT_TABLE()
603
09ddabf7
FM
604//-----------------------------------------------------------------------------
605// MyRawBitmapFrame
606//-----------------------------------------------------------------------------
607
b3f04dc2
VZ
608#ifdef wxHAVE_RAW_BITMAP
609
610BEGIN_EVENT_TABLE(MyRawBitmapFrame, wxFrame)
611 EVT_PAINT(MyRawBitmapFrame::OnPaint)
612END_EVENT_TABLE()
613
614#endif // wxHAVE_RAW_BITMAP
615
09ddabf7 616//-----------------------------------------------------------------------------
01111366 617// MyFrame
09ddabf7 618//-----------------------------------------------------------------------------
01111366 619
b3f04dc2
VZ
620enum
621{
91b07357
JS
622 ID_QUIT = wxID_EXIT,
623 ID_ABOUT = wxID_ABOUT,
624 ID_NEW = 100,
37ba70a5 625 ID_INFO,
95706ac1 626 ID_SHOWRAW,
0a470e5e 627 ID_GRAPHICS,
95706ac1 628 ID_SHOWTHUMBNAIL
b3f04dc2 629};
01111366
RR
630
631IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
37ba70a5 632BEGIN_EVENT_TABLE(MyFrame, wxFrame)
09ddabf7
FM
633 EVT_MENU (ID_ABOUT, MyFrame::OnAbout)
634 EVT_MENU (ID_QUIT, MyFrame::OnQuit)
635 EVT_MENU (ID_NEW, MyFrame::OnNewFrame)
636 EVT_MENU (ID_INFO, MyFrame::OnImageInfo)
637 EVT_MENU (ID_SHOWTHUMBNAIL, MyFrame::OnThumbnail)
b3f04dc2 638#ifdef wxHAVE_RAW_BITMAP
09ddabf7 639 EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap)
b3f04dc2 640#endif
0a470e5e
VZ
641#if wxUSE_GRAPHICS_CONTEXT
642 EVT_MENU (ID_GRAPHICS, MyFrame::OnTestGraphics)
643#endif // wxUSE_GRAPHICS_CONTEXT
dd38c875 644#if wxUSE_CLIPBOARD
da9df1f5
VZ
645 EVT_MENU(wxID_COPY, MyFrame::OnCopy)
646 EVT_MENU(wxID_PASTE, MyFrame::OnPaste)
647#endif // wxUSE_CLIPBOARD
01111366
RR
648END_EVENT_TABLE()
649
1d5b7a0b 650MyFrame::MyFrame()
9a83f860 651 : wxFrame( (wxFrame *)NULL, wxID_ANY, wxT("wxImage sample"),
09ddabf7 652 wxPoint(20, 20), wxSize(950, 700) )
01111366 653{
41f02b9a
FM
654 SetIcon(wxICON(sample));
655
09ddabf7 656 wxMenuBar *menu_bar = new wxMenuBar();
da9df1f5 657
09ddabf7 658 wxMenu *menuImage = new wxMenu;
9a83f860
VZ
659 menuImage->Append( ID_NEW, wxT("&Show any image...\tCtrl-O"));
660 menuImage->Append( ID_INFO, wxT("Show image &information...\tCtrl-I"));
b3f04dc2 661#ifdef wxHAVE_RAW_BITMAP
09ddabf7 662 menuImage->AppendSeparator();
9a83f860 663 menuImage->Append( ID_SHOWRAW, wxT("Test &raw bitmap...\tCtrl-R"));
b3f04dc2 664#endif
0a470e5e
VZ
665#if wxUSE_GRAPHICS_CONTEXT
666 menuImage->AppendSeparator();
667 menuImage->Append(ID_GRAPHICS, "Test &graphics context...\tCtrl-G");
668#endif // wxUSE_GRAPHICS_CONTEXT
09ddabf7 669 menuImage->AppendSeparator();
9a83f860 670 menuImage->Append( ID_SHOWTHUMBNAIL, wxT("Test &thumbnail...\tCtrl-T"),
09ddabf7
FM
671 "Test scaling the image during load (try with JPEG)");
672 menuImage->AppendSeparator();
2d143b66 673 menuImage->Append( ID_ABOUT, wxT("&About\tF1"));
09ddabf7 674 menuImage->AppendSeparator();
9a83f860
VZ
675 menuImage->Append( ID_QUIT, wxT("E&xit\tCtrl-Q"));
676 menu_bar->Append(menuImage, wxT("&Image"));
da9df1f5 677
dd38c875 678#if wxUSE_CLIPBOARD
09ddabf7 679 wxMenu *menuClipboard = new wxMenu;
9a83f860
VZ
680 menuClipboard->Append(wxID_COPY, wxT("&Copy test image\tCtrl-C"));
681 menuClipboard->Append(wxID_PASTE, wxT("&Paste image\tCtrl-V"));
682 menu_bar->Append(menuClipboard, wxT("&Clipboard"));
da9df1f5 683#endif // wxUSE_CLIPBOARD
3d05544e 684
09ddabf7 685 SetMenuBar( menu_bar );
1d5b7a0b 686
8520f137 687#if wxUSE_STATUSBAR
09ddabf7
FM
688 CreateStatusBar(2);
689 int widths[] = { -1, 100 };
690 SetStatusWidths( 2, widths );
8520f137 691#endif // wxUSE_STATUSBAR
1d5b7a0b 692
09ddabf7 693 m_canvas = new MyCanvas( this, wxID_ANY, wxPoint(0,0), wxSize(10,10) );
cbd4be25 694
09ddabf7
FM
695 // 500 width * 2750 height
696 m_canvas->SetScrollbars( 10, 10, 50, 275 );
9ea83ebc 697 m_canvas->SetCursor(wxImage("cursor.png"));
01111366
RR
698}
699
700void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) )
701{
09ddabf7 702 Close( true );
01111366
RR
703}
704
ccec9093
VZ
705#if wxUSE_ZLIB && wxUSE_STREAMS
706#include "wx/zstream.h"
707#endif
708
01111366
RR
709void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) )
710{
ccec9093
VZ
711 wxArrayString array;
712
713 array.Add("wxImage demo");
714 array.Add("(c) Robert Roebling 1998-2005");
715 array.Add("(c) Vadim Zeitlin 2005-2009");
716
717 array.Add(wxEmptyString);
718 array.Add("Version of the libraries used:");
719
720#if wxUSE_LIBPNG
721 array.Add(wxPNGHandler::GetLibraryVersionInfo().ToString());
722#endif
723#if wxUSE_LIBJPEG
724 array.Add(wxJPEGHandler::GetLibraryVersionInfo().ToString());
725#endif
726#if wxUSE_LIBTIFF
727 array.Add(wxTIFFHandler::GetLibraryVersionInfo().ToString());
728#endif
729#if wxUSE_ZLIB && wxUSE_STREAMS
730 // zlib is used by libpng
731 array.Add(wxGetZlibVersionInfo().ToString());
732#endif
733 (void)wxMessageBox( wxJoin(array, '\n'),
a2bbedf0
VZ
734 "About wxImage Demo",
735 wxICON_INFORMATION | wxOK );
fb1585ae
RR
736}
737
37ba70a5 738wxString MyFrame::LoadUserImage(wxImage& image)
ab0f0386 739{
37ba70a5
VZ
740 wxString filename;
741
71307412 742#if wxUSE_FILEDLG
9a83f860 743 filename = wxLoadFileSelector(wxT("image"), wxEmptyString);
37ba70a5
VZ
744 if ( !filename.empty() )
745 {
746 if ( !image.LoadFile(filename) )
747 {
9a83f860 748 wxLogError(wxT("Couldn't load image from '%s'."), filename.c_str());
f6bcfd97 749
37ba70a5
VZ
750 return wxEmptyString;
751 }
752 }
753#endif // wxUSE_FILEDLG
754
755 return filename;
756}
757
758void MyFrame::OnNewFrame( wxCommandEvent &WXUNUSED(event) )
759{
f6bcfd97 760 wxImage image;
37ba70a5
VZ
761 wxString filename = LoadUserImage(image);
762 if ( !filename.empty() )
85fcb94f 763 new MyImageFrame(this, filename, image);
37ba70a5
VZ
764}
765
766void MyFrame::OnImageInfo( wxCommandEvent &WXUNUSED(event) )
767{
768 wxImage image;
769 if ( !LoadUserImage(image).empty() )
f6bcfd97 770 {
37ba70a5
VZ
771 // TODO: show more information about the file
772 wxString info = wxString::Format("Image size: %dx%d",
09ddabf7
FM
773 image.GetWidth(),
774 image.GetHeight());
37ba70a5
VZ
775
776 int xres = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX),
777 yres = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY);
778 if ( xres || yres )
779 {
780 info += wxString::Format("\nResolution: %dx%d", xres, yres);
781 switch ( image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONUNIT) )
782 {
783 default:
784 wxFAIL_MSG( "unknown image resolution units" );
785 // fall through
f6bcfd97 786
37ba70a5
VZ
787 case wxIMAGE_RESOLUTION_NONE:
788 info += " in default units";
789 break;
f6bcfd97 790
37ba70a5
VZ
791 case wxIMAGE_RESOLUTION_INCHES:
792 info += " in";
793 break;
794
795 case wxIMAGE_RESOLUTION_CM:
796 info += " cm";
797 break;
798 }
799 }
800
801 wxLogMessage("%s", info);
802 }
ab0f0386
VZ
803}
804
b3f04dc2
VZ
805#ifdef wxHAVE_RAW_BITMAP
806
481721e8 807void MyFrame::OnTestRawBitmap( wxCommandEvent &WXUNUSED(event) )
b3f04dc2
VZ
808{
809 (new MyRawBitmapFrame(this))->Show();
810}
811
812#endif // wxHAVE_RAW_BITMAP
813
0a470e5e
VZ
814#if wxUSE_GRAPHICS_CONTEXT
815
816class MyGraphicsFrame : public wxFrame
817{
818public:
819 enum
820 {
821 WIDTH = 256,
822 HEIGHT = 90
823 };
824
825 MyGraphicsFrame(wxWindow* parent) :
826 wxFrame(parent, wxID_ANY, "Graphics context test"),
827 m_image(WIDTH, HEIGHT, false)
828 {
829 // Create a test image: it has 3 horizontal primary colour bands with
830 // alpha increasing from left to right.
831 m_image.SetAlpha();
832 unsigned char* alpha = m_image.GetAlpha();
833 unsigned char* data = m_image.GetData();
834
835 for ( int y = 0; y < HEIGHT; y++ )
836 {
837 unsigned char r = 0,
838 g = 0,
839 b = 0;
840 if ( y < HEIGHT/3 )
841 r = 0xff;
842 else if ( y < (2*HEIGHT)/3 )
843 g = 0xff;
844 else
845 b = 0xff;
846
847 for ( int x = 0; x < WIDTH; x++ )
848 {
849 *alpha++ = x;
850 *data++ = r;
851 *data++ = g;
852 *data++ = b;
853 }
854 }
855
856 m_bitmap = wxBitmap(m_image);
857
858 Connect(wxEVT_PAINT, wxPaintEventHandler(MyGraphicsFrame::OnPaint));
859
860 Show();
861 }
862
863private:
864 void OnPaint(wxPaintEvent& WXUNUSED(event))
865 {
866 wxPaintDC dc(this);
867 wxScopedPtr<wxGraphicsContext> gc(wxGraphicsContext::Create(dc));
868 wxGraphicsBitmap gb(gc->CreateBitmapFromImage(m_image));
869
870 gc->SetFont(*wxNORMAL_FONT, *wxBLACK);
0a470e5e
VZ
871 gc->DrawText("Bitmap", 0, HEIGHT/2);
872 gc->DrawBitmap(m_bitmap, 0, 0, WIDTH, HEIGHT);
873
fa378d36
VZ
874 wxGraphicsFont gf = gc->CreateFont(wxNORMAL_FONT->GetPixelSize().y, "");
875 gc->SetFont(gf);
0a470e5e
VZ
876 gc->DrawText("Graphics bitmap", 0, (3*HEIGHT)/2);
877 gc->DrawBitmap(gb, 0, HEIGHT, WIDTH, HEIGHT);
878 }
879
880 wxImage m_image;
881 wxBitmap m_bitmap;
882
883 wxDECLARE_NO_COPY_CLASS(MyGraphicsFrame);
884};
885
886void MyFrame::OnTestGraphics(wxCommandEvent& WXUNUSED(event))
887{
888 new MyGraphicsFrame(this);
889}
890
891#endif // wxUSE_GRAPHICS_CONTEXT
892
dd38c875 893#if wxUSE_CLIPBOARD
da9df1f5
VZ
894
895void MyFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
896{
897 wxBitmapDataObject *dobjBmp = new wxBitmapDataObject;
bd981f27 898 dobjBmp->SetBitmap(m_canvas->my_horse_png);
da9df1f5 899
dd38c875
MB
900 wxTheClipboard->Open();
901
da9df1f5
VZ
902 if ( !wxTheClipboard->SetData(dobjBmp) )
903 {
9a83f860 904 wxLogError(wxT("Failed to copy bitmap to clipboard"));
da9df1f5 905 }
dd38c875
MB
906
907 wxTheClipboard->Close();
da9df1f5
VZ
908}
909
910void MyFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
911{
912 wxBitmapDataObject dobjBmp;
dd38c875
MB
913
914 wxTheClipboard->Open();
da9df1f5
VZ
915 if ( !wxTheClipboard->GetData(dobjBmp) )
916 {
9a83f860 917 wxLogMessage(wxT("No bitmap data in the clipboard"));
da9df1f5
VZ
918 }
919 else
920 {
9a83f860 921 new MyImageFrame(this, wxT("Clipboard"), dobjBmp.GetBitmap());
da9df1f5 922 }
dd38c875 923 wxTheClipboard->Close();
da9df1f5
VZ
924}
925
926#endif // wxUSE_CLIPBOARD
927
95706ac1
VZ
928void MyFrame::OnThumbnail( wxCommandEvent &WXUNUSED(event) )
929{
930#if wxUSE_FILEDLG
9a83f860 931 wxString filename = wxLoadFileSelector(wxT("image"), wxEmptyString, wxEmptyString, this);
95706ac1
VZ
932 if ( filename.empty() )
933 return;
934
935 static const int THUMBNAIL_WIDTH = 320;
936 static const int THUMBNAIL_HEIGHT = 240;
937
938 wxImage image;
939 image.SetOption(wxIMAGE_OPTION_MAX_WIDTH, THUMBNAIL_WIDTH);
940 image.SetOption(wxIMAGE_OPTION_MAX_HEIGHT, THUMBNAIL_HEIGHT);
941
942 wxStopWatch sw;
943 if ( !image.LoadFile(filename) )
944 {
9a83f860 945 wxLogError(wxT("Couldn't load image from '%s'."), filename.c_str());
95706ac1
VZ
946 return;
947 }
948
b6963858
VZ
949 int origWidth = image.GetOptionInt( wxIMAGE_OPTION_ORIGINAL_WIDTH );
950 int origHeight = image.GetOptionInt( wxIMAGE_OPTION_ORIGINAL_HEIGHT );
951
95706ac1
VZ
952 const long loadTime = sw.Time();
953
85fcb94f 954 MyImageFrame * const frame = new MyImageFrame(this, filename, image);
b6963858
VZ
955 wxLogStatus(frame, "Loaded \"%s\" in %ldms; original size was (%d, %d)",
956 filename, loadTime, origWidth, origHeight);
95706ac1 957#else
9a83f860 958 wxLogError( wxT("Couldn't create file selector dialog") );
95706ac1
VZ
959 return;
960#endif // wxUSE_FILEDLG
961}
962
09ddabf7
FM
963//-----------------------------------------------------------------------------
964// MyApp
965//-----------------------------------------------------------------------------
966
967IMPLEMENT_APP(MyApp)
968
969bool MyApp::OnInit()
970{
971 if ( !wxApp::OnInit() )
972 return false;
973
974 wxInitAllImageHandlers();
975
976 wxFrame *frame = new MyFrame();
977 frame->Show( true );
978
979 return true;
980}