paint background by default to avoid unexpected sample appearance
[wxWidgets.git] / samples / image / image.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: samples/image/image.cpp
3 // Purpose: sample showing operations with wxImage
4 // Author: Robert Roebling
5 // Modified by: Francesco Montorsi
6 // Created: 1998
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998-2005 Robert Roebling
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
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
20 #include "wx/wx.h"
21 #endif
22
23 #include "wx/image.h"
24 #include "wx/file.h"
25 #include "wx/filename.h"
26 #include "wx/mstream.h"
27 #include "wx/wfstream.h"
28 #include "wx/quantize.h"
29 #include "wx/stopwatch.h"
30
31 #if wxUSE_CLIPBOARD
32 #include "wx/dataobj.h"
33 #include "wx/clipbrd.h"
34 #endif // wxUSE_CLIPBOARD
35
36 #if defined(__WXMSW__)
37 #ifdef wxHAVE_RAW_BITMAP
38 #include "wx/rawbmp.h"
39 #endif
40 #endif
41
42 #if defined(__WXMAC__) || defined(__WXGTK__)
43 #define wxHAVE_RAW_BITMAP
44 #include "wx/rawbmp.h"
45 #endif
46
47 #include "canvas.h"
48
49 #ifndef __WXMSW__
50 #include "../sample.xpm"
51 #endif
52
53 // ============================================================================
54 // declarations
55 // ============================================================================
56
57 //-----------------------------------------------------------------------------
58 // MyApp
59 //-----------------------------------------------------------------------------
60
61 class MyApp: public wxApp
62 {
63 public:
64 virtual bool OnInit();
65 };
66
67 // ----------------------------------------------------------------------------
68 // MyFrame
69 // ----------------------------------------------------------------------------
70
71 class MyFrame: public wxFrame
72 {
73 public:
74 MyFrame();
75
76 void OnAbout( wxCommandEvent &event );
77 void OnNewFrame( wxCommandEvent &event );
78 void OnImageInfo( wxCommandEvent &event );
79 void OnThumbnail( wxCommandEvent &event );
80
81 #ifdef wxHAVE_RAW_BITMAP
82 void OnTestRawBitmap( wxCommandEvent &event );
83 #endif // wxHAVE_RAW_BITMAP
84 void OnQuit( wxCommandEvent &event );
85
86 #if wxUSE_CLIPBOARD
87 void OnCopy(wxCommandEvent& event);
88 void OnPaste(wxCommandEvent& event);
89 #endif // wxUSE_CLIPBOARD
90
91 MyCanvas *m_canvas;
92
93 private:
94 // ask user for the file name and try to load an image from it
95 //
96 // return the file path on success, empty string if we failed to load the
97 // image or were cancelled by user
98 static wxString LoadUserImage(wxImage& image);
99
100
101 DECLARE_DYNAMIC_CLASS(MyFrame)
102 DECLARE_EVENT_TABLE()
103 };
104
105 // ----------------------------------------------------------------------------
106 // Frame used for showing a standalone image
107 // ----------------------------------------------------------------------------
108
109 enum
110 {
111 ID_ROTATE_LEFT = wxID_HIGHEST+1,
112 ID_ROTATE_RIGHT,
113 ID_RESIZE,
114 ID_PAINT_BG
115 };
116
117 class MyImageFrame : public wxFrame
118 {
119 public:
120 MyImageFrame(wxFrame *parent, const wxString& desc, const wxImage& image)
121 {
122 Create(parent, desc, wxBitmap(image), image.GetImageCount(desc));
123 }
124
125 MyImageFrame(wxFrame *parent, const wxString& desc, const wxBitmap& bitmap)
126 {
127 Create(parent, desc, bitmap);
128 }
129
130 bool Create(wxFrame *parent,
131 const wxString& desc,
132 const wxBitmap& bitmap,
133 int numImages = 1)
134 {
135 if ( !wxFrame::Create(parent, wxID_ANY,
136 wxString::Format(_T("Image from %s"), desc),
137 wxDefaultPosition, wxDefaultSize,
138 wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE) )
139 return false;
140
141 m_bitmap = bitmap;
142
143 wxMenu *menu = new wxMenu;
144 menu->Append(wxID_SAVE);
145 menu->AppendSeparator();
146 menu->AppendCheckItem(ID_PAINT_BG, _T("&Paint background"),
147 "Uncheck this for transparent images");
148 menu->AppendSeparator();
149 menu->Append(ID_RESIZE, _T("&Fit to window\tCtrl-F"));
150 menu->AppendSeparator();
151 menu->Append(ID_ROTATE_LEFT, _T("Rotate &left\tCtrl-L"));
152 menu->Append(ID_ROTATE_RIGHT, _T("Rotate &right\tCtrl-R"));
153
154 wxMenuBar *mbar = new wxMenuBar;
155 mbar->Append(menu, _T("&Image"));
156 SetMenuBar(mbar);
157
158 mbar->Check(ID_PAINT_BG, true);
159
160 CreateStatusBar(2);
161 if ( numImages != 1 )
162 SetStatusText(wxString::Format("%d images", numImages), 1);
163
164 SetClientSize(bitmap.GetWidth(), bitmap.GetHeight());
165
166 UpdateStatusBar();
167
168 Show();
169
170 return true;
171 }
172
173 void OnEraseBackground(wxEraseEvent& WXUNUSED(event))
174 {
175 // do nothing here to be able to see how transparent images are shown
176 }
177
178 void OnPaint(wxPaintEvent& WXUNUSED(event))
179 {
180 wxPaintDC dc(this);
181
182 if ( GetMenuBar()->IsChecked(ID_PAINT_BG) )
183 ClearBackground();
184
185 const wxSize size = GetClientSize();
186 dc.DrawBitmap(m_bitmap,
187 (size.x - m_bitmap.GetWidth())/2,
188 (size.y - m_bitmap.GetHeight())/2,
189 true /* use mask */);
190 }
191
192 void OnSave(wxCommandEvent& WXUNUSED(event))
193 {
194 #if wxUSE_FILEDLG
195 wxImage image = m_bitmap.ConvertToImage();
196
197 wxString savefilename = wxFileSelector( wxT("Save Image"),
198 wxEmptyString,
199 wxEmptyString,
200 (const wxChar *)NULL,
201 wxT("BMP files (*.bmp)|*.bmp|")
202 wxT("PNG files (*.png)|*.png|")
203 wxT("JPEG files (*.jpg)|*.jpg|")
204 wxT("GIF files (*.gif)|*.gif|")
205 wxT("TIFF files (*.tif)|*.tif|")
206 wxT("PCX files (*.pcx)|*.pcx|")
207 wxT("ICO files (*.ico)|*.ico|")
208 wxT("CUR files (*.cur)|*.cur"),
209 wxFD_SAVE,
210 this);
211
212 if ( savefilename.empty() )
213 return;
214
215 wxString extension;
216 wxFileName::SplitPath(savefilename, NULL, NULL, &extension);
217
218 bool saved = false;
219 if ( extension == _T("bmp") )
220 {
221 static const int bppvalues[] =
222 {
223 wxBMP_1BPP,
224 wxBMP_1BPP_BW,
225 wxBMP_4BPP,
226 wxBMP_8BPP,
227 wxBMP_8BPP_GREY,
228 wxBMP_8BPP_RED,
229 wxBMP_8BPP_PALETTE,
230 wxBMP_24BPP
231 };
232
233 const wxString bppchoices[] =
234 {
235 _T("1 bpp color"),
236 _T("1 bpp B&W"),
237 _T("4 bpp color"),
238 _T("8 bpp color"),
239 _T("8 bpp greyscale"),
240 _T("8 bpp red"),
241 _T("8 bpp own palette"),
242 _T("24 bpp")
243 };
244
245 int bppselection = wxGetSingleChoiceIndex(_T("Set BMP BPP"),
246 _T("Image sample: save file"),
247 WXSIZEOF(bppchoices),
248 bppchoices,
249 this);
250 if ( bppselection != -1 )
251 {
252 int format = bppvalues[bppselection];
253 image.SetOption(wxIMAGE_OPTION_BMP_FORMAT, format);
254
255 if ( format == wxBMP_8BPP_PALETTE )
256 {
257 unsigned char *cmap = new unsigned char [256];
258 for ( int i = 0; i < 256; i++ )
259 cmap[i] = (unsigned char)i;
260 image.SetPalette(wxPalette(256, cmap, cmap, cmap));
261
262 delete[] cmap;
263 }
264 }
265 }
266 else if ( extension == _T("png") )
267 {
268 static const int pngvalues[] =
269 {
270 wxPNG_TYPE_COLOUR,
271 wxPNG_TYPE_COLOUR,
272 wxPNG_TYPE_GREY,
273 wxPNG_TYPE_GREY,
274 wxPNG_TYPE_GREY_RED,
275 wxPNG_TYPE_GREY_RED,
276 };
277
278 const wxString pngchoices[] =
279 {
280 _T("Colour 8bpp"),
281 _T("Colour 16bpp"),
282 _T("Grey 8bpp"),
283 _T("Grey 16bpp"),
284 _T("Grey red 8bpp"),
285 _T("Grey red 16bpp"),
286 };
287
288 int sel = wxGetSingleChoiceIndex(_T("Set PNG format"),
289 _T("Image sample: save file"),
290 WXSIZEOF(pngchoices),
291 pngchoices,
292 this);
293 if ( sel != -1 )
294 {
295 image.SetOption(wxIMAGE_OPTION_PNG_FORMAT, pngvalues[sel]);
296 image.SetOption(wxIMAGE_OPTION_PNG_BITDEPTH, sel % 2 ? 16 : 8);
297
298 // these values are taken from OptiPNG with -o3 switch
299 const wxString compressionChoices[] =
300 {
301 _T("compression = 9, memory = 8, strategy = 0, filter = 0"),
302 _T("compression = 9, memory = 9, strategy = 0, filter = 0"),
303 _T("compression = 9, memory = 8, strategy = 1, filter = 0"),
304 _T("compression = 9, memory = 9, strategy = 1, filter = 0"),
305 _T("compression = 1, memory = 8, strategy = 2, filter = 0"),
306 _T("compression = 1, memory = 9, strategy = 2, filter = 0"),
307 _T("compression = 9, memory = 8, strategy = 0, filter = 5"),
308 _T("compression = 9, memory = 9, strategy = 0, filter = 5"),
309 _T("compression = 9, memory = 8, strategy = 1, filter = 5"),
310 _T("compression = 9, memory = 9, strategy = 1, filter = 5"),
311 _T("compression = 1, memory = 8, strategy = 2, filter = 5"),
312 _T("compression = 1, memory = 9, strategy = 2, filter = 5"),
313 };
314
315 int sel = wxGetSingleChoiceIndex(_T("Select compression option (Cancel to use default)\n"),
316 _T("PNG Compression Options"),
317 WXSIZEOF(compressionChoices),
318 compressionChoices,
319 this);
320 if (sel != -1)
321 {
322 const int zc[] = {9, 9, 9, 9, 1, 1, 9, 9, 9, 9, 1, 1};
323 const int zm[] = {8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9};
324 const int zs[] = {0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2};
325 const int f[] = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
326 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8};
327
328 image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_LEVEL , zc[sel]);
329 image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_MEM_LEVEL , zm[sel]);
330 image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_STRATEGY , zs[sel]);
331 image.SetOption(wxIMAGE_OPTION_PNG_FILTER , f[sel]);
332 image.SetOption(wxIMAGE_OPTION_PNG_COMPRESSION_BUFFER_SIZE, 1048576); // 1 MB
333 }
334 }
335 }
336 else if ( extension == _T("cur") )
337 {
338 image.Rescale(32,32);
339 image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, 0);
340 image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, 0);
341 // This shows how you can save an image with explicitly
342 // specified image format:
343 saved = image.SaveFile(savefilename, wxBITMAP_TYPE_CUR);
344 }
345
346 if ( !saved )
347 {
348 // This one guesses image format from filename extension
349 // (it may fail if the extension is not recognized):
350 image.SaveFile(savefilename);
351 }
352 #endif // wxUSE_FILEDLG
353 }
354
355 void OnResize(wxCommandEvent& WXUNUSED(event))
356 {
357 wxImage img(m_bitmap.ConvertToImage());
358
359 const wxSize size = GetClientSize();
360 img.Rescale(size.x, size.y, wxIMAGE_QUALITY_HIGH);
361 m_bitmap = wxBitmap(img);
362
363 UpdateStatusBar();
364 Refresh();
365 }
366
367 void OnRotate(wxCommandEvent& event)
368 {
369 double angle = 5;
370 if ( event.GetId() == ID_ROTATE_LEFT )
371 angle = -angle;
372
373 wxImage img(m_bitmap.ConvertToImage());
374 img = img.Rotate(angle, wxPoint(img.GetWidth() / 2, img.GetHeight() / 2));
375 if ( !img.Ok() )
376 {
377 wxLogWarning(_T("Rotation failed"));
378 return;
379 }
380
381 m_bitmap = wxBitmap(img);
382
383 UpdateStatusBar();
384 Refresh();
385 }
386
387 private:
388 void UpdateStatusBar()
389 {
390 wxLogStatus(this, _T("Image size: (%d, %d)"),
391 m_bitmap.GetWidth(),
392 m_bitmap.GetHeight());
393 }
394
395 wxBitmap m_bitmap;
396
397 DECLARE_EVENT_TABLE()
398 };
399
400 #ifdef wxHAVE_RAW_BITMAP
401
402 #include "wx/rawbmp.h"
403
404 class MyRawBitmapFrame : public wxFrame
405 {
406 public:
407 enum
408 {
409 BORDER = 15,
410 SIZE = 150,
411 REAL_SIZE = SIZE - 2*BORDER
412 };
413
414 MyRawBitmapFrame(wxFrame *parent)
415 : wxFrame(parent, wxID_ANY, _T("Raw bitmaps (how exciting)")),
416 m_bitmap(SIZE, SIZE, 24),
417 m_alphaBitmap(SIZE, SIZE, 32)
418 {
419 SetClientSize(SIZE, SIZE*2+25);
420
421 InitAlphaBitmap();
422 InitBitmap();
423
424 }
425
426 void InitAlphaBitmap()
427 {
428 // First, clear the whole bitmap by making it alpha
429 {
430 wxAlphaPixelData data( m_alphaBitmap, wxPoint(0,0), wxSize(SIZE, SIZE) );
431 if ( !data )
432 {
433 wxLogError(_T("Failed to gain raw access to bitmap data"));
434 return;
435 }
436 wxAlphaPixelData::Iterator p(data);
437 for ( int y = 0; y < SIZE; ++y )
438 {
439 wxAlphaPixelData::Iterator rowStart = p;
440 for ( int x = 0; x < SIZE; ++x )
441 {
442 p.Alpha() = 0;
443 ++p; // same as p.OffsetX(1)
444 }
445 p = rowStart;
446 p.OffsetY(data, 1);
447 }
448 }
449
450 // Then, draw colourful alpha-blended stripes
451 wxAlphaPixelData data(m_alphaBitmap, wxPoint(BORDER, BORDER),
452 wxSize(REAL_SIZE, REAL_SIZE));
453 if ( !data )
454 {
455 wxLogError(_T("Failed to gain raw access to bitmap data"));
456 return;
457 }
458
459 wxAlphaPixelData::Iterator p(data);
460
461 for ( int y = 0; y < REAL_SIZE; ++y )
462 {
463 wxAlphaPixelData::Iterator rowStart = p;
464
465 int r = y < REAL_SIZE/3 ? 255 : 0,
466 g = (REAL_SIZE/3 <= y) && (y < 2*(REAL_SIZE/3)) ? 255 : 0,
467 b = 2*(REAL_SIZE/3) <= y ? 255 : 0;
468
469 for ( int x = 0; x < REAL_SIZE; ++x )
470 {
471 // note that RGB must be premultiplied by alpha
472 unsigned a = (wxAlphaPixelData::Iterator::ChannelType)((x*255.)/REAL_SIZE);
473 p.Red() = r * a / 256;
474 p.Green() = g * a / 256;
475 p.Blue() = b * a / 256;
476 p.Alpha() = a;
477
478 ++p; // same as p.OffsetX(1)
479 }
480
481 p = rowStart;
482 p.OffsetY(data, 1);
483 }
484 }
485
486 void InitBitmap()
487 {
488 // draw some colourful stripes without alpha
489 wxNativePixelData data(m_bitmap);
490 if ( !data )
491 {
492 wxLogError(_T("Failed to gain raw access to bitmap data"));
493 return;
494 }
495
496 wxNativePixelData::Iterator p(data);
497 for ( int y = 0; y < SIZE; ++y )
498 {
499 wxNativePixelData::Iterator rowStart = p;
500
501 int r = y < SIZE/3 ? 255 : 0,
502 g = (SIZE/3 <= y) && (y < 2*(SIZE/3)) ? 255 : 0,
503 b = 2*(SIZE/3) <= y ? 255 : 0;
504
505 for ( int x = 0; x < SIZE; ++x )
506 {
507 p.Red() = r;
508 p.Green() = g;
509 p.Blue() = b;
510 ++p; // same as p.OffsetX(1)
511 }
512
513 p = rowStart;
514 p.OffsetY(data, 1);
515 }
516 }
517
518 void OnPaint(wxPaintEvent& WXUNUSED(event))
519 {
520 wxPaintDC dc( this );
521 dc.DrawText(_T("This is alpha and raw bitmap test"), 0, BORDER);
522 dc.DrawText(_T("This is alpha and raw bitmap test"), 0, SIZE/2 - BORDER);
523 dc.DrawText(_T("This is alpha and raw bitmap test"), 0, SIZE - 2*BORDER);
524 dc.DrawBitmap( m_alphaBitmap, 0, 0, true /* use mask */ );
525
526 dc.DrawText(_T("Raw bitmap access without alpha"), 0, SIZE+5);
527 dc.DrawBitmap( m_bitmap, 0, SIZE+5+dc.GetCharHeight());
528 }
529
530 private:
531 wxBitmap m_bitmap;
532 wxBitmap m_alphaBitmap;
533
534 DECLARE_EVENT_TABLE()
535 };
536
537 #endif // wxHAVE_RAW_BITMAP
538
539
540 // ============================================================================
541 // implementations
542 // ============================================================================
543
544 //-----------------------------------------------------------------------------
545 // MyImageFrame
546 //-----------------------------------------------------------------------------
547
548 BEGIN_EVENT_TABLE(MyImageFrame, wxFrame)
549 EVT_ERASE_BACKGROUND(MyImageFrame::OnEraseBackground)
550 EVT_PAINT(MyImageFrame::OnPaint)
551
552 EVT_MENU(wxID_SAVE, MyImageFrame::OnSave)
553 EVT_MENU_RANGE(ID_ROTATE_LEFT, ID_ROTATE_RIGHT, MyImageFrame::OnRotate)
554 EVT_MENU(ID_RESIZE, MyImageFrame::OnResize)
555 END_EVENT_TABLE()
556
557 //-----------------------------------------------------------------------------
558 // MyRawBitmapFrame
559 //-----------------------------------------------------------------------------
560
561 #ifdef wxHAVE_RAW_BITMAP
562
563 BEGIN_EVENT_TABLE(MyRawBitmapFrame, wxFrame)
564 EVT_PAINT(MyRawBitmapFrame::OnPaint)
565 END_EVENT_TABLE()
566
567 #endif // wxHAVE_RAW_BITMAP
568
569 //-----------------------------------------------------------------------------
570 // MyFrame
571 //-----------------------------------------------------------------------------
572
573 enum
574 {
575 ID_QUIT = wxID_EXIT,
576 ID_ABOUT = wxID_ABOUT,
577 ID_NEW = 100,
578 ID_INFO,
579 ID_SHOWRAW,
580 ID_SHOWTHUMBNAIL
581 };
582
583 IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
584 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
585 EVT_MENU (ID_ABOUT, MyFrame::OnAbout)
586 EVT_MENU (ID_QUIT, MyFrame::OnQuit)
587 EVT_MENU (ID_NEW, MyFrame::OnNewFrame)
588 EVT_MENU (ID_INFO, MyFrame::OnImageInfo)
589 EVT_MENU (ID_SHOWTHUMBNAIL, MyFrame::OnThumbnail)
590 #ifdef wxHAVE_RAW_BITMAP
591 EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap)
592 #endif
593 #if wxUSE_CLIPBOARD
594 EVT_MENU(wxID_COPY, MyFrame::OnCopy)
595 EVT_MENU(wxID_PASTE, MyFrame::OnPaste)
596 #endif // wxUSE_CLIPBOARD
597 END_EVENT_TABLE()
598
599 MyFrame::MyFrame()
600 : wxFrame( (wxFrame *)NULL, wxID_ANY, _T("wxImage sample"),
601 wxPoint(20, 20), wxSize(950, 700) )
602 {
603 SetIcon(wxICON(sample));
604
605 wxMenuBar *menu_bar = new wxMenuBar();
606
607 wxMenu *menuImage = new wxMenu;
608 menuImage->Append( ID_NEW, _T("&Show any image...\tCtrl-O"));
609 menuImage->Append( ID_INFO, _T("Show image &information...\tCtrl-I"));
610 #ifdef wxHAVE_RAW_BITMAP
611 menuImage->AppendSeparator();
612 menuImage->Append( ID_SHOWRAW, _T("Test &raw bitmap...\tCtrl-R"));
613 #endif
614 menuImage->AppendSeparator();
615 menuImage->Append( ID_SHOWTHUMBNAIL, _T("Test &thumbnail...\tCtrl-T"),
616 "Test scaling the image during load (try with JPEG)");
617 menuImage->AppendSeparator();
618 menuImage->Append( ID_ABOUT, _T("&About..."));
619 menuImage->AppendSeparator();
620 menuImage->Append( ID_QUIT, _T("E&xit\tCtrl-Q"));
621 menu_bar->Append(menuImage, _T("&Image"));
622
623 #if wxUSE_CLIPBOARD
624 wxMenu *menuClipboard = new wxMenu;
625 menuClipboard->Append(wxID_COPY, _T("&Copy test image\tCtrl-C"));
626 menuClipboard->Append(wxID_PASTE, _T("&Paste image\tCtrl-V"));
627 menu_bar->Append(menuClipboard, _T("&Clipboard"));
628 #endif // wxUSE_CLIPBOARD
629
630 SetMenuBar( menu_bar );
631
632 #if wxUSE_STATUSBAR
633 CreateStatusBar(2);
634 int widths[] = { -1, 100 };
635 SetStatusWidths( 2, widths );
636 #endif // wxUSE_STATUSBAR
637
638 m_canvas = new MyCanvas( this, wxID_ANY, wxPoint(0,0), wxSize(10,10) );
639
640 // 500 width * 2750 height
641 m_canvas->SetScrollbars( 10, 10, 50, 275 );
642 }
643
644 void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) )
645 {
646 Close( true );
647 }
648
649 void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) )
650 {
651 (void)wxMessageBox( _T("wxImage demo\n")
652 _T("Robert Roebling (c) 1998,2000"),
653 _T("About wxImage Demo"), wxICON_INFORMATION | wxOK );
654 }
655
656 wxString MyFrame::LoadUserImage(wxImage& image)
657 {
658 wxString filename;
659
660 #if wxUSE_FILEDLG
661 filename = wxFileSelector(_T("Select image file"));
662 if ( !filename.empty() )
663 {
664 if ( !image.LoadFile(filename) )
665 {
666 wxLogError(_T("Couldn't load image from '%s'."), filename.c_str());
667
668 return wxEmptyString;
669 }
670 }
671 #endif // wxUSE_FILEDLG
672
673 return filename;
674 }
675
676 void MyFrame::OnNewFrame( wxCommandEvent &WXUNUSED(event) )
677 {
678 wxImage image;
679 wxString filename = LoadUserImage(image);
680 if ( !filename.empty() )
681 new MyImageFrame(this, filename, image);
682 }
683
684 void MyFrame::OnImageInfo( wxCommandEvent &WXUNUSED(event) )
685 {
686 wxImage image;
687 if ( !LoadUserImage(image).empty() )
688 {
689 // TODO: show more information about the file
690 wxString info = wxString::Format("Image size: %dx%d",
691 image.GetWidth(),
692 image.GetHeight());
693
694 int xres = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX),
695 yres = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY);
696 if ( xres || yres )
697 {
698 info += wxString::Format("\nResolution: %dx%d", xres, yres);
699 switch ( image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONUNIT) )
700 {
701 default:
702 wxFAIL_MSG( "unknown image resolution units" );
703 // fall through
704
705 case wxIMAGE_RESOLUTION_NONE:
706 info += " in default units";
707 break;
708
709 case wxIMAGE_RESOLUTION_INCHES:
710 info += " in";
711 break;
712
713 case wxIMAGE_RESOLUTION_CM:
714 info += " cm";
715 break;
716 }
717 }
718
719 wxLogMessage("%s", info);
720 }
721 }
722
723 #ifdef wxHAVE_RAW_BITMAP
724
725 void MyFrame::OnTestRawBitmap( wxCommandEvent &WXUNUSED(event) )
726 {
727 (new MyRawBitmapFrame(this))->Show();
728 }
729
730 #endif // wxHAVE_RAW_BITMAP
731
732 #if wxUSE_CLIPBOARD
733
734 void MyFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
735 {
736 wxBitmapDataObject *dobjBmp = new wxBitmapDataObject;
737 dobjBmp->SetBitmap(m_canvas->my_horse_png);
738
739 wxTheClipboard->Open();
740
741 if ( !wxTheClipboard->SetData(dobjBmp) )
742 {
743 wxLogError(_T("Failed to copy bitmap to clipboard"));
744 }
745
746 wxTheClipboard->Close();
747 }
748
749 void MyFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
750 {
751 wxBitmapDataObject dobjBmp;
752
753 wxTheClipboard->Open();
754 if ( !wxTheClipboard->GetData(dobjBmp) )
755 {
756 wxLogMessage(_T("No bitmap data in the clipboard"));
757 }
758 else
759 {
760 new MyImageFrame(this, _T("Clipboard"), dobjBmp.GetBitmap());
761 }
762 wxTheClipboard->Close();
763 }
764
765 #endif // wxUSE_CLIPBOARD
766
767 void MyFrame::OnThumbnail( wxCommandEvent &WXUNUSED(event) )
768 {
769 #if wxUSE_FILEDLG
770 wxString filename = wxFileSelector(_T("Select image file"));
771 if ( filename.empty() )
772 return;
773
774 static const int THUMBNAIL_WIDTH = 320;
775 static const int THUMBNAIL_HEIGHT = 240;
776
777 wxImage image;
778 image.SetOption(wxIMAGE_OPTION_MAX_WIDTH, THUMBNAIL_WIDTH);
779 image.SetOption(wxIMAGE_OPTION_MAX_HEIGHT, THUMBNAIL_HEIGHT);
780
781 wxStopWatch sw;
782 if ( !image.LoadFile(filename) )
783 {
784 wxLogError(_T("Couldn't load image from '%s'."), filename.c_str());
785 return;
786 }
787
788 const long loadTime = sw.Time();
789
790 MyImageFrame * const frame = new MyImageFrame(this, filename, image);
791 wxLogStatus(frame, "Loaded \"%s\" in %ldms", filename, loadTime);
792 #else
793 wxLogError( _T("Couldn't create file selector dialog") );
794 return;
795 #endif // wxUSE_FILEDLG
796 }
797
798 //-----------------------------------------------------------------------------
799 // MyApp
800 //-----------------------------------------------------------------------------
801
802 IMPLEMENT_APP(MyApp)
803
804 bool MyApp::OnInit()
805 {
806 if ( !wxApp::OnInit() )
807 return false;
808
809 wxInitAllImageHandlers();
810
811 wxFrame *frame = new MyFrame();
812 frame->Show( true );
813
814 return true;
815 }