• ベストアンサー

memcpyで画像を送りたいのですが・・

DirectXを使って 片方の画像(テクスチャ)の一部を、もう片方に送りたいのですが・・ 画像を直接送るだけなら、縦横ピクセル分のforで ------------------------------ memcpy((BYTE*)Rect_tgt.pBits + Rect_tgt.Pitch * i + j*4, (BYTE*)Rect_base.pBits + Rect_base.Pitch * i + j*4, 4); ------------------------------ これで送れるのですが、RGBAそれぞれを確認しながら 特定の色を置き換えたり、抜き色操作したくて ------------------------------ BYTE psend[4]; psend[0] = (BYTE)Rect_base.pBits + Rect_base.Pitch * j + i*1; psend[1] = (BYTE)Rect_base.pBits + Rect_base.Pitch * j + i*2; psend[2] = (BYTE)Rect_base.pBits + Rect_base.Pitch * j + i*3; psend[3] = (BYTE)Rect_base.pBits + Rect_base.Pitch * j + i*4; memcpy((BYTE*)Rect_tgt.pBits + Rect_tgt.Pitch * j + i*4, &psend, 4); ------------------------------ などと色々いじりまわしてみているのですが、 一色で塗り潰した画像を使っても、変なパターン模様になってしまいます。 ------------------------------ psend[0] = 255; psend[1] = 255; ........ ------------------------------ 等と直接指定すれば、ちゃんとそれに応じた色が書き出されるので 他の部分は正常だと思うのですが・・ どうすればRGBA1つ1つの色を正しく受け取れるでしょうか?

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

  • ベストアンサー
  • goosyu
  • ベストアンサー率58% (36/62)
回答No.4

補足ありがとうございました。やりたいことがなんとなくわかりました。指摘点は変更ありませんが,サンプルを訂正します。 for (j = 0;j < tgt_height;j++) { for (i = 0;i < tgt_width; i++) { BYTE psend[4]; BYTE *pSrc; pSrc = &((BYTE *)Rect_base.pBits)[Rect_base.Pitch * j + i * 4]; psend[0] = pSrc[0];//B psend[1] = pSrc[1];//G psend[2] = pSrc[2];//R psend[3] = 255;//A // 正常な直接転送 memcpy((BYTE*)Rect_tgt.pBits + Rect_tgt.Pitch * i + j*4, (BYTE*)Rect_base.pBits + Rect_base.Pitch * i + j*4, 4); memcpy((BYTE*)Rect_tgt.pBits+Rect_tgt.Pitch * j + i*4, &psend, 4); //本体 } }

zaxs5968
質問者

お礼

ありがとうございます・・! 動いて欲しかった通りに動いてくれました・・! BYTE *pSrc; pSrc = &((BYTE *)Rect_base.pBits)[Rect_base.Pitch * j + i * 4]; 一応ポインタやアドレス渡し等の基礎は一通り習ったはずなのですが、 今の私には何をどうやってるのか解らない構文・・orz もう質問の本題は解決できてしまったのでお礼を――なのですが、 これを理解しないとまた似たような質問をここにしてしまいそうなので、 よろしければ pSrc = &((BYTE *)Rect_base.pBits)[Rect_base.Pitch * j + i * 4]; で何が起きているのか軽くでいいので、教えて頂けると幸いです orz

その他の回答 (4)

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.5

【説明】  「pSrc = &((BYTE *)Rect_base.pBits)[Rect_base.Pitch * j + i * 4];」は「pSrc = (BYTE *)Rect_base.pBits + Rect_base.Pitch * j + i * 4;」と同じ結果になると思います。  イメージとしては,「&Rect_base.pBits[Rect_base.Pitch * j + i * 4]」と記述した方がわかりやすいかなと思いコーディングしましたが,「Rect_base.pBits」は「void *」のためキャストが必要となり複雑になったかもしれません。  次のように式を分けるとたぶん読みやすくなります。   pSrc = (BYTE *)Rect_base.pBits;   pSrc = &pSrc[Rect_base.Pitch * j + i * 4];  一応,提供ソースを最小限修正するコードものせておきます。 psend[0] = *((BYTE *)(Rect_base.pBits)+Rect_base.Pitch * j + i*4);//B psend[1] = *((BYTE *)(Rect_base.pBits)+Rect_base.Pitch * j + i*4+1);//G psend[2] = *((BYTE *)(Rect_base.pBits)+Rect_base.Pitch * j + i*4+2);//R psend[3] = 255;//A  または psend[0] = ((BYTE *)(Rect_base.pBits))[Rect_base.Pitch * j + i*4];//B psend[1] = ((BYTE *)(Rect_base.pBits))[Rect_base.Pitch * j + i*4+1];//G psend[2] = ((BYTE *)(Rect_base.pBits))[Rect_base.Pitch * j + i*4+2];//R psend[3] = 255;//A  となります。

zaxs5968
質問者

お礼

pSrc = (BYTE *)Rect_base.pBits; pSrc = &pSrc[Rect_base.Pitch * j + i * 4]; なるほど。 渡しの勉強不足を自覚しましたが、この書式の意味が解りました・・! 色々と親切丁寧に教えて頂いて、本当にありがとうございます・・! この書式、自分でも使えるよう頑張ります。ありがとうございました~!o(_ _)o

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.3

 Rect_base.pBitsがD3DLOCKED_RECT型のメンバであればvoid *なので値はテクスチャの先頭アドレスになります。  この為「Rect_base.pBits + Rect_base.Pitch * j + i*1」ではアドレスの計算結果になります。  それを「psend[0]」に入れてもアドレスの指す値にはなりません。  書くとすれば「psend[0] = (BYTE)Rect_base.pBits + Rect_base.Pitch * j + i*1;」は 「psend[0] = ((BYTE*)Rect_base.pBits)[ Rect_base.Pitch * j + i*1];」となります。  もう一点問題点は「i*1」「i*2」「i*3」「i*4」の計算です。参照位置の計算は「i+0」「i+1」「i+2」「i+3」が正しいと思います。  参考までに次のようなソースでたぶん実施したいことができると思います。 // 1ピクセルが4バイトで構成されている場合のサンプル BYTE *pSrc; // pBitsの値が格納 long index; pSrc = (BYTE *)Rect_base.pBits; for (j= 0;j<Height;j++) { // Heightは元のソースに合わせて置き換えてください for (i= 0;i<Width;i++) { // Widthは元のソースに合わせて置き換えてください BYTE psend[4]; index = Rect_base.Pitch * j + i * 4; psend[0] = pSrc[ index ]; psend[1] = pSrc[ index + 1 ]; psend[2] = pSrc[ index + 2 ]; psend[3] = pSrc[ index + 3 ]; // 値変更する処理をここに書く memcpy(pSrc, &psend[0], 4); } }

zaxs5968
質問者

お礼

ご回答ありがとうございます。

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.2

iの増加量とかわからないので,可能であれば2重のfor文を含めたソースを開示してください。Rect_base.pBitsとRect_base.Pitchn具体的な値があれば確認しやすいです。

zaxs5968
質問者

お礼

ご回答ありがとうございます。 ---------------------------------------------- D3DLOCKED_RECT Rect_tgt; panels->pTex[1]->LockRect(0, &Rect_tgt, NULL, D3DLOCK_DISCARD); panels->pTex[1]->LockRect(0, &Rect_tgt, NULL, 0); D3DLOCKED_RECT Rect_base; pFontTex->LockRect(0, &Rect_base, NULL, D3DLOCK_DISCARD); pFontTex->LockRect(0, &Rect_base, NULL, 0); for (j = 0;j < tgt_height;j++) { for (i = 0;i < tgt_width; i++) { BYTE psend[4]; psend[0] = (BYTE)Rect_base.pBits + Rect_base.Pitch * j + i*1;//B psend[1] = (BYTE)Rect_base.pBits + Rect_base.Pitch * j + i*2;//G psend[2] = (BYTE)Rect_base.pBits + Rect_base.Pitch * j + i*3;//R psend[3] = 255;//A // 正常な直接転送 memcpy((BYTE*)Rect_tgt.pBits + Rect_tgt.Pitch * i + j*4, (BYTE*)Rect_base.pBits + Rect_base.Pitch * i + j*4, 4); memcpy((BYTE*)Rect_tgt.pBits + Rect_tgt.Pitch * j + i*4, &psend, 4); //本体 } } pFontTex->UnlockRect(0); panels->pTex[1]->UnlockRect(0); ---------------------------------------------- こうなってます、値は Rect_base.Pitch = 4804 Rect_base.pBits = 0x04b90040 Rect_tgt.Pitch = 724 Rect_tgt.pBits = 0x001f81a0 となっていました。宜しくお願いします orz

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

>memcpy((BYTE*)Rect_tgt.pBits + Rect_tgt.Pitch * j + i*4, &psend, 4); 第2引数に & が付いているのは、どうしてですか? 第3引数は転送バイト数を指定します。本当に4バイトでいいのですか?

zaxs5968
質問者

お礼

ご回答ありがとうございました。 他のサンプルからの切り張りでイマイチ理解してなくて申し訳ないです; もっと勉強しようと思います;

関連するQ&A

  • CopyMemory()をmemcpy()に書き換える方法

    読み込んだBMP画像をテスクチャに転送しようとしています。 CopyMemory(lpPixel + j + i * iWidth, lpBMPPixel + j*3 + i * iLength, 3); の第二引数から memcpy((BYTE*)LockedRect.pBits + LockedRect.Pitch*i +4*j, &Color, sizeof(DWORD)); の第一引数へ入れたいのですが、 CopyMemory()は LPDWORD型のlpPixelに数値を足して指したメモリブロックに対して、 LPBYTE型のlpBMPPixelに数値を足して(?)指したメモリブロックの情報を 3バイトずつ転送している事。 memcpy()は pBits=テスクチャのメモリブロックの始点 Pitch=テスクチャ1行分のメモリの長さ(改行保障値)で指定したアドレスに DWORD型のColorを直接のデータとして書き込んでいる。 という事まではわかったのですが CopyMemory()側の第二引数   lpBMPPixel + j*3 + i * iLength, から色情報を取り出そうと、型変換したりポインタで受け取ろうとしてみたのですが、 上手く行きませんでした。 ヒント程度で構いませんので、何か教えて頂けると幸いです。

  • OpenGL 画像のα値操作

    こんにちは。 現在、授業の一環でGLUTを用いたOpenGLのプログラムを作っています。 そのプログラムの機能の中に、読み込んだ画像のα値を記憶した後、キー操作によって表示・非表示を切り替える機能を作ろうとしています。 目的の機能自体は一応途中まで(各ピクセルのα値を255⇔0への切り替え)は作れたのですが、原理がよく分かりません。 具体的に書くと、(幅)×(高さ)×(色のチャンネル数) の画像を読み込んだのに、4倍の高さの範囲までα値に関する処理を加えないと、処理後の効果が画像全体に現れないのです。 下にプログラムの断片を張るので、わかる方がいたら解説お願いします。 出来れば、後々のために理由を知っておきたいので。 -*-*-*-*-*-*-*-*-*- /* テクスチャの情報を格納する構造体 */ typedef struct{ unsigned int name; /* 識別番号 */ unsigned char* data; /* 画像のデータ */ int width; /* 画像の幅 */ int height; /* 画像の高さ */ int channels; /* 画像の色成分の数 */ }texture; /* テクスチャ(グローバル変数) */ texture a; /* 画面表示用の関数 */ void display (void) {  /* 初期化 */ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* 透明色を描けるようにする */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  /* 描画 */ glDrawPixels(a.width, a.height, GL_RGBA, GL_UNSIGNED_BYTE, a.data); glutSwapBuffers (); } /* α値の操作(代入値がかわるだけなので、255にする方は省略) */ void alpham(void) { int i, j; for (i = 0; i < a.height * 4; ++i) { for (j = 0; j < (a.width); ++j) { a.data[(a.width * i) + (a.channels * j) +3] = 0; } } } ※画像データ の メモリ確保サイズ a.data = (unsigned char*) malloc(width * height * channels)

  • DIB画像処理

    画像すべてのピクセル red値をプラス1( RGB()で赤色をプラス1) したいんですが。 24DIBで 30ピクセル x 30ピクセル画像として buf にピクセル列のポインタが読み込んである BYTE *buf, *newbuf; for(i=0; i<30; i++){  for(j=0; j<32; j++){  newbuf=*(buf+ □); 24DIBなので, 横幅は4の倍数のため for()文を32にしました。 newbuf=*(buf+ □);の文で赤ピクセルを取り出したいですが どのようにすればいいのか教えてください。

  • ビットマップ画像を読み込むプログラムがうまく行きません。困ってます…。

    こんにちは。大学4年のyu-tinと申します。 現在、大学の研究で使用するためのプログラムとして、以下の機能を持ったプログラム作りに取り込んでいます。 1)ビットマップ画像(グレースケール、縦480×横640pixel)を読み込み、  その画像の1つ1つの画素の輝度値を表示させる 2)読み込んだビットマップ画像を出力させる しかし、作成したプログラムがうまく行きません。以下の3つの問題が発生しています。 a)0行0列~1行383列までの画素値がおかしい。  (0,0,0,0,1,1,1,0,2,2,2,0,3,3,3,0,…,254,0,255,255,255,0 となっている) b)出力した画像の最上部2行程度に、細くて黒い線が表示される。  (読み込んだ画像と全く同じ画像を出力させたい) c)出力した画像が、”ディスクエラー”によりPhotoshopで開けない。  (ペイントでは開ける) その問題のプログラムは、以下の通りです。 しかし、このプログラムは、他人のプログラムに改良を加えて作成したものです。なので、このプログラム自体、私自身が完璧に理解できていない状況です。 私は、プログラミングに関しては初心者に近いので、丁寧に教えて頂けると大変助かります。 研究が先に進まず、大変困っています…。みなさま、本当に、本当によろしくお願い致します。 //ビットマップ画像に関するプログラム。 //画像の表示と輝度値の表示を行う。 #include<stdio.h> #include<windows.h> #include<stdlib.h> #define X_SIZE 640  //画像の横幅(ピクセル数) #define Y_SIZE 480  //画像の縦幅(ピクセル数) #define Z_SIZE 1    //1つの画素に含まれる色の数 void *malloc(size_t size); void main(void) {  int i, j, k;   //ループ用変数 i…縦の画素用, j…横の画素用, k…色数用  int x=0;    //画像の横幅(ピクセル数)*/  int y=0;     //画像の縦幅(ピクセル数)  FILE *fp; /***********元画像データのメモリ確保*********/  BYTE ***mae;  mae=(BYTE ***)malloc(sizeof(BYTE **)*Y_SIZE);  for(i = 0; i < Y_SIZE; i++){   mae[i]=(BYTE **)malloc(sizeof(BYTE *)*X_SIZE);  }  for(i = 0; i < Y_SIZE; i++){   for(j = 0; j < X_SIZE; j++){    mae[i][j]=(BYTE *)malloc(sizeof(BYTE)*Z_SIZE);   }  } /*******画像の読み込み・輝度値の表示*******/  fp=fopen("sample1.bmp","rb");   //画像”sample1”を開く  BITMAPFILEHEADER bmfh;  BITMAPINFOHEADER bmih;  fread(&bmfh,sizeof(bmfh),1,fp);  fread(&bmih,sizeof(bmih),1,fp);  x=bmih.biWidth;  //インフォヘッダに含まれる画像の幅情報をxに代入  y=bmih.biHeight;  //インフォヘッダに含まれる画像の高さ情報をyに代入  for(i = 0; i < y ;i++){   for(j = 0; j < x; j++){    fread(&mae[i][j][0],sizeof(BYTE),1,fp);    if(i<640 && j<480)printf("%d, %d, %d\n",i, j, mae[i][j][0]);   //輝度値を表示   }  }  fclose(fp); /**************画像の表示*************/  //画像”sample1”を”sample2”という名前で出力する  fp = fopen("sample2.bmp" ,"wb");  //ヘッダの書き込み  fwrite(&bmfh,sizeof(bmfh),1,fp);  fwrite(&bmih,sizeof(bmih),1,fp);  for(i = 0; i < bmih.biHeight; i++){   for(j = 0; j < bmih.biWidth; j++){    fwrite(&mae[i][j][0],sizeof(BYTE),1,fp);   }  }  fclose(fp);  //ファイルをクローズ }

  • TIFの画像について

    CADソフトにTIFの画像を2枚重ねて張り付けたいんですが、 黒一色だと見にくいので片方のTIFをたとえば緑色などにして張り付け様としたんですが方法が解りません。 OSは 2000 XPhome 画像をさわれるソフトはphotoshop5.0 LEしかありません。 教えて下さいお願いします。

  • processingのマウス操作について

    現在processingを使って、画像のような図を作り、マウスでクリックしたところだけに色がついて、もう一度クリックすると色が消えるというプログラミングを作りたいと思っているのですが、なかなかうまくできません。 以下現在打ち込んでいるものです // Click within the image to change // the value of the rectangle after // after the mouse has been clicked int value = 255; int rect_size = 50; int num = 300 / rect_size; int x; void setup(){ size(300,300); } void draw(){ fill(value); for (int i = #ffffff;i < num;i++){ for (int j = 0;j < num;j++){ if (j%2 == 0){ x = i*rect_size*2; } else { x = i*rect_size*2+rect_size; } rect(x,j*rect_size,rect_size,rect_size); } } } void mouseClicked() { if (value == 255) { value = #aaaaaa; } else { value = 255; } } 使用言語はすべて英語です。 おそらく、drawのところでパターンとしてチェック模様を書いてしまっているのと、1マスだけに限定するという風な命令を書けていないからだと思うのですが、先生に訊いてもよくわかりません。 ご存じの方はご指導ご鞭撻のほどどうぞよろしくお願いします。

  • DirectX ~テクスチャに値を書き込む~

    m_pDevice->CreateTexture( 128, 128, 1, 0, D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &pTex, NULL ); で生成したテクスチャに浮動小数点の値を 自分で書き込みたいのですが、うまくいきません。 テクスチャのサーフェスをロックしたあと、操作できるようですが・・ ソースコードを記述します。 D3DLOCKED_RECT rect; LPDWORD data; float a = 0.0; float r = 0.56; float g = 0.24; float b = 1.0; /* テクスチャのサーフェスをロック */ surface->LockRect(&rect, NULL, 0); for(int y=128-1; y>=0; y--){ /* 書き込む行の先頭アドレスに移動する */ data = (LPDWORD)((LPBYTE)rect.pBits + rect.Pitch * y); for( int x=0; x<128; x++){ /* カラーデータを書き込む */ *data = ((DWORD)a << 96) | ((DWORD)b << 64) | ((DWORD)g << 32) | ((DWORD)r );     data++; } } スペースで余白を空けることができなくて、少々見にくくなってしまいました。 1つの色につき32bitななので、32bitづつシフトしています。 また、float型は4バイト(32bit)なので間違ってはいないと思うのですが・・。 何かアドバイスできる方はお願い致します。

  • プログラムが動きません。。。(VC++)

    下のソースコードなのですが、コンパイルしてみたのですがうまく動作しません。また、LPVIDEOHDRとは一体何を表しているのでしょうか?この二点をどなたかご教授のほどよろしくお願いいたします。 LRESULT PASCAL CCapture01Dlg::FrameCallback(HWND hWnd, LPVIDEOHDR lpVHdr) { int i,j; BYTE *pBuff; memcpy(m_lpData,lpVHdr->lpData,lpVHdr->dwBufferLength); pBuff=m_lpData; for(j=0;j<HEIGHT;j++){ for(i=0;i<WIDTH;i++){ image_b[i][j]= *pBuff; pBuff++; image_g[i][j]= *(pBuff+1); pBuff++; image_r[i][j]= *(pBuff+2); pBuff++; } } return LRESULT(); }

  • 解像度が同じなのにプリントサイズが違う原因は。

    解像度が縦横全く同じの画像ファイルがあるのですが、 フォトショップ5.5Jで印刷しようとすると、 片方はA4いっぱいなのに、 もう片方はどういうわけか印刷サイズが極めて小さいのです。 考えられる原因はなんでしょうか。

  • c 画像の一致を調べる

    ppmの画像2つがあり、画像2は画像1のどこか一部分を切り取った画像です。 HEIGHT 画像1の縦 WIDTH 画像1の横 HEIGHT_R 画像2の縦 WIDTH_R 画像2の横 とします。 image[i][j].g 画像1 image_re[i][j].g 画像2 には各位置での緑の色情報を格納しているとします。このときに比較の方法は次のようにしてみました。画像1の左上の座標を(0,0)として横に調べていき、一致したところ(1)でそこからWIDTH_Rだけの幅の範囲で各マスが合っているか比較し、合っていれば次の下の行について同じことをして。。。 それでもし一致しないところが出てきたら、(1)のもう一つ横マスについておなじことをやって。。。 と繰り返していく方法です for(i=0; i<HEIGHT; i++) for(j=0; j<WIDTH; j++) for(m=i; m<i+HEIGHT_R; m++){ if(a=0){a=1;break;} if(image[j][m].g == image_re[j][m].g) for(k=j; k<j+WIDTH_R; k++) if(image[k][m].g==image_re[k][m].g)a=1; else {a=0; break;} else break; if(m==i+HEIGHT_R)printf("TRUE"); としてみたのですが どうもsegmentation fault と出てしまいます。 まちがってるところがあればご指摘下さい

専門家に質問してみよう