• ベストアンサー

BMP画像のネガを作成するプログラム

BMP画像をnegative colorにするプログラムの手本を見ていて、どういう仕組でネガが作成されるのか疑問に思いました。 以下のプログラムがそれです。 -------------------------------------------------- for(i=0; i<NVERT; i++){ //縦方向のループ for(j=0; j<NHORI; j++){ //横方向のループ ich1=i*NHORI+j; //処理する点(?)をich1に格納 for(k=0; k<3; k++){ //GBRを順番に反転させるためのループ(?) buf[ich1][k]=255-buf[ich1][k]; //反転 } } } -------------------------------------------------- まだあまり理解できていないのですが、 buf[][0]には赤、buf[][1]には緑、buf[][2]には青 が与えられている気がします。 buf[ich1][k]=255-buf[ich1][k]; この式で、255から引くことによってどうして反転するのか具体的に知りたいです。 どなたかよろしくお願いしますm(__)m

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★アドバイス >この式で、255から引くことによってどうして反転するのか具体的に知りたいです。  単純に1色 8 ビットで表現しているため、255 から引くのです。  ポジティブ・ネガティブ変換はビットの反転を行えばよいのです。→補数を取る  このビットの反転は color & 0xFF でも良いのですが、255 から引いて補数を  取る方法でも同じになるのです。 ・よって、255 とは1色 8 ビットの補数を取るための 255 です。  もし、1色 4 ビットなら補数として 15 の数になります。 >buf[ich1][k]=255-buf[ich1][k];  ↑の部分は  buf[ich1][k] ^= 0xFF;  でも同じになります。こちらの方がちょっと高速演算されます。 ・以上。おわり。

参考URL:
http://homepage3.nifty.com/rio_i/lab/xlib/021filter.htm#21_3
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • TT414
  • ベストアンサー率18% (72/384)
回答No.4

>この式で、255から引くことによってどうして反転するのか具体的に知りたいです。 色の反転は各色の最大値を最小値へ、最小値を最大値へ変換します。 「新しい明るさ=最大値+(現在の明るさ-最小値)」ですが、移項して「新しい明るさ=(最大値+最小値)-現在の明るさ」として、(最大値+最小値)を255と書けば文字数が少なくなるので、書いてあるのでしょう。

すると、全ての回答が全文表示されます。
  • php504
  • ベストアンサー率42% (926/2160)
回答No.2

それぞれの色は8ビットで表されるので最も明るい色が255になり最も暗い色が0になります。 255から引くことで明るさが入れ替わりますね 255->0 254->1 ・ ・ 1->254 0->255

すると、全ての回答が全文表示されます。
  • gungnir7
  • ベストアンサー率43% (1124/2579)
回答No.1

まずGBRの場合、0に緑、1に青、2に赤が格納されていると思います。 (プログラムの都合によって順番が変わっているかもしれません) 次に本題ですが反転とはビットが逆転すること。 例えば11110000なら00001111となります。 C言語で記述しているのなら自身のNotを取った方がスマートですね。 8bitの反転は255から自身を引いても同じ結果になります。 実際に自分で計算して確かめてみて下さい。

すると、全ての回答が全文表示されます。

関連するQ&A

  • raw形式からbmp形式への書き込み (画像処理)

    今、raw形式のファイルを読み込んで、bmp形式への書き込みを 行うプログラムを作成しているのですがうまくいきません. 作成したプログラムの一部は以下のようになっています. ------------------rawファイルを読み込む関数の一部------------- //1次元配列の確保 tmp=us_Calloc2(width,height); //画像の読み込み fread(tmp,sizeof(unsigned short),width*height,fp); //2次元配列の確保 img->data=us_Calloc1(width,height); //1次元配列から2次元配列にデータを移動する for(i=0; i<height; i++){ for(j=0; j<width; j++){ img->data[i][j]=tmp[(width*i)+j]; } } ------------------------------------------------------------ --------------bmpファイルに書きこむ(一部)-------------- //bufのメモリ領域の確保 buf=us_Calloc2(width,height); for(i=0; i<height; i++){ for(j=0; j<width; j++){ buf[(width*i)+j]=img->data[i][j]; } } //BMPのファイルヘッダーの出力(省略) //BMPの情報ヘッダーの出力(省略) //画像データの出力 if(fwrite(buf,sizeof(unsigned short),size,fp)!=size){ printf("画像をBMPに書き込むことができませんでした.\n"); free(buf); fclose(fp); exit(-1); } } このように書いたのですが、うまくBMPファイルに出力できません. アドバイスよろしくお願いします.

  • このプログラムの結果は正しいのでしょうか?

    下記のプログラムはregister変数へのアクセスが高速であることを確認するためのプログラムです #include <stdio.h> #include <time.h> int i; /* これはグローバル変数なので、 register変数には変換されない */ int main(void) { register int j; int k; clock_t start, finish; start = clock(); for(k=0; k<100; k++) for(i=0; i<32000; i++); finish = clock(); printf("レジスタを使わないループの刻み数: %ld \n", finish - start); start = clock(); for(k=0; k<100; k++) for(j=0; j<32000; j++); finish = clock(); printf("レジスタを使ったループの刻み数: %ld \n", finish - start); return 0; } 【質問】 このプログラムを実行すると、 レジスタを使わないループの刻み数: 15 レジスタを使ったループの刻み数: 0 と表示されます。 この結果はregister変数へのアクセスが高速であることの証明になるのでしょうか? また「刻み数」とは何のことですか?教えて頂けないでしょうか?

  • プログラム(C)

    #include <stdio.h> #include <stdlib.h> #define FNAME "smp.bmp" #define WSIZE 256 #define HSIZE 256 #define BSIZE 1024 int main(void) { struct BMPFILEHEADER { ・   ・ }; struct BMPINFOHEADER { ・   ・ }; unsigned char img[HSIZE][WSIZE][3]; unsigned char buf[BSIZE]; struct BMPFILEHEADER lpHead; struct BMPINFOHEADER lpInfo; FILE *fp; int i; int j; int k; fp = fopen(FNAME,"rb"); if (fp==NULL) { printf("ファイルをオープンできません\n"); return 0; } fread(&lpHead.bfType, sizeof(unsigned short),1,fp); fread(&lpHead.bfSize, sizeof(unsigned int),1,fp); fread(&lpHead.bfReserved1, sizeof(unsigned short),1,fp); fread(&lpHead.bfReserved2, sizeof(unsigned short),1,fp); fread(&lpHead.bf0ffBits, sizeof(unsigned int),1,fp); fread(&lpInfo, sizeof(struct BMPINFOHEADER),1,fp); for(i=0;i<HSIZE;i++) { fread(buf,sizeof(unsigned char),WSIZE*3,fp); for(j=0;j<WSIZE;j++) { for(k=0;k<3;k++) { img[HSIZE-1-i][j][k]=buf[j*3+k]; } } } fclose; return 0; } このプログラムはBMP画像を読み込むプログラムなんですが このプログラムに画素値を出力するプログラムにしたいのですがうまくできません。 結果は(真っ白な画像の時)255255255・・・255255と出力したいのです。白黒画像なのでR=G=Bで1画素値は255だけでいいのですが。どうしても255255255や25500などとでてしまいます。 アドバイスお願いします。(800字までなので構造体の宣言は抜いてしましました) 。

  • 細線化のプログラム

    細線化のプログラム C#で細線化のプログラムを作成してみましたがうまくいきません。 http://imagingsolution.blog107.fc2.com/blog-entry-138.html を参考に作成しました。 うまくいかないところは、一部に縦線がいくつも残ってしますところです。 ソース static Bitmap Shape(Bitmap bmp) { int Flag = 0; //初期化 for (int j = 0; j < bmp.Height ; j++) { for (int i = 0; i < bmp.Width ; i++) { if (bmp.GetPixel(i, j).R != 255) { bmp.SetPixel(i, j, Color.FromArgb(0, 0, 0)); } } } while(true){ //パターン1 for (int i = 1; i < bmp.Width - 1; i++) { for (int j = 1; j < bmp.Height - 1; j++) { if (bmp.GetPixel(i, j).R == 255) { //除去しないパターン if (( 略 )) { //セーフ } else if ((略)){ //セーフ } //除去するパターン else if ((bmp.GetPixel(i + 1, j).R != 255) || (bmp.GetPixel(i, j - 1).R != 255)) { //黒にする bmp.SetPixel(i, j, Color.FromArgb(0, 0, 0)); Flag++; } } } } // MessageBox.Show(Flag.ToString()); //終了 if (Flag == 0) return bmp; Flag = 0; /*パターン2も同じようにする*/ という感じでプログラムを組んでいます。 画像は失敗例です。アドバイスをお願いします

    • 締切済み
    • CGI
  • BMP画像ファイルの読み書き

    Visual StudioのC言語により、ビットマップ形式の画像に対するプログラミングで 簡単な背景差分のプログラムを作成しています。 背景画像と対象画像2枚を読み込み色の差を取り、 差の値が背景の値と近ければ背景とみなし白で塗りつぶし、 物体だけを表示した画像を生成するようなプログラムです。 1枚のみの画像は以下のプログラムで作動しますが、連続した画像(01.bmp 02.bmp ・・・・100.bmp) を読み込み上記の処理をする場合にはどうすればよいのでしょうか? 分かりにくくて申し訳ないですが、よろしくお願いします。 #include "BMPData.h" #include <math.h> int main(){ int a=150; int i,j; int r,g,b; int ir,ig,ib; int diff; BMPStruct bmp_bg; BMPStruct bmp_oj; BMPStruct bmp; RGB rgb_bg; RGB rgb_oj; RGB rgb; RGB rgb_w; rgb.r = 255; rgb.g = 255; rgb.b = 255; rgb_w.r = 0; rgb_w.g = 0; rgb_w.b = 0; readBMP(&bmp_bg, "back.bmp"); //背景画像の読み込み readBMP(&bmp_oj, "01.bmp"); //対象画像の読み込み makeBMP(&bmp,640, 480, rgb); //出力用画像を生成する for(i=0; i<640; i++){ for(j=0; j<480; j++){ getColor(bmp_bg, &rgb_bg,i,j);  //背景画像の色を取得 getColor(bmp_oj, &rgb_oj,i,j);  //対象画像の色を取得 //rgbそれぞれの値の差 r = rgb_bg.r - rgb_oj.r; g = rgb_bg.g - rgb_oj.g; b = rgb_bg.b - rgb_oj.b; //絶対値 ir = abs(r); ig = abs(g); ib = abs(b); //色の差 diff = ir + ig + ib; //背景かどうかの判定 if(diff>a){ putColor(bmp, rgb_w, i, j); //色の差が大きければ出力画像に対象画像の色をそのまま出力 } else{ putColor(bmp, rgb, i, j); //色の差が小さければ白を出力 } } } writeBMP(bmp, "image01.bmp"); }

  • 画像の合成プログラム

    現在、飛行機の羽の左側と、右側の羽で撮った2枚の航空写真を合成するプログラムを作っています。これらの画像には若干のずれがあり、合成するには、左の写真に写っている場所と対応する同じ点を右側の写真から探索する必要があります。今の段階で作っているプログラムでは全ての点を走査することができず、画像の一部だけしか走査されません。 以下のプログラムをどのように変更したら、画像全体を走査できるかアドバイスください。お願いします。 /*対応点の探索*/ for (x = 0; x < 512; x+=25) { for (y= 0; y < 512; y+=25) { for (i = 0; i < 30; i++) { for (j = 0; j < 30; j++) { block1[i][j] = image1[x - 30 / 2 + i][y - 30 / 2 + j]; } } min = 99999; x1 = x*2; if(x1 > 512){ x1 = 512; } y1 = y*2; if(y1 > 512){ y1 = 512; } for (i = 30 / 2; i < x1 - 30 / 2; i++) { for (j = 30 / 2; j < y1- 30 / 2; j++) { sa = 0; for(k = 0; k < 30; k++) { for(l = 0; l < 30; l++) { sa += abs(block1[k][l] - image2[i - 30 / 2 + k][j - 30 / 2 + l]); } } if (min > sa) { min = sa; min_i = i; min_j = j; } } } if(x-15 < min_i && min_i < x+15){ if(y-15 < min_j && min_j < y+15){ printf("File_1の座標点( %d, %d )の対応点は ( %d, %d ) である。\n",y,x, min_j, min_i); } } } } return 0; }

  • basicプログラムです。

    100 DIM A(5) 110 FOR J=1 TO 5 120 READ A(J)   130 NEXT J   140 FOR I=1 TO 4  150 LET K=I    160 FOR J=I+1 TO 5  170 IF A(J)<A(K) THEN LET k=J  180 NEXT J    190 LET T=A(I)    200 LET A(I)=A(K)   210 LET A(K)=T    220 FOR J=1 TO 5   230 PRINT A(J);   240 NEXT J     250 PRINT      260 NEXT I     270 DATA 5,3,7,2,1,  280 END このようなプログラムがあります。 いろいろ調べたのですがそれぞれの文の意味と 何を求めるプログラムか教えて下さい。 5つの数の組み合わせで小さい数から順番に4個 かなと思ったのですが???

  • BMPファイルへの書き込みができない

    このプログラムは、左半分を黒、右半分を白の画像をBMPファイルに出力しようとしています。(出来ていません) プログラムの下に質問書いてます!お願いします! #include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct{ char *filename; int x; int y; int width; int height; unsigned char data[80][100]; } BMP_DATA; static void WriteBmp(char *filename, BMP_DATA Image) { unsigned long Bmp_size;/*BMPファイルのサイズ*/ unsigned int Bmp_info_header_size;/*情報ヘッダのサイズ*/ unsigned int Bmp_header_size;/*ヘッダのサイズ*/ long Bmp_width;/*幅*/ long Bmp_height;/*高さ*/ unsigned short Bmp_planes;/*プレーン数*/ unsigned short Bmp_color;/*色 = 1[bit] (黒か白かだけ)*/ long Bmp_image_size;/*画像部分のサイズ*/ long Bmp_xppm;/*水平解像度*/ long Bmp_yppm;/*垂直解像度*/ int i,j; unsigned char Bmp_headbuf[54]; /*ヘッダ*/ unsigned char Bmp_Data[13]; FILE *Out = fopen(filename, "wb"); if(Out==NULL){ fclose(Out); exit(1); } /* ヘッダ情報の準備 */ Bmp_info_header_size = 40; Bmp_header_size = 54; Bmp_planes = 1; Bmp_color = 1; Bmp_image_size = Image.height * Image.width; Bmp_xppm = 0; Bmp_yppm = 0; Bmp_size = Bmp_image_size + Bmp_header_size; Bmp_headbuf[0] = 'B'; Bmp_headbuf[1] = 'M'; memcpy(Bmp_headbuf+2, &Bmp_size, sizeof(Bmp_size)); Bmp_headbuf[6] = 0; Bmp_headbuf[7] = 0; Bmp_headbuf[8] = 0; Bmp_headbuf[9] = 0; memcpy(Bmp_headbuf+10, &Bmp_header_size, sizeof(Bmp_header_size)); Bmp_headbuf[11] = 0; Bmp_headbuf[12] = 0; Bmp_headbuf[13] = 0; memcpy(Bmp_headbuf+14, &Bmp_info_header_size, sizeof(Bmp_info_header_size)); Bmp_headbuf[15] = 0; Bmp_headbuf[16] = 0; Bmp_headbuf[17] = 0; memcpy(Bmp_headbuf+18, &Image.width, sizeof(Bmp_width)); memcpy(Bmp_headbuf+22, &Image.height, sizeof(Bmp_height)); memcpy(Bmp_headbuf+26, &Bmp_planes, sizeof(Bmp_planes)); memcpy(Bmp_headbuf+28, &Bmp_color, sizeof(Bmp_color)); memcpy(Bmp_headbuf+34, &Bmp_image_size, sizeof(Bmp_image_size)); memcpy(Bmp_headbuf+38, &Bmp_xppm, sizeof(Bmp_xppm)); memcpy(Bmp_headbuf+42, &Bmp_yppm, sizeof(Bmp_yppm)); Bmp_headbuf[46] = 0; Bmp_headbuf[47] = 0; Bmp_headbuf[48] = 0; Bmp_headbuf[49] = 0; Bmp_headbuf[50] = 0; Bmp_headbuf[51] = 0; Bmp_headbuf[52] = 0; Bmp_headbuf[53] = 0; /* ヘッダ情報書き出し */ fwrite(Bmp_headbuf, sizeof(unsigned char), Bmp_header_size, Out); /* 画像データ書き出し */ for(i=0;i<13;i++) Bmp_Data[i] = 0; for(i=0; i<Image.height; i++){ for(j=0; j<Image.width; j++){ int index = j/8; if(j%8 == 0){ Bmp_Data[index] = Image.data[i][j ] * 128 + Image.data[i][j+1] * 64 + Image.data[i][j+2] * 32 + Image.data[i][j+3] * 16 + Image.data[i][j+4] * 8 + Image.data[i][j+5] * 4 + Image.data[i][j+6] * 2 + Image.data[i][j+7]; } } Bmp_Data[12] = (Bmp_Data[12] & 0xf0); fwrite(Bmp_Data, sizeof(unsigned char), 20, Out); /* ○ */ } fclose(Out); } int main() { BMP_DATA Image; int line = 0; int i,j; Image.x = 0; Image.y = 0; Image.width = 100; Image.height = 80; if(line == 0){ for(i=0; i<Image.height; i++){ for(j=0; j<Image.width; j++){ Image.data[i][j] = 1; } } } while(1){ /* BMPファイルデータを編集 */ for(j=0; j<Image.width; j++){ if(j < 50){ Image.data[line][j] = 0;//black }else{ Image.data[line][j] = 1;//white } } /* すべての列を編集したら、再描画する */ if(line == 63){ /* BMPファイルに書込む */ WriteBmp("display.bmp", Image); break; } line++; } return 0; } 以下の条件で、BMPファイルへ書き込もうとしています ・色の深さ1(黒か白) ・画像のピクセルサイズ(横100×縦80) fwrite関数で1列ずつ書き込もうとしているのですが、 この関数は1バイトずつしか書き込めないみたいで、100ビット書き込もうと思うと、 最低でも104ビット書き込まなくてはならない状況になります。 まず、この4ビットはどう処理すればいいのでしょうか?? あと、display.bmpのファイルがある状態で、プログラムを実行するとちゃんと動くのですが、 プログラム中の○のところのfwrite関数の第三引数を13にすると、BMPファイルが壊れて閲覧できなくなります。(ある程度大きい数字だと、BMPファイルは壊れないのですが、ぐちゃぐちゃの絵になります) その理由もわかりません。 汚い文章&プログラムですが よろしくお願いします><

  • ソートプログラム

    前に質問したものです。慌てていたのですみません。 Cで書いた直接選択法です。 #include <stdio.h> #include <stdlib.h> #include <time.h> #define N 1000 void main( void ) { int min,s,t,i,j,k,a[N]; srand((unsigned int)time(NULL)); for(i=0;i<N;i++) a[i]=rand()%1000+1; for(j=0;j<i-1;j++){ min=a[j]; s=j; for(k=j+1;k<i;k++){ if(a[k]<min){ min=a[k]; s=k; } } t=a[j];a[j]=a[s];a[s]=t; for(s=0;s<i;s++) printf("%d,\t",a[s]); } } このプログラムを実行すると、1回ずつ入れ替えされたものが出力されます。 100回、200回、・・・と入れ替えを行った値を出力するには、どうすればよいでしょうか? ループを入れてみたりしてみましたが、、?? プログラムを再帰の方法をつかって書いたほうが、、、?? よろしくお願いします。

  • プログラムがわかりません

    C言語の本を読んでいるんですが、詰まってしまいました。プログラム自体は単純なのですが #include<stdio.h> void hello(void) { fprintf(stderr,"hello!\n"); } void func(void) { void *buf[10]; static int i; for(i=0;i<10;i++) { buf[i] = hello; } } int main(void) { int buf[100]; func(); return 0; } のスタックオーバーフローのプログラムです。 1. 要素100のint型配列を宣言 2. 関数funcの呼び出し 3. void *buf[10]; まずここでがわかりません。なぜポインタが   でてきたのか?またbufの要素数は100では? 4. buf[i] = hello; のループ    これもわかりません。配列に関数を代入しているのでしょうか?     5.  fprintf(stderr,"hello!\n"); これもまたわかりません。    fprintfの最初の引数は出力先ですが、なぜ標準エラー出力なの   でしょうか? 時間のあるかた解説お願いします。

MDF材の切り口補強方法とは?
このQ&Aのポイント
  • MDF材の切り口に木ねじを使って補強する方法はあるのでしょうか?
  • MDF材には種類がありますが、詳細は不明です。テレビ台に使用する際に切り口を補強する方法を知りたいです。
  • MDF材は木ネジに弱いと言われていますが、切り口に使う木ねじを抜けにくくする方法はありますか?
回答を見る

専門家に質問してみよう