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