• ベストアンサー

ActionscriptのBitmapDataの描画速度

BitmapDataクラスを使って単色で塗りつぶしたのですが、 以下の二つの方法で試して速度を比較してみました。 1)各ピクセル毎にループさせて、setPixel(x, y, color)で各ピクセルを塗りつぶした。 2)fillRect(rect, color)で一気に塗りつぶした。 結果は、2)の方が断然速く処理しました。なぜ塗りの速度が全然違うのでしょうか?fillRectの中では何が行われているのでしょうか? ご教授願います。

  • Flash
  • 回答数2
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • atse
  • ベストアンサー率83% (36/43)
回答No.2

ループによるsetPixel()は、毎回そのピクセルのカラー情報を取得し、それにあわせて実際に塗られるカラーを毎回再計算します。 fillRect()は、おそらく最初にそのBitmapData自身が24bitか32bitかを判断するだけで、実際塗られるカラーの計算も最初の1回のみと思われます(24bitカラーによる塗り潰しの違いから推測、わかりやすく言うと上書き)。 もう一つは、setPixel()は実行するごとに毎回、つまりループで100回マスを塗ったとしたら100回、その関連するオブジェクトに「情報が変わったよ」と、教えます。 (一応AS3.0からはlock()/unlock()で制御できます) 以上がsetPixelが遅くなる大きな理由だと思われます。

rivertk
質問者

お礼

回答ありがとうございます。 よくわかりました。 ピクセル単位で操作する時は lock()/unlock()を使おうと思います。

その他の回答 (1)

  • BlurFiltan
  • ベストアンサー率91% (1611/1754)
回答No.1

Flash に限らず,普通はそうじゃないでしょうか? 1個ずつ,それもひっついているものをわざわざわけて操作するより, ひとまとめで操作した方が速いでしょう。 例えば「文書A(文字列A)」を「文書B」に貼り付けるとき, そのデータを,1文字ずつ 捜査してピックアップ するより, ~~~~~~~~~~~~~~~~~~~ 全部選択して貼り付ける方が速いです。 そうでない方が変だと思いますけどね。 それを不思議に思いだしたら, PCすべての機能が不思議に思えると思います。 (別に PC に限定する必要もありませんが。)

rivertk
質問者

お礼

回答ありがとうございます。 参考にさせていただきます。

関連するQ&A

  • 色描画

    以下は、ウインドウプロシージャ内でのプログラムです。 RGB( )ですが、0xFFは、255の事ですよね? x*0xFF/rect.rightこの計算式は、何を求めているんですか? 教えてください。 HDC         hdc; PAINTSTRUCT  ps; COLORREF    color; LONG        x,y; RECT        rect; switch(umsg){   case  WM_PAINT:       hdc =BeginPaint(hwnd,&ps);       GetClientRect(hwnd,&rect);       for(y=0;y<rect.bottom;y++){          for(x=0;x<rect.right;x++){            color=RGB(x*0xFF/rect.right,0,0);            SetPixel(hdc,x,y,color);          }       }

  • actionscript 3.0 初心者です

    現在bitmap処理について調べています。 以下の記述に置いて、ライブラリーにあるpng画像をbitmapで読み込みました。 この画像はswfファイルに埋め込み済みでクラスをtokyo1としています。 続いて、これを.draw()を使って画像に変化を起こそうとしましたが、 こちらはうまく行きませんでした。 どこかおかしいのでしょうか?お心当たりございましたら是非よろしくお願いします。 import flash.display.BitmapData; import flash.display.Bitmap; import flash.geom.Matrix; import flash.geom.ColorTransform; var rectX:Number=40; var rectY:Number=30; var rectwidth:Number=20; var rectheight:Number=20; var rect1:Rectangle=new Rectangle(rectX,rectY,rectwidth,rectheight); var btm_data:BitmapData=new tokyo1(); var btm_obj:Bitmap=new Bitmap(btm_data,PixelSnapping.AUTO,false); var matrix:Matrix=new Matrix(2,0,0,3,0,0); var color:ColorTransform=new ColorTransform(1,1,1,1,0,0,0,0); btm_data.draw(stage,matrix,color,BlendMode.NORMAL,rect1,true); addChild(btm_obj);

    • ベストアンサー
    • Flash
  • GDI+で高速な描画

    GDI+を利用してお絵かきツールのようなものを作成しようと思っています。 しかしdrawImage()での画面への描画が非常に遅いようで、描いてみると線がカクカクしてしまいます。 アンチエイリアスやアルファブレンドが必要なのでGDI+を利用したいのですが、どうにか高速に描画させる方法はないでしょうか? 下記は現在のソースの一部です。 static Bitmap *offscreenBitmap //描画処理はこっちに static Graphics *offscreen; static Graphics *onscreen; //画面表示用 static RECT rect; //クライアント領域 static POINTS posPts,pts; //一つ前と現在のマウス座標 static BOOL bLButtonDown; Pen nomalPen(Color(100,0,0,0), 1); //描画用ペン switch(msg){  case WM_CREATE:   GetClientRect(hWnd,&rect);   offscreenBitmap = new Bitmap(rect.right, rect.bottom); //ビットマップ生成   offscreen = new Graphics(offscreenBitmap);   offscreen->SetCompositingMode(Gdiplus::CompositingModeSourceOver);   offscreen->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);//アンチエイリアス有効化   offscreen->Clear(Color(255,255,255)); //初期化   onscreen = new Graphics(hWnd); //ウインドウ表示用   onscreen->SetCompositingMode(CompositingModeSourceCopy);   break;  case WM_LBTTONDOWN:   bLButtonDown = TRUE;   posPts=MAKEPOINTS(lp)   break;  case WM_MOVE:   pts=MAKEPOINTS(lp)   if(bLButtonDown){    offscreen->DrawLine(&nomalPen, posPts.x, posPts.y, pts.x, pts.y);//線描画    posPts.x=pts.x;    posPts.y=pts.y;   }   InvalidateRect(hWnd,&rect,0);//ウインドウを更新   break;  case WM_PAINT:   onscreen->DrawImage(offscreenBitmap,0,0);//画面に書き出し   break; }

  • LVGLで作った描画プログラムが動かない。

    現在、ESP32基板にili9488というTFT部品を接続して、タッチ操作ができる画面プログラムをLVGLライブラリで作成しています。 hello world表示や、ボタンを表示したりすることはLVGLライブラリを使用して動作することは確認できましたが、ボタンをタッチする操作ができないようで、反応がありません。 Chat gptで画面をなぞると線を描画してくれるようなプログラムを作ってもらったのですが、画面をなぞっても描画できません。 この場合、タッチ機能が停止してしまっていますでしょうか? LVGLでタッチ操作ではなにか特別な設定などが必要でしょうか? なお、TFT_eSPIライブラリのみで作成した画面タッチプログラムでは、タッチ操作は正常にできています。 どうぞ、ご教示の程よろしくお願い致します。 (プログラム内容) #include <Arduino.h> #include <lvgl.h> #include <TFT_eSPI.h> // ILI9488ドライバを含むライブラリ void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p); // ILI9488用のflush関数 TFT_eSPI tft = TFT_eSPI(); // TFTインスタンスを作成 // タッチイベントハンドラ static void touch_event_handler(lv_event_t *e) { lv_obj_t *obj = lv_event_get_target(e); lv_indev_t *indev = lv_indev_get_act(); lv_point_t point; lv_indev_get_point(indev, &point); // タッチされた位置に円を描画 lv_draw_rect_dsc_t rect_dsc; lv_draw_rect_dsc_init(&rect_dsc); rect_dsc.bg_color = lv_color_make(0xFF, 0x00, 0x00); // 赤色 lv_area_t area; area.x1 = point.x - 5; area.y1 = point.y - 5; area.x2 = point.x + 5; area.y2 = point.y + 5; lv_canvas_draw_rect(obj, area.x1, area.y1, lv_area_get_width(&area), lv_area_get_height(&area), &rect_dsc); } void setup() { lv_init(); tft.begin(); tft.setRotation(1); lv_disp_draw_buf_t draw_buf; static lv_color_t buf[TFT_WIDTH * 10]; // 描画バッファを定義 lv_disp_draw_buf_init(&draw_buf, buf, NULL, TFT_WIDTH * 10); // ディスプレイドライバを設定 static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.hor_res = TFT_WIDTH; disp_drv.ver_res = TFT_HEIGHT; disp_drv.flush_cb = my_disp_flush; // ここでILI9488用のflush関数を設定 disp_drv.draw_buf = &draw_buf; lv_disp_drv_register(&disp_drv); // キャンバスを作成 lv_obj_t *canvas = lv_canvas_create(lv_scr_act()); lv_obj_add_event_cb(canvas, touch_event_handler, LV_EVENT_PRESSED, NULL); } void loop() { lv_timer_handler(); // LVGLタイマーを処理 delay(5); } // ILI9488用のflush関数(ディスプレイドライバの設定に必要) void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { uint32_t w = (area->x2 - area->x1 + 1); uint32_t h = (area->y2 - area->y1 + 1); tft.startWrite(); tft.setAddrWindow(area->x1, area->y1, w, h); tft.pushColors((uint16_t *)&color_p->full, w * h, true); tft.endWrite(); lv_disp_flush_ready(disp); }

  • public void paint(Graphics g){

    public void paint(Graphics g){ g.setColor(new Color(ci, ci, ci)); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(Color.WHITE); g.drawString("Canvas表示", 20, 20); g.drawImage(image, x1, y1, this); g.drawImage(image1, x2, y2, this); } public void update(Graphics g){ paint(g); } public void run(){         //while(true)で永久ループ //imageの座標を変更する処理         //repaint();     } スレッドを使ってイメージの座標を変更し、イメージが動くプログラムを作りました。 これだと滑らかに動かないからpaintメソッドをもうひとつ作って 処理するpaintと描画するpaintとにわけたらいいと言われました。 ですがやりかたがわからないので教えてください。

  • スキャナの速度

    いまこのスキャナを使っていて GT-9400UF http://www.epson.jp/products/back/hyou/scanner/gt9400uf.htm このスキャナへの買い換えを検討しています。 CanoScan LiDE220 http://cweb.canon.jp/canoscan/lineup/lide220/ スキャン速度がどれだけ速くなるのかを知りたいのですが GT-9400UF 3.1msec/line(600dpi) CanoScan LiDE220 A4カラー文書/300dpi 約10秒 とあるのですが、300dpiで比較すると http://d.hatena.ne.jp/yoshisite/20091126/1259213718 A4 - 210×297ミリ 8.26*11.69?  2480*3510ピクセル なので、 【3510*3.1e-3/2】 5.4405 となり、旧機種のGT-9400UFが5.4秒のところが 新機種のCanoScan LiDE220だと10秒ということになります。 転送速度は含まれておりませんが、 10年前の機種よりも新機種の方が遅いというのはなぜなのでしょうか?

  • 初心者です。 コンパイルのエラー

    import java.awt.*; import javax.swing.*; public class R11Sample1 extends JFrame { Rect r1 = new Rect(Color.red, 100, 100, 80, 60); Rect r2 = new Rect(new Color (0.5f, 1f, 0f, 0.7f), 150, 120, 60, 90); Oval = new Oval(Color.blue, 60, 50, 10, 10); JPanel panel = new JPanel() { public void paint(Graphics g) { Graphics2D g2 = (Graphics2D)g; r1.draw(g2); r2.draw(g2); } }; public R11Sample1() { setSize(400, 350); setDefaultCloseOperation(EXIT_ON_CLOSE); getContentPane().add(panel); } public static void main(String[] args) { new R11Sample1().setVisible (true); } } class Rect { Paint pat; int xpos, ypos, width, height; public Rect(Paint p, int x, int y, int w, int h) { pat = p; xpos = x; ypos = y; width = w; height = h; } public void draw(Graphics2D g) { g.setPaint(pat); g.fillRect(xpos-width/2, ypos-height/2, width, height); } } class Oval { Paint pat; int xpos, ypos, radius; public Oval(Paint p, int x, int y, int width, int height) { pat = p; xpos = x; ypos = y; width = w; height = h; } public void draw(Graphics2D g) { g.setPaint(pat); g.fillOval(xpos-width/2, ypos-height/2, width, height); } } これでコンパイルすると、 Identifierがありません といわれました。 どこを直せばいいのでしょうか。 また、全体的に間違ったところがあったら教えてください。

    • ベストアンサー
    • Java
  • ActionScript3.0にて描画させたい!

    2秒ほどかけて次の描画を実現させたいのでお力下さい! 真っ白の画面があり、(円形のマスクでロゴの全体が隠れているというイメージ。) 真下から両側に弧を描きながらロゴが見えてくる。(円形のマスクがロゴの中心を軸に真 下から上に開いていくイメージ) というものです。 言葉で表現するのがむずがしいのですが、 as初心者です。 現在はフレームアニメーションで(48フレーム分の絵を描いて)対応しましたが、 データが重いうえ、秒数の調整で融通が効かず大変です。 asで対応が出来るものならぜひ、この機会に触れておきたいと思い質問をさせて頂 きました。よろしくお願い致します。

  • C++での画像切り抜きについて

    こんにちは。プログラミング初心者です。 Microsoft Visual Studio C++ MFCで画像解析のプログラムを書いています。 その際、jpg画像から左上隅・右下隅の座標を指定してある領域を切り出したいのですが、 今の方法では切り出した画像の周りに黒の領域ができてしまいます。(添付画像参照) サイズを切り抜いた画像のサイズに変更して、黒の領域をなくしたいのですが、 どのように書けばいいのでしょうか? 下記のコードに追加する部分・変更する部分を具体的に教えていただけると有難いです。 説明不足で申し訳ありませんが、よろしくお願いいたします。 void CtestbView::OnUleft() //左上隅点の座標 { // TODO: ここにコマンド ハンドラー コードを追加します。 Lcpx=px; //左上隅のx座標 Lcpy=py; //左上隅のy座標 } void CtestbView::OnDright() //右下隅点を指定するサブルーチン { // TODO: ここにコマンド ハンドラー コードを追加します。 int x,y; Rcpx=px;//右下隅x座標 Rcpy=py;// y for(y=Lcpy-1; y<=Rcpy+1; y++) {//切り出し範囲を白線で囲む(白線を切り出さないため+-1を付加) img1.SetPixel(Lcpx-1,y,RGB(255,255,255)); //左側縦線 img1.SetPixel(Rcpx+1,y,RGB(255,255,255)); //右側縦線 } for(x=Lcpx-1; x<=Rcpx+1; x++) { img1.SetPixel(x,Lcpy-1,RGB(255,255,255)); //上側横線 img1.SetPixel(x,Rcpy+1,RGB(255,255,255)); //下側横線 } jpgLoadFlag1=true; Invalidate(); } void CtestbView::OnCut() //テンプレートを切り出すサブルーチン { // TODO: ここにコマンド ハンドラー コードを追加します。 int x,y; BeginWaitCursor(); for(y=0; y<jpgHeight; y++) for(x=0; x<jpgWidth; x++) img2.SetPixel(x,y,RGB(0,0,0)); //画面をクリア int xshift=0; int yshift=0; for(y=Lcpy; y<=Rcpy; y++) { for(x=Lcpx; x<=Rcpx; x++) { COLORREF color=img1.GetPixel(x,y); int RV=GetRValue(color); int GV=GetGValue(color); int BV=GetBValue(color); img2.SetPixel(x-Lcpx+xshift,y-Lcpy+yshift,RGB(RV,GV,BV)); } } xminP=xshift; xmaxP=Rcpx-Lcpx+xshift; //テンプレート上のパターンの位置 yminP=yshift; ymaxP=Rcpy-Lcpy+yshift; jpgWidth=xmaxP; jpgHeight=ymaxP; jpgLoadFlag2=true; Invalidate(); EndWaitCursor(); } void CtestbView::OnLButtonDown(UINT nFlags, CPoint point) //指定点の座標値を取り出す { // TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。 CView::OnLButtonDown(nFlags, point); int i,j; int x,y; px=point.x; //マウス指定点のx座標 py=point.y; //マウス指定点のy座標 COLORREF color=img1.GetPixel(px,py); //指定点のアドレス変換 rv=GetRValue(color); //マウス指定点の赤成分 gv=GetGValue(color); //マウス指定点の緑座標 bv=GetBValue(color); //マウス指定点の青座標 img1.SetPixel(px, py, RGB(255,0,0));//指定点位置の赤点表示 for(j=0; j<=20; j++)//指定点の色を20×20の短径で表示 for(i=0; i<=20; i++) img1.SetPixel(jpgWidth-30+i,20+j,RGB(rv,gv,bv)); //指定点の色設定 jpgLoadFlag1=true; InvalidateRect(NULL); }

  • BMP画像を画像処理して連続に表示したいですが?

    プログラミングの初心者ですが、現在VC++2005のフォームアプリケーションでプログラムについて勉強しています。画像を連続表示するところで、わからなくなってしまったので、みなさんのご指導お願いいたします。 やりたい処理は、取り込んだ画像の色を変化させて、順番に表示したい 処理です。作成したプログラムは下記のようになります。 前略 for(n=0; n<256; n+=20){ for(y=0; y<480; y++){ for(x=0; y<640; x++){ bmp->Setpixel(x, y, Color::FromArgb(n, n, n)); } } pictureBox->Image = bmp; Thread::Sleep(2000); } nの値をbmpに入れてから一回表示し、さらにnを足してからbmpに入れて表示するといった流れですが、Sleepを入れても何にも表示されません。 どういったところは不具合なのかをよくわかりません。 ご指導をいただければ感謝致します。どうぞよろしくお願い致します。

専門家に質問してみよう