]> git.saurik.com Git - wxWidgets.git/blob - samples/image/image.cpp
fix ANI loading; check for errors when calling Read()
[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:
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 #include "smile.xbm"
37 #include "smile.xpm"
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 // derived classes
51
52 class MyFrame;
53 class MyApp;
54
55 // MyCanvas
56
57 class MyCanvas: public wxScrolledWindow
58 {
59 public:
60 MyCanvas( wxWindow *parent, wxWindowID, const wxPoint &pos, const wxSize &size );
61 ~MyCanvas();
62 void OnPaint( wxPaintEvent &event );
63 void CreateAntiAliasedBitmap();
64
65 wxBitmap my_horse_png;
66 wxBitmap my_horse_jpeg;
67 wxBitmap my_horse_gif;
68 wxBitmap my_horse_bmp;
69 wxBitmap my_horse_bmp2;
70 wxBitmap my_horse_pcx;
71 wxBitmap my_horse_pnm;
72 wxBitmap my_horse_tiff;
73 wxBitmap my_horse_tga;
74 wxBitmap my_horse_xpm;
75 wxBitmap my_horse_ico32;
76 wxBitmap my_horse_ico16;
77 wxBitmap my_horse_ico;
78 wxBitmap my_horse_cur;
79
80 wxBitmap my_smile_xbm;
81 wxBitmap my_square;
82 wxBitmap my_anti;
83
84 wxBitmap my_horse_asciigrey_pnm;
85 wxBitmap my_horse_rawgrey_pnm;
86
87 wxBitmap colorized_horse_jpeg;
88 wxBitmap my_cmyk_jpeg;
89
90 wxBitmap my_toucan;
91 wxBitmap my_toucan_flipped_horiz;
92 wxBitmap my_toucan_flipped_vert;
93 wxBitmap my_toucan_flipped_both;
94 wxBitmap my_toucan_grey;
95 wxBitmap my_toucan_head;
96 wxBitmap my_toucan_scaled_normal;
97 wxBitmap my_toucan_scaled_high;
98 wxBitmap my_toucan_blur;
99
100 int xH, yH ;
101 int m_ani_images;
102 wxBitmap *my_horse_ani;
103
104 private:
105 wxBitmap m_bmpSmileXpm;
106 wxIcon m_iconSmileXpm;
107
108 DECLARE_EVENT_TABLE()
109 };
110
111
112 // MyFrame
113
114
115 class MyFrame: public wxFrame
116 {
117 public:
118 MyFrame();
119
120 void OnAbout( wxCommandEvent &event );
121 void OnNewFrame( wxCommandEvent &event );
122 void OnImageInfo( wxCommandEvent &event );
123 void OnThumbnail( wxCommandEvent &event );
124
125 #ifdef wxHAVE_RAW_BITMAP
126 void OnTestRawBitmap( wxCommandEvent &event );
127 #endif // wxHAVE_RAW_BITMAP
128 void OnQuit( wxCommandEvent &event );
129
130 #if wxUSE_CLIPBOARD
131 void OnCopy(wxCommandEvent& event);
132 void OnPaste(wxCommandEvent& event);
133 #endif // wxUSE_CLIPBOARD
134
135 MyCanvas *m_canvas;
136
137 private:
138 // ask user for the file name and try to load an image from it
139 //
140 // return the file path on success, empty string if we failed to load the
141 // image or were cancelled by user
142 static wxString LoadUserImage(wxImage& image);
143
144
145 DECLARE_DYNAMIC_CLASS(MyFrame)
146 DECLARE_EVENT_TABLE()
147 };
148
149 // ----------------------------------------------------------------------------
150 // Frame used for showing a standalone image
151 // ----------------------------------------------------------------------------
152
153 enum
154 {
155 ID_ROTATE_LEFT = wxID_HIGHEST+1,
156 ID_ROTATE_RIGHT,
157 ID_RESIZE,
158 ID_PAINT_BG
159 };
160
161 class MyImageFrame : public wxFrame
162 {
163 public:
164 MyImageFrame(wxFrame *parent, const wxString& desc, const wxBitmap& bitmap)
165 : wxFrame(parent, wxID_ANY,
166 wxString::Format(_T("Image from %s"), desc.c_str()),
167 wxDefaultPosition, wxDefaultSize,
168 wxDEFAULT_FRAME_STYLE | wxFULL_REPAINT_ON_RESIZE),
169 m_bitmap(bitmap)
170 {
171 wxMenu *menu = new wxMenu;
172 menu->Append(wxID_SAVE);
173 menu->AppendSeparator();
174 m_pClearBgMenu = menu->AppendCheckItem(ID_PAINT_BG, _T("&Paint background"));
175 menu->AppendSeparator();
176 menu->Append(ID_RESIZE, _T("&Fit to window\tCtrl-F"));
177 menu->AppendSeparator();
178 menu->Append(ID_ROTATE_LEFT, _T("Rotate &left\tCtrl-L"));
179 menu->Append(ID_ROTATE_RIGHT, _T("Rotate &right\tCtrl-R"));
180
181 wxMenuBar *mbar = new wxMenuBar;
182 mbar->Append(menu, _T("&Image"));
183 SetMenuBar(mbar);
184
185 CreateStatusBar();
186
187 SetClientSize(bitmap.GetWidth(), bitmap.GetHeight());
188
189 UpdateStatusBar();
190
191 // SetBackgroundColour(*wxWHITE);
192 }
193
194 void OnEraseBackground(wxEraseEvent& WXUNUSED(event))
195 {
196 // do nothing here to be able to see how transparent images are shown
197 }
198
199 void OnPaint(wxPaintEvent& WXUNUSED(event))
200 {
201 wxPaintDC dc(this);
202
203 if (m_pClearBgMenu->IsChecked())
204 ClearBackground();
205
206 const wxSize size = GetClientSize();
207 dc.DrawBitmap(m_bitmap,
208 (size.x - m_bitmap.GetWidth())/2,
209 (size.y - m_bitmap.GetHeight())/2,
210 true /* use mask */);
211 }
212
213 void OnSave(wxCommandEvent& WXUNUSED(event))
214 {
215 #if wxUSE_FILEDLG
216 wxImage image = m_bitmap.ConvertToImage();
217
218 wxString savefilename = wxFileSelector( wxT("Save Image"),
219 wxEmptyString,
220 wxEmptyString,
221 (const wxChar *)NULL,
222 wxT("BMP files (*.bmp)|*.bmp|")
223 wxT("PNG files (*.png)|*.png|")
224 wxT("JPEG files (*.jpg)|*.jpg|")
225 wxT("GIF files (*.gif)|*.gif|")
226 wxT("TIFF files (*.tif)|*.tif|")
227 wxT("PCX files (*.pcx)|*.pcx|")
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 == _T("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 _T("1 bpp color"),
257 _T("1 bpp B&W"),
258 _T("4 bpp color"),
259 _T("8 bpp color"),
260 _T("8 bpp greyscale"),
261 _T("8 bpp red"),
262 _T("8 bpp own palette"),
263 _T("24 bpp")
264 };
265
266 int bppselection = wxGetSingleChoiceIndex(_T("Set BMP BPP"),
267 _T("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 else if ( extension == _T("png") )
288 {
289 static const int pngvalues[] =
290 {
291 wxPNG_TYPE_COLOUR,
292 wxPNG_TYPE_COLOUR,
293 wxPNG_TYPE_GREY,
294 wxPNG_TYPE_GREY,
295 wxPNG_TYPE_GREY_RED,
296 wxPNG_TYPE_GREY_RED,
297 };
298
299 const wxString pngchoices[] =
300 {
301 _T("Colour 8bpp"),
302 _T("Colour 16bpp"),
303 _T("Grey 8bpp"),
304 _T("Grey 16bpp"),
305 _T("Grey red 8bpp"),
306 _T("Grey red 16bpp"),
307 };
308
309 int sel = wxGetSingleChoiceIndex(_T("Set PNG format"),
310 _T("Image sample: save file"),
311 WXSIZEOF(pngchoices),
312 pngchoices,
313 this);
314 if ( sel != -1 )
315 {
316 image.SetOption(wxIMAGE_OPTION_PNG_FORMAT, pngvalues[sel]);
317 image.SetOption(wxIMAGE_OPTION_PNG_BITDEPTH, sel % 2 ? 16 : 8);
318 }
319 }
320 else if ( extension == _T("cur") )
321 {
322 image.Rescale(32,32);
323 image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, 0);
324 image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, 0);
325 // This shows how you can save an image with explicitly
326 // specified image format:
327 saved = image.SaveFile(savefilename, wxBITMAP_TYPE_CUR);
328 }
329
330 if ( !saved )
331 {
332 // This one guesses image format from filename extension
333 // (it may fail if the extension is not recognized):
334 image.SaveFile(savefilename);
335 }
336 #endif // wxUSE_FILEDLG
337 }
338
339 void OnResize(wxCommandEvent& WXUNUSED(event))
340 {
341 wxImage img(m_bitmap.ConvertToImage());
342
343 const wxSize size = GetClientSize();
344 img.Rescale(size.x, size.y, wxIMAGE_QUALITY_HIGH);
345 m_bitmap = wxBitmap(img);
346
347 UpdateStatusBar();
348 Refresh();
349 }
350
351 void OnRotate(wxCommandEvent& event)
352 {
353 double angle = 5;
354 if ( event.GetId() == ID_ROTATE_LEFT )
355 angle = -angle;
356
357 wxImage img(m_bitmap.ConvertToImage());
358 img = img.Rotate(angle, wxPoint(img.GetWidth() / 2, img.GetHeight() / 2));
359 if ( !img.Ok() )
360 {
361 wxLogWarning(_T("Rotation failed"));
362 return;
363 }
364
365 m_bitmap = wxBitmap(img);
366
367 UpdateStatusBar();
368 Refresh();
369 }
370
371 private:
372 void UpdateStatusBar()
373 {
374 wxLogStatus(this, _T("Image size: (%d, %d)"),
375 m_bitmap.GetWidth(),
376 m_bitmap.GetHeight());
377 }
378
379 wxBitmap m_bitmap;
380 wxMenuItem* m_pClearBgMenu;
381
382 DECLARE_EVENT_TABLE()
383 };
384
385 #ifdef wxHAVE_RAW_BITMAP
386
387 #include "wx/rawbmp.h"
388
389 class MyRawBitmapFrame : public wxFrame
390 {
391 public:
392 enum
393 {
394 BORDER = 15,
395 SIZE = 150,
396 REAL_SIZE = SIZE - 2*BORDER
397 };
398
399 MyRawBitmapFrame(wxFrame *parent)
400 : wxFrame(parent, wxID_ANY, _T("Raw bitmaps (how exciting)")),
401 m_bitmap(SIZE, SIZE, 24),
402 m_alphaBitmap(SIZE, SIZE, 32)
403 {
404 SetClientSize(SIZE, SIZE*2+25);
405
406 InitAlphaBitmap();
407 InitBitmap();
408
409 }
410
411 void InitAlphaBitmap()
412 {
413 // First, clear the whole bitmap by making it alpha
414 {
415 wxAlphaPixelData data( m_alphaBitmap, wxPoint(0,0), wxSize(SIZE, SIZE) );
416 if ( !data )
417 {
418 wxLogError(_T("Failed to gain raw access to bitmap data"));
419 return;
420 }
421 wxAlphaPixelData::Iterator p(data);
422 for ( int y = 0; y < SIZE; ++y )
423 {
424 wxAlphaPixelData::Iterator rowStart = p;
425 for ( int x = 0; x < SIZE; ++x )
426 {
427 p.Alpha() = 0;
428 ++p; // same as p.OffsetX(1)
429 }
430 p = rowStart;
431 p.OffsetY(data, 1);
432 }
433 }
434
435 // Then, draw colourful alpha-blended stripes
436 wxAlphaPixelData data(m_alphaBitmap, wxPoint(BORDER, BORDER),
437 wxSize(REAL_SIZE, REAL_SIZE));
438 if ( !data )
439 {
440 wxLogError(_T("Failed to gain raw access to bitmap data"));
441 return;
442 }
443
444 wxAlphaPixelData::Iterator p(data);
445
446 for ( int y = 0; y < REAL_SIZE; ++y )
447 {
448 wxAlphaPixelData::Iterator rowStart = p;
449
450 int r = y < REAL_SIZE/3 ? 255 : 0,
451 g = (REAL_SIZE/3 <= y) && (y < 2*(REAL_SIZE/3)) ? 255 : 0,
452 b = 2*(REAL_SIZE/3) <= y ? 255 : 0;
453
454 for ( int x = 0; x < REAL_SIZE; ++x )
455 {
456 // note that RGB must be premultiplied by alpha
457 unsigned a = (wxAlphaPixelData::Iterator::ChannelType)((x*255.)/REAL_SIZE);
458 p.Red() = r * a / 256;
459 p.Green() = g * a / 256;
460 p.Blue() = b * a / 256;
461 p.Alpha() = a;
462
463 ++p; // same as p.OffsetX(1)
464 }
465
466 p = rowStart;
467 p.OffsetY(data, 1);
468 }
469 }
470
471 void InitBitmap()
472 {
473 // draw some colourful stripes without alpha
474 wxNativePixelData data(m_bitmap);
475 if ( !data )
476 {
477 wxLogError(_T("Failed to gain raw access to bitmap data"));
478 return;
479 }
480
481 wxNativePixelData::Iterator p(data);
482 for ( int y = 0; y < SIZE; ++y )
483 {
484 wxNativePixelData::Iterator rowStart = p;
485
486 int r = y < SIZE/3 ? 255 : 0,
487 g = (SIZE/3 <= y) && (y < 2*(SIZE/3)) ? 255 : 0,
488 b = 2*(SIZE/3) <= y ? 255 : 0;
489
490 for ( int x = 0; x < SIZE; ++x )
491 {
492 p.Red() = r;
493 p.Green() = g;
494 p.Blue() = b;
495 ++p; // same as p.OffsetX(1)
496 }
497
498 p = rowStart;
499 p.OffsetY(data, 1);
500 }
501 }
502
503 void OnPaint(wxPaintEvent& WXUNUSED(event))
504 {
505 wxPaintDC dc( this );
506 dc.DrawText(_T("This is alpha and raw bitmap test"), 0, BORDER);
507 dc.DrawText(_T("This is alpha and raw bitmap test"), 0, SIZE/2 - BORDER);
508 dc.DrawText(_T("This is alpha and raw bitmap test"), 0, SIZE - 2*BORDER);
509 dc.DrawBitmap( m_alphaBitmap, 0, 0, true /* use mask */ );
510
511 dc.DrawText(_T("Raw bitmap access without alpha"), 0, SIZE+5);
512 dc.DrawBitmap( m_bitmap, 0, SIZE+5+dc.GetCharHeight());
513 }
514
515 private:
516 wxBitmap m_bitmap;
517 wxBitmap m_alphaBitmap;
518
519 DECLARE_EVENT_TABLE()
520 };
521
522 #endif // wxHAVE_RAW_BITMAP
523
524 // MyApp
525
526 class MyApp: public wxApp
527 {
528 public:
529 virtual bool OnInit();
530 };
531
532 // main program
533
534 IMPLEMENT_APP(MyApp)
535
536 // MyCanvas
537
538 BEGIN_EVENT_TABLE(MyImageFrame, wxFrame)
539 EVT_ERASE_BACKGROUND(MyImageFrame::OnEraseBackground)
540 EVT_PAINT(MyImageFrame::OnPaint)
541
542 EVT_MENU(wxID_SAVE, MyImageFrame::OnSave)
543 EVT_MENU_RANGE(ID_ROTATE_LEFT, ID_ROTATE_RIGHT, MyImageFrame::OnRotate)
544 EVT_MENU(ID_RESIZE, MyImageFrame::OnResize)
545 END_EVENT_TABLE()
546
547 #ifdef wxHAVE_RAW_BITMAP
548
549 BEGIN_EVENT_TABLE(MyRawBitmapFrame, wxFrame)
550 EVT_PAINT(MyRawBitmapFrame::OnPaint)
551 END_EVENT_TABLE()
552
553 #endif // wxHAVE_RAW_BITMAP
554
555 BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
556 EVT_PAINT(MyCanvas::OnPaint)
557 END_EVENT_TABLE()
558
559 MyCanvas::MyCanvas( wxWindow *parent, wxWindowID id,
560 const wxPoint &pos, const wxSize &size )
561 : wxScrolledWindow( parent, id, pos, size, wxSUNKEN_BORDER )
562 , m_bmpSmileXpm(smile_xpm)
563 , m_iconSmileXpm(smile_xpm)
564 {
565 my_horse_ani = NULL;
566 m_ani_images = 0 ;
567
568 SetBackgroundColour(* wxWHITE);
569
570 wxBitmap bitmap( 100, 100 );
571
572 wxMemoryDC dc;
573 dc.SelectObject( bitmap );
574 dc.SetBrush( wxBrush( wxT("orange"), wxSOLID ) );
575 dc.SetPen( *wxBLACK_PEN );
576 dc.DrawRectangle( 0, 0, 100, 100 );
577 dc.SetBrush( *wxWHITE_BRUSH );
578 dc.DrawRectangle( 20, 20, 60, 60 );
579 dc.SelectObject( wxNullBitmap );
580
581 // try to find the directory with our images
582 wxString dir;
583 if ( wxFile::Exists(wxT("./horse.png")) )
584 dir = wxT("./");
585 else if ( wxFile::Exists(wxT("../horse.png")) )
586 dir = wxT("../");
587 else
588 wxLogWarning(wxT("Can't find image files in either '.' or '..'!"));
589
590 wxImage image = bitmap.ConvertToImage();
591
592 #if wxUSE_LIBPNG
593 if ( !image.SaveFile( dir + _T("test.png"), wxBITMAP_TYPE_PNG ))
594 wxLogError(wxT("Can't save file"));
595
596 image.Destroy();
597
598 if ( image.LoadFile( dir + _T("test.png") ) )
599 my_square = wxBitmap( image );
600
601 image.Destroy();
602
603 if ( !image.LoadFile( dir + _T("horse.png")) )
604 wxLogError(wxT("Can't load PNG image"));
605 else
606 my_horse_png = wxBitmap( image );
607
608 if ( !image.LoadFile( dir + _T("toucan.png")) )
609 wxLogError(wxT("Can't load PNG image"));
610 else
611 my_toucan = wxBitmap(image);
612
613 my_toucan_flipped_horiz = wxBitmap(image.Mirror(true));
614 my_toucan_flipped_vert = wxBitmap(image.Mirror(false));
615 my_toucan_flipped_both = wxBitmap(image.Mirror(true).Mirror(false));
616 my_toucan_grey = wxBitmap(image.ConvertToGreyscale());
617 my_toucan_head = wxBitmap(image.GetSubImage(wxRect(40, 7, 80, 60)));
618 my_toucan_scaled_normal = wxBitmap(image.Scale(110,90,wxIMAGE_QUALITY_NORMAL));
619 my_toucan_scaled_high = wxBitmap(image.Scale(110,90,wxIMAGE_QUALITY_HIGH));
620 my_toucan_blur = wxBitmap(image.Blur(10));
621
622 #endif // wxUSE_LIBPNG
623
624 #if wxUSE_LIBJPEG
625 image.Destroy();
626
627 if ( !image.LoadFile( dir + _T("horse.jpg")) )
628 wxLogError(wxT("Can't load JPG image"));
629 else
630 {
631 my_horse_jpeg = wxBitmap( image );
632
633 // Colorize by rotating green hue to red
634 wxImage::HSVValue greenHSV = wxImage::RGBtoHSV(wxImage::RGBValue(0, 255, 0));
635 wxImage::HSVValue redHSV = wxImage::RGBtoHSV(wxImage::RGBValue(255, 0, 0));
636 image.RotateHue(redHSV.hue - greenHSV.hue);
637 colorized_horse_jpeg = wxBitmap( image );
638 }
639
640 if ( !image.LoadFile( dir + _T("cmyk.jpg")) )
641 wxLogError(_T("Can't load CMYK JPG image"));
642 else
643 my_cmyk_jpeg = wxBitmap(image);
644 #endif // wxUSE_LIBJPEG
645
646 #if wxUSE_GIF
647 image.Destroy();
648
649 if ( !image.LoadFile( dir + _T("horse.gif" )) )
650 wxLogError(wxT("Can't load GIF image"));
651 else
652 my_horse_gif = wxBitmap( image );
653 #endif
654
655 #if wxUSE_PCX
656 image.Destroy();
657
658 if ( !image.LoadFile( dir + _T("horse.pcx"), wxBITMAP_TYPE_PCX ) )
659 wxLogError(wxT("Can't load PCX image"));
660 else
661 my_horse_pcx = wxBitmap( image );
662 #endif
663
664 image.Destroy();
665
666 if ( !image.LoadFile( dir + _T("horse.bmp"), wxBITMAP_TYPE_BMP ) )
667 wxLogError(wxT("Can't load BMP image"));
668 else
669 my_horse_bmp = wxBitmap( image );
670
671 #if wxUSE_XPM
672 image.Destroy();
673
674 if ( !image.LoadFile( dir + _T("horse.xpm"), wxBITMAP_TYPE_XPM ) )
675 wxLogError(wxT("Can't load XPM image"));
676 else
677 my_horse_xpm = wxBitmap( image );
678
679 if ( !image.SaveFile( dir + _T("test.xpm"), wxBITMAP_TYPE_XPM ))
680 wxLogError(wxT("Can't save file"));
681 #endif
682
683 #if wxUSE_PNM
684 image.Destroy();
685
686 if ( !image.LoadFile( dir + _T("horse.pnm"), wxBITMAP_TYPE_PNM ) )
687 wxLogError(wxT("Can't load PNM image"));
688 else
689 my_horse_pnm = wxBitmap( image );
690
691 image.Destroy();
692
693 if ( !image.LoadFile( dir + _T("horse_ag.pnm"), wxBITMAP_TYPE_PNM ) )
694 wxLogError(wxT("Can't load PNM image"));
695 else
696 my_horse_asciigrey_pnm = wxBitmap( image );
697
698 image.Destroy();
699
700 if ( !image.LoadFile( dir + _T("horse_rg.pnm"), wxBITMAP_TYPE_PNM ) )
701 wxLogError(wxT("Can't load PNM image"));
702 else
703 my_horse_rawgrey_pnm = wxBitmap( image );
704 #endif
705
706 #if wxUSE_LIBTIFF
707 image.Destroy();
708
709 if ( !image.LoadFile( dir + _T("horse.tif"), wxBITMAP_TYPE_TIF ) )
710 wxLogError(wxT("Can't load TIFF image"));
711 else
712 my_horse_tiff = wxBitmap( image );
713 #endif
714
715 #if wxUSE_LIBTIFF
716 image.Destroy();
717
718 if ( !image.LoadFile( dir + _T("horse.tga"), wxBITMAP_TYPE_TGA ) )
719 wxLogError(wxT("Can't load TGA image"));
720 else
721 my_horse_tga = wxBitmap( image );
722 #endif
723
724 CreateAntiAliasedBitmap();
725
726 my_smile_xbm = wxBitmap( (const char*)smile_bits, smile_width,
727 smile_height, 1 );
728
729 // demonstrates XPM automatically using the mask when saving
730 if ( m_bmpSmileXpm.Ok() )
731 m_bmpSmileXpm.SaveFile(_T("saved.xpm"), wxBITMAP_TYPE_XPM);
732
733 #if wxUSE_ICO_CUR
734 image.Destroy();
735
736 if ( !image.LoadFile( dir + _T("horse.ico"), wxBITMAP_TYPE_ICO, 0 ) )
737 wxLogError(wxT("Can't load first ICO image"));
738 else
739 my_horse_ico32 = wxBitmap( image );
740
741 image.Destroy();
742
743 if ( !image.LoadFile( dir + _T("horse.ico"), wxBITMAP_TYPE_ICO, 1 ) )
744 wxLogError(wxT("Can't load second ICO image"));
745 else
746 my_horse_ico16 = wxBitmap( image );
747
748 image.Destroy();
749
750 if ( !image.LoadFile( dir + _T("horse.ico") ) )
751 wxLogError(wxT("Can't load best ICO image"));
752 else
753 my_horse_ico = wxBitmap( image );
754
755 image.Destroy();
756
757 if ( !image.LoadFile( dir + _T("horse.cur"), wxBITMAP_TYPE_CUR ) )
758 wxLogError(wxT("Can't load best ICO image"));
759 else
760 {
761 my_horse_cur = wxBitmap( image );
762 xH = 30 + image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X) ;
763 yH = 2420 + image.GetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y) ;
764 }
765
766 m_ani_images = wxImage::GetImageCount ( dir + _T("horse3.ani"), wxBITMAP_TYPE_ANI );
767 if (m_ani_images==0)
768 wxLogError(wxT("No ANI-format images found"));
769 else
770 my_horse_ani = new wxBitmap [m_ani_images];
771 int i ;
772 for (i=0; i < m_ani_images; i++)
773 {
774 image.Destroy();
775 if (!image.LoadFile( dir + _T("horse3.ani"), wxBITMAP_TYPE_ANI, i ))
776 {
777 wxString tmp = wxT("Can't load image number ");
778 tmp << i ;
779 wxLogError(tmp);
780 }
781 else
782 my_horse_ani [i] = wxBitmap( image );
783 }
784 #endif // wxUSE_ICO_CUR
785
786 image.Destroy();
787
788 // test image loading from stream
789 wxFile file(dir + _T("horse.bmp"));
790 if ( file.IsOpened() )
791 {
792 wxFileOffset len = file.Length();
793 size_t dataSize = (size_t)len;
794 void *data = malloc(dataSize);
795 if ( file.Read(data, dataSize) != len )
796 wxLogError(_T("Reading bitmap file failed"));
797 else
798 {
799 wxMemoryInputStream mis(data, dataSize);
800 if ( !image.LoadFile(mis) )
801 wxLogError(wxT("Can't load BMP image from stream"));
802 else
803 my_horse_bmp2 = wxBitmap( image );
804 }
805
806 free(data);
807 }
808 }
809
810 MyCanvas::~MyCanvas()
811 {
812 delete [] my_horse_ani;
813 }
814
815 void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) )
816 {
817 wxPaintDC dc( this );
818 PrepareDC( dc );
819
820 dc.DrawText( _T("Loaded image"), 30, 10 );
821 if (my_square.Ok())
822 dc.DrawBitmap( my_square, 30, 30 );
823
824 dc.DrawText( _T("Drawn directly"), 150, 10 );
825 dc.SetBrush( wxBrush( wxT("orange"), wxSOLID ) );
826 dc.SetPen( *wxBLACK_PEN );
827 dc.DrawRectangle( 150, 30, 100, 100 );
828 dc.SetBrush( *wxWHITE_BRUSH );
829 dc.DrawRectangle( 170, 50, 60, 60 );
830
831 if (my_anti.Ok())
832 dc.DrawBitmap( my_anti, 280, 30 );
833
834 dc.DrawText( _T("PNG handler"), 30, 135 );
835 if (my_horse_png.Ok())
836 {
837 dc.DrawBitmap( my_horse_png, 30, 150 );
838 wxRect rect(0,0,100,100);
839 wxBitmap sub( my_horse_png.GetSubBitmap(rect) );
840 dc.DrawText( _T("GetSubBitmap()"), 280, 175 );
841 dc.DrawBitmap( sub, 280, 195 );
842 }
843
844 dc.DrawText( _T("JPEG handler"), 30, 365 );
845 if (my_horse_jpeg.Ok())
846 dc.DrawBitmap( my_horse_jpeg, 30, 380 );
847
848 dc.DrawText( _T("Green rotated to red"), 280, 365 );
849 if (colorized_horse_jpeg.Ok())
850 dc.DrawBitmap( colorized_horse_jpeg, 280, 380 );
851
852 dc.DrawText( _T("CMYK JPEG image"), 530, 365 );
853 if (my_cmyk_jpeg.Ok())
854 dc.DrawBitmap( my_cmyk_jpeg, 530, 380 );
855
856 dc.DrawText( _T("GIF handler"), 30, 595 );
857 if (my_horse_gif.Ok())
858 dc.DrawBitmap( my_horse_gif, 30, 610 );
859
860 dc.DrawText( _T("PCX handler"), 30, 825 );
861 if (my_horse_pcx.Ok())
862 dc.DrawBitmap( my_horse_pcx, 30, 840 );
863
864 dc.DrawText( _T("BMP handler"), 30, 1055 );
865 if (my_horse_bmp.Ok())
866 dc.DrawBitmap( my_horse_bmp, 30, 1070 );
867
868 dc.DrawText( _T("BMP read from memory"), 280, 1055 );
869 if (my_horse_bmp2.Ok())
870 dc.DrawBitmap( my_horse_bmp2, 280, 1070 );
871
872 dc.DrawText( _T("PNM handler"), 30, 1285 );
873 if (my_horse_pnm.Ok())
874 dc.DrawBitmap( my_horse_pnm, 30, 1300 );
875
876 dc.DrawText( _T("PNM handler (ascii grey)"), 280, 1285 );
877 if (my_horse_asciigrey_pnm.Ok())
878 dc.DrawBitmap( my_horse_asciigrey_pnm, 280, 1300 );
879
880 dc.DrawText( _T("PNM handler (raw grey)"), 530, 1285 );
881 if (my_horse_rawgrey_pnm.Ok())
882 dc.DrawBitmap( my_horse_rawgrey_pnm, 530, 1300 );
883
884 dc.DrawText( _T("TIFF handler"), 30, 1515 );
885 if (my_horse_tiff.Ok())
886 dc.DrawBitmap( my_horse_tiff, 30, 1530 );
887
888 dc.DrawText( _T("TGA handler"), 30, 1745 );
889 if (my_horse_tga.Ok())
890 dc.DrawBitmap( my_horse_tga, 30, 1760 );
891
892 dc.DrawText( _T("XPM handler"), 30, 1975 );
893 if (my_horse_xpm.Ok())
894 dc.DrawBitmap( my_horse_xpm, 30, 2000 );
895
896 // toucans
897 {
898 int x = 750, y = 10, yy = 170;
899
900 dc.DrawText(wxT("Original toucan"), x+50, y);
901 dc.DrawBitmap(my_toucan, x, y+15, true);
902 y += yy;
903 dc.DrawText(wxT("Flipped horizontally"), x+50, y);
904 dc.DrawBitmap(my_toucan_flipped_horiz, x, y+15, true);
905 y += yy;
906 dc.DrawText(wxT("Flipped vertically"), x+50, y);
907 dc.DrawBitmap(my_toucan_flipped_vert, x, y+15, true);
908 y += yy;
909 dc.DrawText(wxT("Flipped both h&v"), x+50, y);
910 dc.DrawBitmap(my_toucan_flipped_both, x, y+15, true);
911
912 y += yy;
913 dc.DrawText(wxT("In greyscale"), x+50, y);
914 dc.DrawBitmap(my_toucan_grey, x, y+15, true);
915
916 y += yy;
917 dc.DrawText(wxT("Toucan's head"), x+50, y);
918 dc.DrawBitmap(my_toucan_head, x, y+15, true);
919
920 y += yy;
921 dc.DrawText(wxT("Scaled with normal quality"), x+50, y);
922 dc.DrawBitmap(my_toucan_scaled_normal, x, y+15, true);
923
924 y += yy;
925 dc.DrawText(wxT("Scaled with high quality"), x+50, y);
926 dc.DrawBitmap(my_toucan_scaled_high, x, y+15, true);
927
928 y += yy;
929 dc.DrawText(wxT("Blured"), x+50, y);
930 dc.DrawBitmap(my_toucan_blur, x, y+15, true);
931 }
932
933 if (my_smile_xbm.Ok())
934 {
935 int x = 300, y = 1800;
936
937 dc.DrawText( _T("XBM bitmap"), x, y );
938 dc.DrawText( _T("(green on red)"), x, y + 15 );
939 dc.SetTextForeground( _T("GREEN") );
940 dc.SetTextBackground( _T("RED") );
941 dc.DrawBitmap( my_smile_xbm, x, y + 30 );
942
943 dc.SetTextForeground( *wxBLACK );
944 dc.DrawText( _T("After wxImage conversion"), x + 120, y );
945 dc.DrawText( _T("(red on white)"), x + 120, y + 15 );
946 dc.SetTextForeground( wxT("RED") );
947 wxImage i = my_smile_xbm.ConvertToImage();
948 i.SetMaskColour( 255, 255, 255 );
949 i.Replace( 0, 0, 0,
950 wxRED_PEN->GetColour().Red(),
951 wxRED_PEN->GetColour().Green(),
952 wxRED_PEN->GetColour().Blue() );
953 dc.DrawBitmap( wxBitmap(i), x + 120, y + 30, true );
954 dc.SetTextForeground( *wxBLACK );
955 }
956
957
958 wxBitmap mono( 60,50,1 );
959 wxMemoryDC memdc;
960 memdc.SelectObject( mono );
961 memdc.SetPen( *wxBLACK_PEN );
962 memdc.SetBrush( *wxWHITE_BRUSH );
963 memdc.DrawRectangle( 0,0,60,50 );
964 memdc.SetTextForeground( *wxBLACK );
965 #ifndef __WXGTK20__
966 // I cannot convince GTK2 to draw into mono bitmaps
967 memdc.DrawText( _T("Hi!"), 5, 5 );
968 #endif
969 memdc.SetBrush( *wxBLACK_BRUSH );
970 memdc.DrawRectangle( 33,5,20,20 );
971 memdc.SetPen( *wxRED_PEN );
972 memdc.DrawLine( 5, 42, 50, 42 );
973 memdc.SelectObject( wxNullBitmap );
974
975 if (mono.Ok())
976 {
977 int x = 300, y = 1900;
978
979 dc.DrawText( _T("Mono bitmap"), x, y );
980 dc.DrawText( _T("(red on green)"), x, y + 15 );
981 dc.SetTextForeground( wxT("RED") );
982 dc.SetTextBackground( wxT("GREEN") );
983 dc.DrawBitmap( mono, x, y + 30 );
984
985 dc.SetTextForeground( *wxBLACK );
986 dc.DrawText( _T("After wxImage conversion"), x + 120, y );
987 dc.DrawText( _T("(red on white)"), x + 120, y + 15 );
988 dc.SetTextForeground( wxT("RED") );
989 wxImage i = mono.ConvertToImage();
990 i.SetMaskColour( 255,255,255 );
991 i.Replace( 0,0,0,
992 wxRED_PEN->GetColour().Red(),
993 wxRED_PEN->GetColour().Green(),
994 wxRED_PEN->GetColour().Blue() );
995 dc.DrawBitmap( wxBitmap(i), x + 120, y + 30, true );
996 dc.SetTextForeground( *wxBLACK );
997 }
998
999 // For testing transparency
1000 dc.SetBrush( *wxRED_BRUSH );
1001 dc.DrawRectangle( 20, 2220, 560, 68 );
1002
1003 dc.DrawText(_T("XPM bitmap"), 30, 2230 );
1004 if ( m_bmpSmileXpm.Ok() )
1005 dc.DrawBitmap(m_bmpSmileXpm, 30, 2250, true);
1006
1007 dc.DrawText(_T("XPM icon"), 110, 2230 );
1008 if ( m_iconSmileXpm.Ok() )
1009 dc.DrawIcon(m_iconSmileXpm, 110, 2250);
1010
1011 // testing icon -> bitmap conversion
1012 wxBitmap to_blit( m_iconSmileXpm );
1013 if (to_blit.Ok())
1014 {
1015 dc.DrawText( _T("SubBitmap"), 170, 2230 );
1016 wxBitmap sub = to_blit.GetSubBitmap( wxRect(0,0,15,15) );
1017 if (sub.Ok())
1018 dc.DrawBitmap( sub, 170, 2250, true );
1019
1020 dc.DrawText( _T("Enlarged"), 250, 2230 );
1021 dc.SetUserScale( 1.5, 1.5 );
1022 dc.DrawBitmap( to_blit, (int)(250/1.5), (int)(2250/1.5), true );
1023 dc.SetUserScale( 2, 2 );
1024 dc.DrawBitmap( to_blit, (int)(300/2), (int)(2250/2), true );
1025 dc.SetUserScale( 1.0, 1.0 );
1026
1027 dc.DrawText( _T("Blit"), 400, 2230);
1028 wxMemoryDC blit_dc;
1029 blit_dc.SelectObject( to_blit );
1030 dc.Blit( 400, 2250, to_blit.GetWidth(), to_blit.GetHeight(), &blit_dc, 0, 0, wxCOPY, true );
1031 dc.SetUserScale( 1.5, 1.5 );
1032 dc.Blit( (int)(450/1.5), (int)(2250/1.5), to_blit.GetWidth(), to_blit.GetHeight(), &blit_dc, 0, 0, wxCOPY, true );
1033 dc.SetUserScale( 2, 2 );
1034 dc.Blit( (int)(500/2), (int)(2250/2), to_blit.GetWidth(), to_blit.GetHeight(), &blit_dc, 0, 0, wxCOPY, true );
1035 dc.SetUserScale( 1.0, 1.0 );
1036 }
1037
1038 dc.DrawText( _T("ICO handler (1st image)"), 30, 2290 );
1039 if (my_horse_ico32.Ok())
1040 dc.DrawBitmap( my_horse_ico32, 30, 2330, true );
1041
1042 dc.DrawText( _T("ICO handler (2nd image)"), 230, 2290 );
1043 if (my_horse_ico16.Ok())
1044 dc.DrawBitmap( my_horse_ico16, 230, 2330, true );
1045
1046 dc.DrawText( _T("ICO handler (best image)"), 430, 2290 );
1047 if (my_horse_ico.Ok())
1048 dc.DrawBitmap( my_horse_ico, 430, 2330, true );
1049
1050 dc.DrawText( _T("CUR handler"), 30, 2390 );
1051 if (my_horse_cur.Ok())
1052 {
1053 dc.DrawBitmap( my_horse_cur, 30, 2420, true );
1054 dc.SetPen (*wxRED_PEN);
1055 dc.DrawLine (xH-10,yH,xH+10,yH);
1056 dc.DrawLine (xH,yH-10,xH,yH+10);
1057 }
1058
1059 dc.DrawText( _T("ANI handler"), 230, 2390 );
1060 for ( int i=0; i < m_ani_images; i++ )
1061 {
1062 if (my_horse_ani[i].Ok())
1063 {
1064 dc.DrawBitmap( my_horse_ani[i], 230 + i * 2 * my_horse_ani[i].GetWidth() , 2420, true );
1065 }
1066 }
1067 }
1068
1069 void MyCanvas::CreateAntiAliasedBitmap()
1070 {
1071 wxBitmap bitmap( 300, 300 );
1072
1073 wxMemoryDC dc;
1074
1075 dc.SelectObject( bitmap );
1076
1077 dc.Clear();
1078
1079 dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL) );
1080 dc.SetTextForeground( wxT("RED") );
1081 dc.DrawText( _T("This is anti-aliased Text."), 20, 5 );
1082 dc.DrawText( _T("And a Rectangle."), 20, 45 );
1083
1084 dc.SetBrush( *wxRED_BRUSH );
1085 dc.SetPen( *wxTRANSPARENT_PEN );
1086 dc.DrawRoundedRectangle( 20, 85, 200, 180, 20 );
1087
1088 wxImage original= bitmap.ConvertToImage();
1089 wxImage anti( 150, 150 );
1090
1091 /* This is quite slow, but safe. Use wxImage::GetData() for speed instead. */
1092
1093 for (int y = 1; y < 149; y++)
1094 for (int x = 1; x < 149; x++)
1095 {
1096 int red = original.GetRed( x*2, y*2 ) +
1097 original.GetRed( x*2-1, y*2 ) +
1098 original.GetRed( x*2, y*2+1 ) +
1099 original.GetRed( x*2+1, y*2+1 );
1100 red = red/4;
1101
1102 int green = original.GetGreen( x*2, y*2 ) +
1103 original.GetGreen( x*2-1, y*2 ) +
1104 original.GetGreen( x*2, y*2+1 ) +
1105 original.GetGreen( x*2+1, y*2+1 );
1106 green = green/4;
1107
1108 int blue = original.GetBlue( x*2, y*2 ) +
1109 original.GetBlue( x*2-1, y*2 ) +
1110 original.GetBlue( x*2, y*2+1 ) +
1111 original.GetBlue( x*2+1, y*2+1 );
1112 blue = blue/4;
1113 anti.SetRGB( x, y, (unsigned char)red, (unsigned char)green, (unsigned char)blue );
1114 }
1115 my_anti = wxBitmap(anti);
1116 }
1117
1118 // MyFrame
1119
1120 enum
1121 {
1122 ID_QUIT = wxID_EXIT,
1123 ID_ABOUT = wxID_ABOUT,
1124 ID_NEW = 100,
1125 ID_INFO,
1126 ID_SHOWRAW,
1127 ID_SHOWTHUMBNAIL
1128 };
1129
1130 IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
1131
1132 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
1133 EVT_MENU (ID_ABOUT, MyFrame::OnAbout)
1134 EVT_MENU (ID_QUIT, MyFrame::OnQuit)
1135 EVT_MENU (ID_NEW, MyFrame::OnNewFrame)
1136 EVT_MENU (ID_INFO, MyFrame::OnImageInfo)
1137 EVT_MENU (ID_SHOWTHUMBNAIL, MyFrame::OnThumbnail)
1138 #ifdef wxHAVE_RAW_BITMAP
1139 EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap)
1140 #endif
1141
1142 #if wxUSE_CLIPBOARD
1143 EVT_MENU(wxID_COPY, MyFrame::OnCopy)
1144 EVT_MENU(wxID_PASTE, MyFrame::OnPaste)
1145 #endif // wxUSE_CLIPBOARD
1146 END_EVENT_TABLE()
1147
1148 MyFrame::MyFrame()
1149 : wxFrame( (wxFrame *)NULL, wxID_ANY, _T("wxImage sample"),
1150 wxPoint(20, 20), wxSize(950, 700) )
1151 {
1152 wxMenuBar *menu_bar = new wxMenuBar();
1153
1154 wxMenu *menuImage = new wxMenu;
1155 menuImage->Append( ID_NEW, _T("&Show any image...\tCtrl-O"));
1156 menuImage->Append( ID_INFO, _T("Show image &information...\tCtrl-I"));
1157 #ifdef wxHAVE_RAW_BITMAP
1158 menuImage->AppendSeparator();
1159 menuImage->Append( ID_SHOWRAW, _T("Test &raw bitmap...\tCtrl-R"));
1160 #endif
1161 menuImage->AppendSeparator();
1162 menuImage->Append( ID_SHOWTHUMBNAIL, _T("Test &thumbnail...\tCtrl-T"),
1163 "Test scaling the image during load (try with JPEG)");
1164 menuImage->AppendSeparator();
1165 menuImage->Append( ID_ABOUT, _T("&About..."));
1166 menuImage->AppendSeparator();
1167 menuImage->Append( ID_QUIT, _T("E&xit\tCtrl-Q"));
1168 menu_bar->Append(menuImage, _T("&Image"));
1169
1170 #if wxUSE_CLIPBOARD
1171 wxMenu *menuClipboard = new wxMenu;
1172 menuClipboard->Append(wxID_COPY, _T("&Copy test image\tCtrl-C"));
1173 menuClipboard->Append(wxID_PASTE, _T("&Paste image\tCtrl-V"));
1174 menu_bar->Append(menuClipboard, _T("&Clipboard"));
1175 #endif // wxUSE_CLIPBOARD
1176
1177 SetMenuBar( menu_bar );
1178
1179 #if wxUSE_STATUSBAR
1180 CreateStatusBar(2);
1181 int widths[] = { -1, 100 };
1182 SetStatusWidths( 2, widths );
1183 #endif // wxUSE_STATUSBAR
1184
1185 m_canvas = new MyCanvas( this, wxID_ANY, wxPoint(0,0), wxSize(10,10) );
1186
1187 // 500 width * 2750 height
1188 m_canvas->SetScrollbars( 10, 10, 50, 275 );
1189 }
1190
1191 void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) )
1192 {
1193 Close( true );
1194 }
1195
1196 void MyFrame::OnAbout( wxCommandEvent &WXUNUSED(event) )
1197 {
1198 (void)wxMessageBox( _T("wxImage demo\n")
1199 _T("Robert Roebling (c) 1998,2000"),
1200 _T("About wxImage Demo"), wxICON_INFORMATION | wxOK );
1201 }
1202
1203 wxString MyFrame::LoadUserImage(wxImage& image)
1204 {
1205 wxString filename;
1206
1207 #if wxUSE_FILEDLG
1208 filename = wxFileSelector(_T("Select image file"));
1209 if ( !filename.empty() )
1210 {
1211 if ( !image.LoadFile(filename) )
1212 {
1213 wxLogError(_T("Couldn't load image from '%s'."), filename.c_str());
1214
1215 return wxEmptyString;
1216 }
1217 }
1218 #endif // wxUSE_FILEDLG
1219
1220 return filename;
1221 }
1222
1223 void MyFrame::OnNewFrame( wxCommandEvent &WXUNUSED(event) )
1224 {
1225 wxImage image;
1226 wxString filename = LoadUserImage(image);
1227 if ( !filename.empty() )
1228 (new MyImageFrame(this, filename, wxBitmap(image)))->Show();
1229 }
1230
1231 void MyFrame::OnImageInfo( wxCommandEvent &WXUNUSED(event) )
1232 {
1233 wxImage image;
1234 if ( !LoadUserImage(image).empty() )
1235 {
1236 // TODO: show more information about the file
1237 wxString info = wxString::Format("Image size: %dx%d",
1238 image.GetWidth(),
1239 image.GetHeight());
1240
1241 int xres = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX),
1242 yres = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY);
1243 if ( xres || yres )
1244 {
1245 info += wxString::Format("\nResolution: %dx%d", xres, yres);
1246 switch ( image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONUNIT) )
1247 {
1248 default:
1249 wxFAIL_MSG( "unknown image resolution units" );
1250 // fall through
1251
1252 case wxIMAGE_RESOLUTION_NONE:
1253 info += " in default units";
1254 break;
1255
1256 case wxIMAGE_RESOLUTION_INCHES:
1257 info += " in";
1258 break;
1259
1260 case wxIMAGE_RESOLUTION_CM:
1261 info += " cm";
1262 break;
1263 }
1264 }
1265
1266 wxLogMessage("%s", info);
1267 }
1268 }
1269
1270 #ifdef wxHAVE_RAW_BITMAP
1271
1272 void MyFrame::OnTestRawBitmap( wxCommandEvent &WXUNUSED(event) )
1273 {
1274 (new MyRawBitmapFrame(this))->Show();
1275 }
1276
1277 #endif // wxHAVE_RAW_BITMAP
1278
1279 #if wxUSE_CLIPBOARD
1280
1281 void MyFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
1282 {
1283 wxBitmapDataObject *dobjBmp = new wxBitmapDataObject;
1284 dobjBmp->SetBitmap(m_canvas->my_horse_png);
1285
1286 wxTheClipboard->Open();
1287
1288 if ( !wxTheClipboard->SetData(dobjBmp) )
1289 {
1290 wxLogError(_T("Failed to copy bitmap to clipboard"));
1291 }
1292
1293 wxTheClipboard->Close();
1294 }
1295
1296 void MyFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
1297 {
1298 wxBitmapDataObject dobjBmp;
1299
1300 wxTheClipboard->Open();
1301 if ( !wxTheClipboard->GetData(dobjBmp) )
1302 {
1303 wxLogMessage(_T("No bitmap data in the clipboard"));
1304 }
1305 else
1306 {
1307 (new MyImageFrame(this, _T("Clipboard"), dobjBmp.GetBitmap()))->Show();
1308 }
1309 wxTheClipboard->Close();
1310 }
1311
1312 #endif // wxUSE_CLIPBOARD
1313
1314 //-----------------------------------------------------------------------------
1315 // MyApp
1316 //-----------------------------------------------------------------------------
1317
1318 bool MyApp::OnInit()
1319 {
1320 if ( !wxApp::OnInit() )
1321 return false;
1322
1323 wxInitAllImageHandlers();
1324
1325 wxFrame *frame = new MyFrame();
1326 frame->Show( true );
1327
1328 return true;
1329 }
1330
1331 void MyFrame::OnThumbnail( wxCommandEvent &WXUNUSED(event) )
1332 {
1333 #if wxUSE_FILEDLG
1334 wxString filename = wxFileSelector(_T("Select image file"));
1335 if ( filename.empty() )
1336 return;
1337
1338 static const int THUMBNAIL_WIDTH = 320;
1339 static const int THUMBNAIL_HEIGHT = 240;
1340
1341 wxImage image;
1342 image.SetOption(wxIMAGE_OPTION_MAX_WIDTH, THUMBNAIL_WIDTH);
1343 image.SetOption(wxIMAGE_OPTION_MAX_HEIGHT, THUMBNAIL_HEIGHT);
1344
1345 wxStopWatch sw;
1346 if ( !image.LoadFile(filename) )
1347 {
1348 wxLogError(_T("Couldn't load image from '%s'."), filename.c_str());
1349 return;
1350 }
1351
1352 const long loadTime = sw.Time();
1353
1354 MyImageFrame * const
1355 frame = new MyImageFrame(this, filename, wxBitmap(image));
1356 frame->Show();
1357 wxLogStatus(frame, "Loaded \"%s\" in %ldms", filename, loadTime);
1358 #else
1359 wxLogError( _T("Couldn't create file selector dialog") );
1360 return;
1361 #endif // wxUSE_FILEDLG
1362 }
1363