スポンサーリンク

skiaで画像ファイルの読み込みとクロッピング

ファイルから画像を読み込む方法。それから矩形で画像を切り出す方法。表示は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);

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: