image.cpp 29 KB

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