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