Allow using wxImage::Scale() for zooming in image sample

By default, continue to use wxDC::SetUserScale(), but allow also using
wxImage::Scale() with various parameters to compare how the results look
like.
This commit is contained in:
Vadim Zeitlin
2022-02-22 02:26:06 +00:00
parent c227d10728
commit ce8bf736fa

View File

@@ -128,6 +128,11 @@ enum
ID_ROTATE_RIGHT,
ID_RESIZE,
ID_ZOOM_x2,
ID_ZOOM_DC,
ID_ZOOM_NEAREST,
ID_ZOOM_BILINEAR,
ID_ZOOM_BICUBIC,
ID_ZOOM_BOX_AVERAGE,
ID_PAINT_BG
};
@@ -190,6 +195,7 @@ private:
m_bitmap = bitmap;
m_zoom = 1.;
m_useImageForZoom = false;
wxMenu *menu = new wxMenu;
menu->Append(wxID_SAVEAS);
@@ -204,6 +210,12 @@ private:
menu->Append(wxID_ZOOM_100, "Reset zoom to &100%\tCtrl-1");
menu->Append(ID_ZOOM_x2, "Double zoom level\tCtrl-2");
menu->AppendSeparator();
menu->AppendRadioItem(ID_ZOOM_DC, "Use wx&DC for zoomin\tShift-Ctrl-D");
menu->AppendRadioItem(ID_ZOOM_NEAREST, "Use rescale nearest\tShift-Ctrl-N");
menu->AppendRadioItem(ID_ZOOM_BILINEAR, "Use rescale bilinear\tShift-Ctrl-L");
menu->AppendRadioItem(ID_ZOOM_BICUBIC, "Use rescale bicubic\tShift-Ctrl-C");
menu->AppendRadioItem(ID_ZOOM_BOX_AVERAGE, "Use rescale box average\tShift-Ctrl-B");
menu->AppendSeparator();
menu->Append(ID_ROTATE_LEFT, "Rotate &left\tCtrl-L");
menu->Append(ID_ROTATE_RIGHT, "Rotate &right\tCtrl-R");
@@ -237,14 +249,27 @@ private:
if ( GetMenuBar()->IsChecked(ID_PAINT_BG) )
dc.Clear();
dc.SetUserScale(m_zoom, m_zoom);
const int width = int(m_zoom * m_bitmap.GetWidth());
const int height = int(m_zoom * m_bitmap.GetHeight());
wxBitmap bitmap;
if ( m_useImageForZoom )
{
bitmap = m_bitmap.ConvertToImage().Scale(width, height,
m_resizeQuality);
}
else
{
dc.SetUserScale(m_zoom, m_zoom);
bitmap = m_bitmap;
}
const wxSize size = GetClientSize();
dc.DrawBitmap
(
m_bitmap,
dc.DeviceToLogicalX((size.x - int(m_zoom * m_bitmap.GetWidth())) / 2),
dc.DeviceToLogicalY((size.y - int(m_zoom * m_bitmap.GetHeight())) / 2),
bitmap,
dc.DeviceToLogicalX((size.x - width) / 2),
dc.DeviceToLogicalY((size.y - height) / 2),
true /* use mask */
);
}
@@ -471,6 +496,42 @@ private:
UpdateStatusBar();
}
void OnUseZoom(wxCommandEvent& event)
{
bool useImageForZoom = true;
switch ( event.GetId() )
{
case ID_ZOOM_DC:
useImageForZoom = false;
break;
case ID_ZOOM_NEAREST:
m_resizeQuality = wxIMAGE_QUALITY_NEAREST;
break;
case ID_ZOOM_BILINEAR:
m_resizeQuality = wxIMAGE_QUALITY_BILINEAR;
break;
case ID_ZOOM_BICUBIC:
m_resizeQuality = wxIMAGE_QUALITY_BICUBIC;
break;
case ID_ZOOM_BOX_AVERAGE:
m_resizeQuality = wxIMAGE_QUALITY_BOX_AVERAGE;
break;
default:
wxFAIL_MSG("unknown use for zoom command");
return;
}
m_useImageForZoom = useImageForZoom;
Refresh();
}
void OnRotate(wxCommandEvent& event)
{
double angle = 5;
@@ -537,6 +598,11 @@ private:
wxBitmap m_bitmap;
double m_zoom;
// If false, then wxDC is used for zooming. If true, then m_resizeQuality
// is used with wxImage::Scale() for zooming.
bool m_useImageForZoom;
wxImageResizeQuality m_resizeQuality;
wxDECLARE_EVENT_TABLE();
};
@@ -966,6 +1032,12 @@ wxBEGIN_EVENT_TABLE(MyImageFrame, wxFrame)
EVT_MENU(wxID_ZOOM_OUT, MyImageFrame::OnZoom)
EVT_MENU(wxID_ZOOM_100, MyImageFrame::OnZoom)
EVT_MENU(ID_ZOOM_x2, MyImageFrame::OnZoom)
EVT_MENU(ID_ZOOM_DC, MyImageFrame::OnUseZoom)
EVT_MENU(ID_ZOOM_NEAREST, MyImageFrame::OnUseZoom)
EVT_MENU(ID_ZOOM_BILINEAR, MyImageFrame::OnUseZoom)
EVT_MENU(ID_ZOOM_BICUBIC, MyImageFrame::OnUseZoom)
EVT_MENU(ID_ZOOM_BOX_AVERAGE, MyImageFrame::OnUseZoom)
wxEND_EVENT_TABLE()
//-----------------------------------------------------------------------------