ファイルから画像を読み込む方法。それから矩形で画像を切り出す方法。表示はwxWidgetsに出力している。
// https://docs.wxwidgets.org/3.0/overview_helloworld.html // プリプロセッサに以下二つを追加 // __WXMSW__ // WXUSINGDLL // サブシステムをWindowsに設定(WinMainで呼び出すので) // Windows (/SUBSYSTEM:WINDOWS) #ifndef WX_PRECOMP #include <wx/wx.h> #endif #include <wx/gdicmn.h> // wxPointに必要 #include <wx/frame.h> // wxFrameに必要 #pragma comment(lib,"skia.dll.lib") #include "skia/include/core/SkCanvas.h" #include "skia/include/core/SkBitmap.h" #include "skia/include/core/SkImage.h" // 画像読み込み #include "skia/include/core/SkStream.h" #include "skia/include/codec/SkCodec.h" ///////////////////////////////////// ///////////////////////////////////// ///////////////////////////////////// #include <string> void getPixelRGB(std::vector<std::uint8_t>& rgb,const SkBitmap& bitmap) { if (!bitmap.readyToDraw()) { return; } if (bitmap.colorType() != kRGBA_8888_SkColorType && bitmap.colorType() != kBGRA_8888_SkColorType) { return; // Unsupported format } int Width = bitmap.width(); int Height = bitmap.height(); size_t rowBytes = bitmap.rowBytes(); const auto& info = bitmap.info(); int channels = info.bytesPerPixel(); std::uint8_t* pixels = (std::uint8_t*)bitmap.getPixels(); rgb.resize(Width * Height * 3); for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { size_t pos_ppm = (i * Width + j) * 3; size_t pos_sk = (i * rowBytes + j * channels); rgb[pos_ppm + 0] = pixels[pos_sk + 2]; rgb[pos_ppm + 1] = pixels[pos_sk + 1]; rgb[pos_ppm + 2] = pixels[pos_sk + 0]; } } } //////////////////////////////////////////////////////////////////
//! @brief 画像読み込み関数 //! @param path 画像ファイルのパス //! @param bitmap 読み込んだ画像を格納するビットマップ //! @return 読み込みに成功したらtrue bool LoadImageToBitmap(const std::string& path, SkBitmap* bitmap) { // ファイルからデータを読み込む
sk_sp<SkData> data = SkData::MakeFromFileName(path.c_str()); if (!data) { return false; // データの読み込みに失敗 } // データからSkCodecを作成 std::unique_ptr<SkCodec> codec(SkCodec::MakeFromData(data)); if (!codec) { return false; // コーデックの作成に失敗 } // ロード先のビットマップの情報を設定 SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); // ロード先のメモリ確保 if (!bitmap->tryAllocPixels(info)) { return false; // メモリ確保に失敗 } // ロード先へ画像をデコード SkCodec::Result ret = codec->getPixels( info, // 画像の情報 bitmap->getPixels(), // ロード先のメモリ bitmap->rowBytes() // ロード先の1行のバイト数 ); if (ret != SkCodec::kSuccess) { return false; // 画像のデコードに失敗 } return true; }
//////////////////////////////////////////////////////////////////
//! @brief 画像の一部を切り出す //! @param dst 切り出した画像を格納するビットマップ //! @param src 元画像 //! @param croprect 切り出す範囲 //! @return なし void CropImage(SkBitmap* dst, const SkBitmap& src, const SkIRect croprect) { sk_sp<SkImage> src_bmp_img = src.asImage();// SkBitmapをSkImageに変換 SkCanvas canv(src); dst->allocN32Pixels(croprect.width(), croprect.height());// 画像のメモリ確保 SkCanvas croppedCanvas(*dst);// 結果のSkBitmapからSkCanvas作成 SkIRect dstRect = SkIRect::MakeWH(croprect.width(), croprect.height());// 結果の書き込み範囲作成 SkSamplingOptions samplingOptions(SkFilterMode::kLinear); croppedCanvas.drawImageRect( src_bmp_img, // 元画像 SkRect::Make(croprect), // 切り取り範囲 SkRect::Make(dstRect), // 描画範囲 samplingOptions, // サンプリングオプション nullptr, SkCanvas::kStrict_SrcRectConstraint // 切り取り範囲を超えた描画を禁止 ); }
// ウィンドウ作成 class MyFrame : public wxFrame { SkBitmap _bmp; public: void PostCreate() {
// 画像をファイルから読み込む LoadImageToBitmap("test.png", &_bmp); Bind(wxEVT_PAINT, &MyFrame::OnPaint, this); this->Layout(); // レイアウトの更新 } MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) : wxFrame(NULL, wxID_ANY, title, pos, size) { // CallAfter : 現在処理中のイベントが終わったらPostCreateを実行 // コンストラクタはウィンドウ生成イベント扱い CallAfter(&MyFrame::PostCreate); } void OnPaint(wxPaintEvent& event) { // 切り出したい範囲をSkIRectで定義 SkIRect cropRect = SkIRect::MakeXYWH(300, 300, 400, 200); // 切り出した画像を格納する画像 SkBitmap croppedBitmap; // 切り出し処理 CropImage(&croppedBitmap, _bmp, cropRect); ////////////////////////////////////////// SkBitmap* dispbmp = &croppedBitmap; std::vector<std::uint8_t> rgb; getPixelRGB(rgb,*dispbmp); wxImage img(dispbmp->width(), dispbmp->height(), (unsigned char*)rgb.data(), true); wxBitmap wxbitmap(img); wxPaintDC dc(this); dc.DrawBitmap(wxbitmap, 0, 0, true); } private: }; ///////////////////////////////////// ///////////////////////////////////// ///////////////////////////////////// // wxWidgetsのアプリケーション作成 class MyApp : public wxApp { public: virtual bool OnInit() { MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340)); frame->Show(true); return true; } }; ///////////////////////////////////// ///////////////////////////////////// ///////////////////////////////////// // WinMainをマクロで定義 wxIMPLEMENT_APP(MyApp);