プログラムで画像の明るさを変更する方法

このQ&Aのポイント
  • 現在、プログラムで画像の明るさを変更する方法について試していますが、うまくいきません。
  • 現在のプログラムでは、画像の明るさをランダムに選んで変更しているため、画像が乱れて表示されてしまいます。
  • ライン毎にランダムに明るさを選ぶ方法を教えてください。
回答を見る
  • ベストアンサー

プログラムで

以前も似たような質問をしたのですが、いろいろとやってみたのですがわからなくてまた質問しました。現在、次のようなプログラムを書いています。 int w = img.getWidth(this); int h = img.getHeight(this); int[] pixels = new int[w * h]; int[] epixels = new int[w * h]; int[] uepixels = new int[w * h]; int scan = w; int offset = 0; PixelGrabber pg = new PixelGrabber(img,0,0,w,h,pixels,0,scan); try{pg.grabPixels(); } catch(InterruptedException e){;} for(int i=0; i < w*h ; i++){ int r = (int)(pixels[i]&0x00ff0000); if (r!=0x00000000){r = ((int)((pixels[i]&0x00ff0000)*0.5)&0x00ff0000);} int g = (int)(pixels[i]&0x0000ff00); if (g!=0x00000000){g = ((int)((pixels[i]&0x0000ff00)*0.5)&0x0000ff00);} int b = (int)(pixels[i]&0x000000ff); if (b!=0x00000000){b = ((int)((pixels[i]&0x000000ff)*0.5)&0x000000ff);} if((ra.nextInt()%2)!=0) { epixels[i] = 0xff000000| r | g | b ; uepixels[i]=pixels[i]; } else { epixels[i] = pixels[i]; uepixels[i] = 0xff000000| r | g | b ; } (Exception ex){;} } しかし、これですとiが1進む毎にランダムに真または偽をとってしまうため、実際に動かしてみた所「砂嵐」のように画像が表示されました。このランダムにとるのを、1ライン目はそのままの明るさで2ライン目は明るさ半減していて3ライン目も明るさ半減していて・・・といった感じにライン毎にランダムに「そのままの明るさのライン」か「明るさが半減しているライン」かをとるように改良するにはどうしたらいいでしょうか?お願いします。

  • mos21
  • お礼率46% (128/273)
  • Java
  • 回答数1
  • ありがとう数1

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

  • ベストアンサー
  • takaP-
  • ベストアンサー率79% (83/105)
回答No.1

う~ん。。。 なんかhttp://www.okweb.ne.jp/kotaeru.php3?q=589046の#2さんのアドバイスが無になってるような (^^; #2さんもおっしゃってますが、ライン毎の変化を求めているのに、やってることはピクセル単位での変化になっちゃってますよね。これの原因が解からないというのはプログラムの力量云々とかじゃなくて、頭の整理が付いていない状態で闇雲にコーディングをしてしまっているからです。 ライン数とは、この場合「画像の縦のピクセル数」ですよね? ですから、img.getHeight() で求めた数値がライン数になります。 この数だけのランダムな真偽値が必要なのですから、まずは最初に必要な数だけの真偽値を求めてしまいましょう(余計な乱数を使わないために) int h=img.getHeight(this); boolean[] bool=new boolean[h]; Random ra=new Random(); for(int i=0; i<h; i++){  bool[i]=ra.nextBoolean(); } これで必要なだけの真偽値の配列が出来ます。 1行目のラインを変化させるかの判定値は bool[0]、2行目のラインを変化させるかの判定値は bool[1] ....... となります。 では、まずは1行目の最初のpixelを作成してみましょう。 if(bool[0]){//真なら  epixels[0]=(pixels[0] & 0x00FEFEFF) >> 1;  uepixels[0]=pixels[0]; } else {//偽なら  epixels[0]=pixels[0];  uepixels[0]=(pixels[0] & 0x00FEFEFF) >> 1; } *注)RGBそれぞれに取り出し演算せずとも上記のようにすれば、目的の処理を1行で済ます事が出来ます(かなり余談ですけど・w) 次に、この処理を1ライン分のピクセル数繰返すように書き換えてみましょう。 1ライン分のピクセル数は img.getWidth() で求められる数値です。ここでは w ですよね。 if(bool[0]){//1行目が真なら  for(int i=0; i<w; i++){   epixels[i]=(pixels[i] & 0x00FEFEFF) >> 1;   uepixels[i]=pixels[i];  } } else {//1行目が偽なら  for(int i=0; i<w; i++){   epixels[i]=pixels[i];   uepixels[i]=(pixels[i] & 0x00FEFEFF) >> 1;  } } これで1ライン作成のアルゴリズムが出来ました。 次に、複数ラインのアルゴリズムを作りますが、ライン数分この記述を繰返すのですから、外に大きなループを作ります。 for(int i=0; i<h; i++){//ライン数分繰返すループ  if(bool[i]){//i+1行目が真なら   for(int j=0; j<w; j++){    epixels[i*w+j]=(pixels[i*w+j] & 0x00FEFEFF) >> 1;    uepixels[i*w+j]=pixels[i*w+j];   }  }  else {//i+1行目が偽なら   for(int j=0; j<w; j++){    epixels[i*w+j]=pixels[i*w+j];    uepixels[i*w+j]=(pixels[i*w+j] & 0x00FEFEFF) >> 1;   }  } } 普通、他の方は↑とは違った(もっと簡潔な)アルゴリズムの形を取るかもしれません。けれど、ワンステップずつ発展させていく形を取るという性質上、上記の記述になりました。全体の流れが見えてくれば、簡略化する場所も自ずと見えてくるはずです。 注)上記のコードは何も確認してません。脳内コンパイル&実行のみですので、間違いがあるときはご容赦を。

mos21
質問者

お礼

ご丁寧な回答ありがとうございます。実際にやってみたり悪戦苦闘したんですが、#2さんのアドバイスやtakaP-さんの貴重なアドバイスも今の私の力量ではうまく生かせる事が出来ないみたいですね。1回でプログラムを完成しようとせずに、画像を3枚を交互に表示させるのではなくまずは1枚ずつ取得してその後3枚を交互に表示させるやり方で進めていきたいと思います。その時にはtakaP-のアドバイスもわかるようになると思います^^本当にありがとうございましたー!!

関連するQ&A

  • プログラムについて

    javaを使って静止画像にラインをつけて、その奇数ライン画像(偶数ラインは輝度が下がっている画像)と偶数ライン画像(奇数ラインは輝度が下がっている画像)の2枚の画像を1/100秒間隔で交互に表示させ、実際に見ているぶんには普通の静止画像が表示されているというプログラムを作りました。この輝度が下がっているところは奇数ラインと偶数ラインのように決まっているのですが、これを輝度が下がっているところがランダムになるようにとりたいのですがどうるればよいかわかりません... わかる方いましたら何かアドバイスなどお願いします。m(_ _)m for(int i=0; i < w*h ; i++){ try{ int r = (int)(pixels[i]&0x00ff0000); if (r!=0x00000000){r = ((int)((pixels[i]&0x00ff0000)*90/100)&0x00ff0000);} int g = (int)(pixels[i]&0x0000ff00); if (g!=0x00000000){g = ((int)((pixels[i]&0x0000ff00)*90/100)&0x0000ff00);} int b = (int)(pixels[i]&0x000000ff); if (b!=0x00000000){b = ((int)((pixels[i]&0x000000ff)*90/100)&0x000000ff);} if((((w+i)/w)%2)!=0){epixels[i] = 0xff000000| r | g | b ;uepixels[i]=pixels[i];} else {epixels[i] = pixels[i];uepixels[i] = 0xff000000| r | g | b ;} }catch(Exception ex){;} } これがそのプログラムの、交互に表示している場所だと思うのですが。

    • ベストアンサー
    • Java
  • 意味がわかりません

    for(int i=0; i < w*h ; i++){ try{ int r = (int)(pixels[i]&0x00ff0000); if (r!=0x00000000){r = ((int)((pixels[i]&0x00ff0000)*90/100)&0x00ff0000);} int g = (int)(pixels[i]&0x0000ff00); if (g!=0x00000000){g = ((int)((pixels[i]&0x0000ff00)*90/100)&0x0000ff00);} int b = (int)(pixels[i]&0x000000ff); if (b!=0x00000000){b = ((int)((pixels[i]&0x000000ff)*90/100)&0x000000ff);} if((((w+i)/w)%2)!=0){epixels[i] = 0xff000000| r | g | b ;uepixels[i]=pixels[i];} else {epixels[i] = pixels[i];uepixels[i] = 0xff000000| r | g | b ;} }catch(Exception ex){;} } このようなプログラムがあるのですが、何をしているのかがわかりません。 見づらいかもしれませんがどなたかわかる方よろしくお願いします。

  • プログラムで

    次のtry文がよくわからなくて困っています。わかる方いましたら解説お願いします。 try{ int r = (int)(pixels[i]&0x00ff0000); if (r!=0x00000000){r = ((int)((pixels[i]&0x00ff0000)*0.5)&0x00ff0000);} int g = (int)(pixels[i]&0x0000ff00); if (g!=0x00000000){g = ((int)((pixels[i]&0x0000ff00)*0.5)&0x0000ff00);} int b = (int)(pixels[i]&0x000000ff); if (b!=0x00000000){b = ((int)((pixels[i]&0x000000ff)*0.5)&0x000000ff);} if((((w+i)/w)%2)!=0){epixels[i] = 0xff000000| r | g | b ; uepixels[i]=pixels[i];} else {epixels[i] = pixels[i]; uepixels[i] = 0xff000000| r | g | b ;} }catch(Exception ex){;} }

    • ベストアンサー
    • Java
  • int型について

    1枚の静止画像の明るさを、1行おきにではなくてランダムに、元の色使いのままの行と、明るさを半減した行を持つという画像を2枚作成したいのですが、次のプログラムの記述ではif((r.nextInt()%2)!=0){の部分でintは間接参照できません。というエラーが出てしまいました。なぜでしょうか?わかる方いましたらお願いします。 先に記述してあるプログラムを後で記述したプログラムに改良したところエラーが起こってしまいました。 こちらが改良前で if((((w+i)/w)%2)!=0){ epixels[i] = 0xff000000| r | g | b ; uepixels[i]=pixels[i];} else {    epixels[i] = pixels[i];uepixels[i] =  0xff000000| r | g | b ;} こちらが改良後です。 if((r.nextInt()%2)!=0){ epixels[i] = 0xff000000|r|g|b; uepixels[i] = pixels[i]; } else{ epixels[i] = pixels[i]; uepixels[i] = 0xff000000|r|g|b; }

    • ベストアンサー
    • Java
  • 質問です。

    1枚の静止画像を、1行おきに、元の色使いのままの行と、明るさ半減した行を合成するというプログラムなのですが。偶数行を半減させるか、奇数行を半減させるかではなくてランダムに行を半減させるにはどうすればよいのでしょうか?RandomクラスやMathクラスを使用すればよいでしょうか? if((((w+i)/w)%2)!=0){  epixels[i] = 0xff000000| r | g | b ;  uepixels[i]=pixels[i]; } else {  epixels[i] = pixels[i];  uepixels[i] = 0xff000000| r | g | b ; }

    • ベストアンサー
    • Java
  • 意味がわかりません

    javaのプログラムでこのようなものがあったのですがよくわかりません、解説をお願いします。配列変数pixelsのi番目の値の何をr,g,bに入れているのかがよくわかりません。わかる方いましたら、お願いします。 for(int i=0; i < w*h ; i++) { try { int r = (int)(pixels[i]&0x00ff0000); if (r!=0x00000000) { r = ((int)((pixels[i]&0x00ff0000)*0.5)&0x00ff0000); } int g = (int)(pixels[i]&0x0000ff00); if (g!=0x00000000) { g = ((int)((pixels[i]&0x0000ff00)*0.5)&0x0000ff00); } int b = (int)(pixels[i]&0x000000ff); if (b!=0x00000000) { b = ((int)((pixels[i]&0x000000ff)*0.5)&0x000000ff); }

    • ベストアンサー
    • Java
  • 意味がわかりません

    このようなプログラムがあるのですが少し意味がわからなくて困っています。わかる方解説などお願いしますm(_ _)m try{mt.waitForAll(); } catch( InterruptedException e ) { } int w = img.getWidth(this); int h = img.getHeight(this); int[] pixels = new int[w * h]; int[] epixels = new int[w * h]; int[] uepixels = new int[w * h]; int scan = w; int offset = 0; PixelGrabber pg = new PixelGrabber(img,0,0,w,h,pixels,0,scan); try{pg.grabPixels(); } catch(InterruptedException e) { ; }

    • ベストアンサー
    • Java
  • ビットマップを直接編集して背景画像を波打たせる

    質問(1) pixelsは一次元配列で1ラインのx方向の要素を左方向や右方向にシフト量sだけ離れた所へコピーすることにより1ラインの画像のピクセルデータをシフト量sだけずらして波打たせる効果を持たせていることは想像つきますが、これではy方向を考慮した全てのラインをずらすことにはなっていない様な感じがします。y方向はどうなっているのですか? 質問(2) int line = y*bmpdata.Stride/4;で4で割っているのは何故ですか? 質問(3) if(s<0){ //左へコピー for(int x=-s; x<BITMAP_W; x++){ if(x+s>=0){ pixels[line+x+s] = pixels[line+x]; } } } でこのif文の中の条件式x+s>=0はint x=-s;→int x+s=0;…;x++により明らかに常に真ではないですか?もし、そうだとしたらこのif文は必要ないのではないですか? 質問(4) } else if(s>0){ //右へコピー for(int x=BITMAP_W; x>=s; x--){ if(x+s<BITMAP_W){ pixels[line+x] = pixels[line+x-s]; } } } } でこのif文の中の条件式x+s<BITMAP_Wの意味が良く分かりません。 質問(5)(6)(7) for(int y=0; y<BITMAP_H; y++){ … int line = y*bmpdata.Stride/4;の意味が良く分かりません。質問(5) … pixels[line+x+s] = pixels[line+x];でlineを加えているのは何故ですか?質問(6) … pixels[line+x] = pixels[line+x-s];でlineを加えているのは何故ですか?質問(7) C言語、C++言語初心者なので分かりやすく教えて下さい。 宜しくお願いします。 プログラムコード(animation.cpp) //ウェーブエフェクト UINT g_wavecount; const int BITMAP_H = 480; const int BITMAP_W = 320; float g_wavelines[BITMAP_H]; //ウェーブエフェクト初期化 void ResetWave(){ g_wavecount = 0; float r=0, rdelta=3.14f/12;//波の数 float waveh = 3;//波の高さ for(int i=0; i<BITMAP_H; i++){ g_wavelines[i] = sinf(r) * waveh; r += rdelta; } } //ウェーブエフェクト描画 void RenderWave(Gdiplus::Bitmap *bmp){ g_wavecount++; int topline = g_wavecount % BITMAP_H; //ビットマップのロック Gdiplus::BitmapData bmpdata; Gdiplus::Status status = bmp->LockBits( &Gdiplus::Rect(0,0,320,480), Gdiplus::ImageLockModeWrite, bmp->GetPixelFormat(), &bmpdata); if(status != Gdiplus::Ok) return; UINT* pixels = (UINT*)bmpdata.Scan0; //←この行から下のコードが全部分からない。 //ビットマップを加工する for(int y=0; y<BITMAP_H; y++){ //シフト量を取得 int s = (int)g_wavelines[(topline+y)%BITMAP_H]; int line = y*bmpdata.Stride/4; //ピクセルコピー if(s<0){ //左へコピー for(int x=-s; x<BITMAP_W; x++){ if(x+s>=0){ pixels[line+x+s] = pixels[line+x]; } } } else if(s>0){ //右へコピー for(int x=BITMAP_W; x>=s; x--){ if(x+s<BITMAP_W){ pixels[line+x] = pixels[line+x-s]; } } } } bmp->UnlockBits(&bmpdata); }

  • コンパイルできません

    imgにオリジナルの画像データを格納して、それを配列pixelsに格納した後、またpixelsをimg2等に格納してimg2を画面上に表示する。というものを作りたいのですが、コンパイルできなくて困っています。次はプログラムの一部です。pixelsに格納するところでエラーが出てしまいます。エラー内容は シンボルを解釈処理できません。 シンボル: クラス PixelGrabber 位置 : na3 の クラス PixelGrabber pg = new PixelGrabber(img,0,0,w,h,pixels,0,scan) と表示されます。 わかるかたいましたらお願いします。 img = Toolkit.getDefaultToolkit().createImage(imagedata); int w,h; w = (int)getSize().width; h = (int)getSize().height; buffer = this.createImage(w,h); bufferGraphics = buffer.getGraphics(); } public void paint(Graphics g){ int w,h; w = (int)getSize().width; h = (int)getSize().height; int[] pixels = new int[w * h]; int scan = w; int offset = 0; PixelGrabber pg = new PixelGrabber(img,0,0,w,h,pixels,0,scan); try{ pg.grabPixels(); } catch(InterruptedException e){ ; } bufferGraphics.drawImage(img,0,0,this); bufferGraphics.setColor(Color.black); //処理を10回繰り返す for(int j=0; j<10; j++){ //2から1002の中で乱数を1つranに取得 int ran = (int)(Math.random() * 1000)+2; for(int i=0;i<h;i+=ran){ //ranの値にしたがって画面上にラインを表示 bufferGraphics.drawLine(0,i,w,i); } g.drawImage(buffer,0,0,null); } }

    • ベストアンサー
    • Java
  • カラー画像からグレースケール画像フォーマットの変換

    カラー画像からグレースケール画像フォーマットの変換するプログラムなんですが、いまいち理解できていません。 プログラムはRGB構造体を使ってのものなんですが添削お願いいたします。 #include<stdio.h> #include<stdlib.h> typedef struct _RGB { unsigned char r; unsigned char g; unsigned char b; } RGB; int main(int argc, char *argv[]) { int x, y; unsigned char *in, *out; int i, j, Magic, level; unsigned char tmp[255]; RGB **pixels; int width = 255; int height = 255; int size = width * height; FILE *fin, *fout; if(argc != 3){ printf("Usage : %s input outpu \n", argv[0]); exit(1); } fin = fopen(argv[1], "rb"); fgets(tmp, 255, fin); if(tmp[0] != 'P'){ return 0; } sscanf(tmp, "P%d", &Magic); if(Magic < 1 || Magic > 6){ return 0; } do{ fgets(tmp, 255, fin); } while(tmp[0] == '#'); sscanf(tmp, "%d %d", &x, &y); if(x < 1 || y < 1){ return 0; } fgets(tmp, 255, fin); sscanf(tmp, "%d", &level); printf("P%d\n", &Magic); printf("%d %d\n", x, y); printf("%d\n", level); in = (unsigned char *)malloc(sizeof(unsigned char) *x*y); fread(in, sizeof(unsigned char), x*y, fin); pixels = (RGB**)malloc(width*sizeof(RGB*)); pixels[0] = (RGB* )malloc(size * sizeof(RGB)); for(i = 1; i < width; i++){ pixels[i] = pixels[i - 1] + height; } free(pixels[0]); for(i = 1; i < width * height * 3; i++){ out[i] = pixels[i][0].r * 0.299 + pixels[i][1].g * 0.587 + pixels[i][2].b * 0.114; } fout = fopen(argv[2], "wb"); fprintf(fout,"P%d\n",Magic); fprintf(fout,"# My new PGM\n"); fprintf(fout,"%d %d\n",x, y); fprintf(fout,"%d\n",level); fwrite(out, sizeof(unsigned char),x*y, fout); free(pixels); free(in); free(out); free(fin); free(fout); }

専門家に質問してみよう