A couple of fixes to Brazilian Portuguese translations from Felipe.
[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 // Copyright: (c) 1998-2005 Robert Roebling
8 // (c) 2005-2009 Vadim Zeitlin
9 // Licence: 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/graphics.h"
27 #include "wx/mstream.h"
28 #include "wx/wfstream.h"
29 #include "wx/quantize.h"
30 #include "wx/scopedptr.h"
31 #include "wx/stopwatch.h"
32 #include "wx/versioninfo.h"
33
34 #if wxUSE_CLIPBOARD
35 #include "wx/dataobj.h"
36 #include "wx/clipbrd.h"
37 #endif // wxUSE_CLIPBOARD
38
39 #if defined(__WXMSW__)
40 #ifdef wxHAVE_RAW_BITMAP
41 #include "wx/rawbmp.h"
42 #endif
43 #endif
44
45 #if defined(__WXMAC__) || defined(__WXGTK__)
46 #define wxHAVE_RAW_BITMAP
47 #include "wx/rawbmp.h"
48 #endif
49
50 #include "canvas.h"
51
52 #ifndef wxHAS_IMAGES_IN_RESOURCES
53 #include "../sample.xpm"
54 #endif
55
56 // ============================================================================
57 // declarations
58 // ============================================================================
59
60 //-----------------------------------------------------------------------------
61 // MyApp
62 //-----------------------------------------------------------------------------
63
64 class MyApp: public wxApp
65 {
66 public:
67 virtual bool OnInit();
68 };
69
70 // ----------------------------------------------------------------------------
71 // MyFrame
72 // ----------------------------------------------------------------------------
73
74 class MyFrame: public wxFrame
75 {
76 public:
77 MyFrame();
78
79 void OnAbout( wxCommandEvent &event );
80 void OnNewFrame( wxCommandEvent &event );
81 void OnImageInfo( wxCommandEvent &event );
82 void OnThumbnail( wxCommandEvent &event );
83
84 #ifdef wxHAVE_RAW_BITMAP
85 void OnTestRawBitmap( wxCommandEvent &event );
86 #endif // wxHAVE_RAW_BITMAP
87 #if wxUSE_GRAPHICS_CONTEXT
88 void OnTestGraphics(wxCommandEvent& event);
89 #endif // wxUSE_GRAPHICS_CONTEXT
90 void OnQuit( wxCommandEvent &event );
91
92 #if wxUSE_CLIPBOARD
93 void OnCopy(wxCommandEvent& event);
94 void OnPaste(wxCommandEvent& event);
95 #endif // wxUSE_CLIPBOARD
96
97 MyCanvas *m_canvas;
98
99 private:
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
107 DECLARE_DYNAMIC_CLASS(MyFrame)
108 DECLARE_EVENT_TABLE()
109 };
110
111 // ----------------------------------------------------------------------------
112 // Frame used for showing a standalone image
113 // ----------------------------------------------------------------------------
114
115 enum
116 {
117 ID_ROTATE_LEFT = wxID_HIGHEST+1,
118 ID_ROTATE_RIGHT,
119 ID_RESIZE,
120 ID_PAINT_BG
121 };
122
123 class MyImageFrame : public wxFrame
124 {
125 public:
126 MyImageFrame(wxFrame *parent, const wxString& desc, const wxImage& image)
127 {
128 Create(parent, desc, wxBitmap(image), image.GetImageCount(desc));
129 }
130
131 MyImageFrame(wxFrame *parent, const wxString& desc, const wxBitmap& bitmap)
132 {
133 Create(parent, desc, bitmap);
134 }
135
136 private:
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,
143 wxString::Format(wxT("Image from %s"), desc),
144 wxDefaultPosition, wxDefaultSize,
145 wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE) )
146 return false;
147
148 m_bitmap = bitmap;
149 m_zoom = 1.;
150
151 wxMenu *menu = new wxMenu;
152 menu->Append(wxID_SAVEAS);
153 menu->AppendSeparator();
154 menu->AppendCheckItem(ID_PAINT_BG, wxT("&Paint background"),
155 "Uncheck this for transparent images");
156 menu->AppendSeparator();
157 menu->Append(ID_RESIZE, wxT("&Fit to window\tCtrl-F"));
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");
161 menu->AppendSeparator();
162 menu->Append(ID_ROTATE_LEFT, wxT("Rotate &left\tCtrl-L"));
163 menu->Append(ID_ROTATE_RIGHT, wxT("Rotate &right\tCtrl-R"));
164
165 wxMenuBar *mbar = new wxMenuBar;
166 mbar->Append(menu, wxT("&Image"));
167 SetMenuBar(mbar);
168
169 mbar->Check(ID_PAINT_BG, true);
170
171 CreateStatusBar(2);
172 if ( numImages != 1 )
173 SetStatusText(wxString::Format("%d images", numImages), 1);
174
175 SetClientSize(bitmap.GetWidth(), bitmap.GetHeight());
176
177 UpdateStatusBar();
178
179 Show();
180
181 return true;
182 }
183
184 void OnEraseBackground(wxEraseEvent& WXUNUSED(event))
185 {
186 // do nothing here to be able to see how transparent images are shown
187 }
188
189 void OnPaint(wxPaintEvent& WXUNUSED(event))
190 {
191 wxPaintDC dc(this);
192
193 if ( GetMenuBar()->IsChecked(ID_PAINT_BG) )
194 dc.Clear();
195
196 dc.SetUserScale(m_zoom, m_zoom);
197
198 const wxSize size = GetClientSize();
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 );
206 }
207
208 void OnSave(wxCommandEvent& WXUNUSED(event))
209 {
210 #if wxUSE_FILEDLG
211 wxImage image = m_bitmap.ConvertToImage();
212
213 wxString savefilename = wxFileSelector( wxT("Save Image"),
214 wxEmptyString,
215 wxEmptyString,
216 wxEmptyString,
217 wxT("BMP files (*.bmp)|*.bmp|")
218 #if wxUSE_LIBPNG
219 wxT("PNG files (*.png)|*.png|")
220 #endif
221 #if wxUSE_LIBJPEG
222 wxT("JPEG files (*.jpg)|*.jpg|")
223 #endif
224 #if wxUSE_GIF
225 wxT("GIF files (*.gif)|*.gif|")
226 #endif
227 #if wxUSE_LIBTIFF
228 wxT("TIFF files (*.tif)|*.tif|")
229 #endif
230 #if wxUSE_PCX
231 wxT("PCX files (*.pcx)|*.pcx|")
232 #endif
233 #if wxUSE_XPM
234 wxT("X PixMap files (*.xpm)|*.xpm|")
235 #endif
236 wxT("ICO files (*.ico)|*.ico|")
237 wxT("CUR files (*.cur)|*.cur"),
238 wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
239 this);
240
241 if ( savefilename.empty() )
242 return;
243
244 wxString extension;
245 wxFileName::SplitPath(savefilename, NULL, NULL, &extension);
246
247 bool saved = false;
248 if ( extension == wxT("bmp") )
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
262 const wxString bppchoices[] =
263 {
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")
272 };
273
274 int bppselection = wxGetSingleChoiceIndex(wxT("Set BMP BPP"),
275 wxT("Image sample: save file"),
276 WXSIZEOF(bppchoices),
277 bppchoices,
278 this);
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
291 delete[] cmap;
292 }
293 }
294 }
295 #if wxUSE_LIBPNG
296 else if ( extension == wxT("png") )
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
308 const wxString pngchoices[] =
309 {
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"),
316 };
317
318 int sel = wxGetSingleChoiceIndex(wxT("Set PNG format"),
319 wxT("Image sample: save file"),
320 WXSIZEOF(pngchoices),
321 pngchoices,
322 this);
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);
327
328 // these values are taken from OptiPNG with -o3 switch
329 const wxString compressionChoices[] =
330 {
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"),
343 };
344
345 int sel = wxGetSingleChoiceIndex(wxT("Select compression option (Cancel to use default)\n"),
346 wxT("PNG Compression Options"),
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 }
364 }
365 }
366 #endif // wxUSE_LIBPNG
367 else if ( extension == wxT("cur") )
368 {
369 image.Rescale(32,32);
370 image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, 0);
371 image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, 0);
372 // This shows how you can save an image with explicitly
373 // specified image format:
374 saved = image.SaveFile(savefilename, wxBITMAP_TYPE_CUR);
375 }
376
377 if ( !saved )
378 {
379 // This one guesses image format from filename extension
380 // (it may fail if the extension is not recognized):
381 image.SaveFile(savefilename);
382 }
383 #endif // wxUSE_FILEDLG
384 }
385
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();
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();
407 }
408
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());
416 img = img.Rotate(angle, wxPoint(img.GetWidth() / 2, img.GetHeight() / 2));
417 if ( !img.IsOk() )
418 {
419 wxLogWarning(wxT("Rotation failed"));
420 return;
421 }
422
423 m_bitmap = wxBitmap(img);
424
425 UpdateStatusBar();
426 }
427
428 void UpdateStatusBar()
429 {
430 wxLogStatus(this, wxT("Image size: (%d, %d), zoom %.2f"),
431 m_bitmap.GetWidth(),
432 m_bitmap.GetHeight(),
433 m_zoom);
434 Refresh();
435 }
436
437 wxBitmap m_bitmap;
438 double m_zoom;
439
440 DECLARE_EVENT_TABLE()
441 };
442
443 #ifdef wxHAVE_RAW_BITMAP
444
445 #include "wx/rawbmp.h"
446
447 class MyRawBitmapFrame : public wxFrame
448 {
449 public:
450 enum
451 {
452 BORDER = 15,
453 SIZE = 150,
454 REAL_SIZE = SIZE - 2*BORDER
455 };
456
457 MyRawBitmapFrame(wxFrame *parent)
458 : wxFrame(parent, wxID_ANY, wxT("Raw bitmaps (how exciting)")),
459 m_bitmap(SIZE, SIZE, 24),
460 m_alphaBitmap(SIZE, SIZE, 32)
461 {
462 SetClientSize(SIZE, SIZE*2+25);
463
464 InitAlphaBitmap();
465 InitBitmap();
466
467 }
468
469 void InitAlphaBitmap()
470 {
471 // First, clear the whole bitmap by making it alpha
472 {
473 wxAlphaPixelData data( m_alphaBitmap, wxPoint(0,0), wxSize(SIZE, SIZE) );
474 if ( !data )
475 {
476 wxLogError(wxT("Failed to gain raw access to bitmap data"));
477 return;
478 }
479 wxAlphaPixelData::Iterator p(data);
480 for ( int y = 0; y < SIZE; ++y )
481 {
482 wxAlphaPixelData::Iterator rowStart = p;
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 }
492
493 // Then, draw colourful alpha-blended stripes
494 wxAlphaPixelData data(m_alphaBitmap, wxPoint(BORDER, BORDER),
495 wxSize(REAL_SIZE, REAL_SIZE));
496 if ( !data )
497 {
498 wxLogError(wxT("Failed to gain raw access to bitmap data"));
499 return;
500 }
501
502 wxAlphaPixelData::Iterator p(data);
503
504 for ( int y = 0; y < REAL_SIZE; ++y )
505 {
506 wxAlphaPixelData::Iterator rowStart = p;
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 {
514 // note that RGB must be premultiplied by alpha
515 unsigned a = (wxAlphaPixelData::Iterator::ChannelType)((x*255.)/REAL_SIZE);
516 p.Red() = r * a / 256;
517 p.Green() = g * a / 256;
518 p.Blue() = b * a / 256;
519 p.Alpha() = a;
520
521 ++p; // same as p.OffsetX(1)
522 }
523
524 p = rowStart;
525 p.OffsetY(data, 1);
526 }
527 }
528
529 void InitBitmap()
530 {
531 // draw some colourful stripes without alpha
532 wxNativePixelData data(m_bitmap);
533 if ( !data )
534 {
535 wxLogError(wxT("Failed to gain raw access to bitmap data"));
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
561 void OnPaint(wxPaintEvent& WXUNUSED(event))
562 {
563 wxPaintDC dc( this );
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);
567 dc.DrawBitmap( m_alphaBitmap, 0, 0, true /* use mask */ );
568
569 dc.DrawText(wxT("Raw bitmap access without alpha"), 0, SIZE+5);
570 dc.DrawBitmap( m_bitmap, 0, SIZE+5+dc.GetCharHeight());
571 }
572
573 private:
574 wxBitmap m_bitmap;
575 wxBitmap m_alphaBitmap;
576
577 DECLARE_EVENT_TABLE()
578 };
579
580 #endif // wxHAVE_RAW_BITMAP
581
582
583 // ============================================================================
584 // implementations
585 // ============================================================================
586
587 //-----------------------------------------------------------------------------
588 // MyImageFrame
589 //-----------------------------------------------------------------------------
590
591 BEGIN_EVENT_TABLE(MyImageFrame, wxFrame)
592 EVT_ERASE_BACKGROUND(MyImageFrame::OnEraseBackground)
593 EVT_PAINT(MyImageFrame::OnPaint)
594
595 EVT_MENU(wxID_SAVEAS, MyImageFrame::OnSave)
596 EVT_MENU_RANGE(ID_ROTATE_LEFT, ID_ROTATE_RIGHT, MyImageFrame::OnRotate)
597 EVT_MENU(ID_RESIZE, MyImageFrame::OnResize)
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)
602 END_EVENT_TABLE()
603
604 //-----------------------------------------------------------------------------
605 // MyRawBitmapFrame
606 //-----------------------------------------------------------------------------
607
608 #ifdef wxHAVE_RAW_BITMAP
609
610 BEGIN_EVENT_TABLE(MyRawBitmapFrame, wxFrame)
611 EVT_PAINT(MyRawBitmapFrame::OnPaint)
612 END_EVENT_TABLE()
613
614 #endif // wxHAVE_RAW_BITMAP
615
616 //-----------------------------------------------------------------------------
617 // MyFrame
618 //-----------------------------------------------------------------------------
619
620 enum
621 {
622 ID_QUIT = wxID_EXIT,
623 ID_ABOUT = wxID_ABOUT,
624 ID_NEW = 100,
625 ID_INFO,
626 ID_SHOWRAW,
627 ID_GRAPHICS,
628 ID_SHOWTHUMBNAIL
629 };
630
631 IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
632 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
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)
638 #ifdef wxHAVE_RAW_BITMAP
639 EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap)
640 #endif
641 #if wxUSE_GRAPHICS_CONTEXT
642 EVT_MENU (ID_GRAPHICS, MyFrame::OnTestGraphics)
643 #endif // wxUSE_GRAPHICS_CONTEXT
644 #if wxUSE_CLIPBOARD
645 EVT_MENU(wxID_COPY, MyFrame::OnCopy)
646 EVT_MENU(wxID_PASTE, MyFrame::OnPaste)
647 #endif // wxUSE_CLIPBOARD
648 END_EVENT_TABLE()
649
650 MyFrame::MyFrame()
651 : wxFrame( (wxFrame *)NULL, wxID_ANY, wxT("wxImage sample"),
652 wxPoint(20, 20), wxSize(950, 700) )
653 {
654 SetIcon(wxICON(sample));
655
656 wxMenuBar *menu_bar = new wxMenuBar();
657
658 wxMenu *menuImage = new wxMenu;
659 menuImage->Append( ID_NEW, wxT("&Show any image...\tCtrl-O"));
660 menuImage->Append( ID_INFO, wxT("Show image &information...\tCtrl-I"));
661 #ifdef wxHAVE_RAW_BITMAP
662 menuImage->AppendSeparator();
663 menuImage->Append( ID_SHOWRAW, wxT("Test &raw bitmap...\tCtrl-R"));
664 #endif
665 #if wxUSE_GRAPHICS_CONTEXT
666 menuImage->AppendSeparator();
667 menuImage->Append(ID_GRAPHICS, "Test &graphics context...\tCtrl-G");
668 #endif // wxUSE_GRAPHICS_CONTEXT
669 menuImage->AppendSeparator();
670 menuImage->Append( ID_SHOWTHUMBNAIL, wxT("Test &thumbnail...\tCtrl-T"),
671 "Test scaling the image during load (try with JPEG)");
672 menuImage->AppendSeparator();
673 menuImage->Append( ID_ABOUT, wxT("&About\tF1"));
674 menuImage->AppendSeparator();
675 menuImage->Append( ID_QUIT, wxT("E&xit\tCtrl-Q"));
676 menu_bar->Append(menuImage, wxT("&Image"));
677
678 #if wxUSE_CLIPBOARD
679 wxMenu *menuClipboard = new wxMenu;
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"));
683 #endif // wxUSE_CLIPBOARD
684
685 SetMenuBar( menu_bar );
686
687 #if wxUSE_STATUSBAR
688 CreateStatusBar(2);
689 int widths[] = { -1, 100 };
690 SetStatusWidths( 2, widths );
691 #endif // wxUSE_STATUSBAR
692
693 m_canvas = new MyCanvas( this, wxID_ANY, wxPoint(0,0), wxSize(10,10) );
694
695 // 500 width * 2750 height
696 m_canvas->SetScrollbars( 10, 10, 50, 275 );
697 m_canvas->SetCursor(wxImage("cursor.png"));
698 }
699
700 void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) )
701 {
702 Close( true );
703 }
704
705 #if wxUSE_ZLIB && wxUSE_STREAMS
706 #include "wx/zstream.h"
707 #endif
708
709 void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) )
710 {
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'),
734 "About wxImage Demo",
735 wxICON_INFORMATION | wxOK );
736 }
737
738 wxString MyFrame::LoadUserImage(wxImage& image)
739 {
740 wxString filename;
741
742 #if wxUSE_FILEDLG
743 filename = wxLoadFileSelector(wxT("image"), wxEmptyString);
744 if ( !filename.empty() )
745 {
746 if ( !image.LoadFile(filename) )
747 {
748 wxLogError(wxT("Couldn't load image from '%s'."), filename.c_str());
749
750 return wxEmptyString;
751 }
752 }
753 #endif // wxUSE_FILEDLG
754
755 return filename;
756 }
757
758 void MyFrame::OnNewFrame( wxCommandEvent &WXUNUSED(event) )
759 {
760 wxImage image;
761 wxString filename = LoadUserImage(image);
762 if ( !filename.empty() )
763 new MyImageFrame(this, filename, image);
764 }
765
766 void MyFrame::OnImageInfo( wxCommandEvent &WXUNUSED(event) )
767 {
768 wxImage image;
769 if ( !LoadUserImage(image).empty() )
770 {
771 // TODO: show more information about the file
772 wxString info = wxString::Format("Image size: %dx%d",
773 image.GetWidth(),
774 image.GetHeight());
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
786
787 case wxIMAGE_RESOLUTION_NONE:
788 info += " in default units";
789 break;
790
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 }
803 }
804
805 #ifdef wxHAVE_RAW_BITMAP
806
807 void MyFrame::OnTestRawBitmap( wxCommandEvent &WXUNUSED(event) )
808 {
809 (new MyRawBitmapFrame(this))->Show();
810 }
811
812 #endif // wxHAVE_RAW_BITMAP
813
814 #if wxUSE_GRAPHICS_CONTEXT
815
816 class MyGraphicsFrame : public wxFrame
817 {
818 public:
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
863 private:
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);
871 gc->DrawText("Bitmap", 0, HEIGHT/2);
872 gc->DrawBitmap(m_bitmap, 0, 0, WIDTH, HEIGHT);
873
874 wxGraphicsFont gf = gc->CreateFont(wxNORMAL_FONT->GetPixelSize().y, "");
875 gc->SetFont(gf);
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
886 void MyFrame::OnTestGraphics(wxCommandEvent& WXUNUSED(event))
887 {
888 new MyGraphicsFrame(this);
889 }
890
891 #endif // wxUSE_GRAPHICS_CONTEXT
892
893 #if wxUSE_CLIPBOARD
894
895 void MyFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
896 {
897 wxBitmapDataObject *dobjBmp = new wxBitmapDataObject;
898 dobjBmp->SetBitmap(m_canvas->my_horse_png);
899
900 wxTheClipboard->Open();
901
902 if ( !wxTheClipboard->SetData(dobjBmp) )
903 {
904 wxLogError(wxT("Failed to copy bitmap to clipboard"));
905 }
906
907 wxTheClipboard->Close();
908 }
909
910 void MyFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
911 {
912 wxBitmapDataObject dobjBmp;
913
914 wxTheClipboard->Open();
915 if ( !wxTheClipboard->GetData(dobjBmp) )
916 {
917 wxLogMessage(wxT("No bitmap data in the clipboard"));
918 }
919 else
920 {
921 new MyImageFrame(this, wxT("Clipboard"), dobjBmp.GetBitmap());
922 }
923 wxTheClipboard->Close();
924 }
925
926 #endif // wxUSE_CLIPBOARD
927
928 void MyFrame::OnThumbnail( wxCommandEvent &WXUNUSED(event) )
929 {
930 #if wxUSE_FILEDLG
931 wxString filename = wxLoadFileSelector(wxT("image"), wxEmptyString, wxEmptyString, this);
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 {
945 wxLogError(wxT("Couldn't load image from '%s'."), filename.c_str());
946 return;
947 }
948
949 int origWidth = image.GetOptionInt( wxIMAGE_OPTION_ORIGINAL_WIDTH );
950 int origHeight = image.GetOptionInt( wxIMAGE_OPTION_ORIGINAL_HEIGHT );
951
952 const long loadTime = sw.Time();
953
954 MyImageFrame * const frame = new MyImageFrame(this, filename, image);
955 wxLogStatus(frame, "Loaded \"%s\" in %ldms; original size was (%d, %d)",
956 filename, loadTime, origWidth, origHeight);
957 #else
958 wxLogError( wxT("Couldn't create file selector dialog") );
959 return;
960 #endif // wxUSE_FILEDLG
961 }
962
963 //-----------------------------------------------------------------------------
964 // MyApp
965 //-----------------------------------------------------------------------------
966
967 IMPLEMENT_APP(MyApp)
968
969 bool 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 }