2017-07-05 14 views
0

PNG画像をグレースケールに変更する際に問題があります。私は、byte []イメージをパラメータとして受け入れ、新たに修正されたグレースケールイメージとしてbyte []として返すメソッドを作りたかったのです。Javaを使用してPNGイメージをグレースケールに変換するには?

以下のスニペットを使用して、JPEG画像で画像をグレースケールにするリンクが見つかりました。

private byte[] makeItGray(byte[] img, String contentType) throws IOException, Exception{ 


    InputStream in = new ByteArrayInputStream(img); 
    BufferedImage bimg = ImageIO.read(in); 

    for(int y=0; y < bimg.getHeight(); y++){ 
     for(int x=0; x < bimg.getWidth(); x++){ 
      Color color = new Color(bimg.getRGB(x,y)); 
      int graylevel = (color.getRed() + color.getGreen() + color.getBlue())/3; 
      int r = graylevel; 
      int g = graylevel; 
      int b = graylevel; 
      int rgb = (r<<16) | (g<<8) | b; 
      bimg.setRGB(x, y, rgb); 
     } 
    } 

    in.close(); 


    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    if(contentType.equals(MediaType.IMAGE_PNG_VALUE)){ 
     ImageIO.write(bimg, "png", baos); 
     System.out.println("PNG!!!"); 
    } 
    else if(contentType.equals(MediaType.IMAGE_JPEG_VALUE)){ 
     ImageIO.write(bimg, "jpg", baos); 
    } 
    else 
     throw new Exception(); 



    baos.flush(); 
    byte[] grayImage = baos.toByteArray(); 
    baos.close(); 

    return grayImage; 
} 

私の参照は、以下にあった: How can I use ImageJ as a library for a separate Java application? https://www.mkyong.com/java/how-to-convert-byte-to-bufferedimage-in-java/

それは、JPEG画像に動作しますが、PNGに、それは私に透明画像を送信します。

// converting orig image to grayscale in byte[] 
imageBytes = makeItGray(imageBytes, file.getContentType()); 
Path path = Paths.get("some path here that would overwrite existing image"); 
Files.write(path, imageBytes); 

私はそれがグレースケールであるかどうかを確認するために手動で画像を開こうとすると、それは私に透明画像やイメージなし、それはバイト[]データを返すので、nullを示していないが、を与えます。上記の方法がPNG形式で問題ないのですか?

質問がありましたら教えてください。ありがとう!

+0

"手動で画像を開く"とはどういう意味ですか、どのように透明であることがわかりますか? –

+0

画像がグレースケールで表示されているかどうかを確認するには、手動で開き、透明にしますか?私のアプリケーションでエラーがないので、私のプログラムが画像(png)に対してGETリクエストを行うときはいつも、タグをbase64データで埋めています。 しかし、イメージはありません。そのような透明です。 – bpunzalan

答えて

1

実際には、getRGBsetRGBメソッドは名前にかかわらず、32ビットのパックARGB形式のピクセルを実際に返して受け入れます。つまり、BufferedImageのカラーモデルに実際にアルファチャンネルが含まれている場合、そのピクセルのアルファ値を空のままにしておくと(0x00)、すべての透過画像が得られます。

PNG形式はアルファJPEGは通常それを使用しませんが、そういうわけで、あなたが行った結果を見るのはなぜでしょうか、さまざまなフォーマットで異なるように見えるのです。

修正はちょうどすべての不透明なアルファとのピクセル値を付加、しかし単純です:あなたは、元のアルファを保持したい場合は、あなたがあまりにも(私はsimpliedfiedことを行うことができます

int rgb = 0xff000000 | (r << 16) | (g << 8) | b; 
bimg.setRGB(x, y, rgb); 

コード少し):

int oldrgb = bimg.getRGB(x,y); 
Color color = new Color(oldrgb); 
int gray = (color.getRed() + color.getGreen() + color.getBlue())/3; 
int rgb = (oldrgb & 0xff000000) | (gray << 16) | (gray << 8) | gray; 
bimg.setRGB(x, y, rgb); 

PS:平均化によってグレー値を計算するあなたの方法をW推奨されないことに注意してくださいRGBをグレースケールに変換するため、画像が他のツールと比べて見えなくなることがあります。例えば、Converting color to grayscaleを参照してください。

+0

うわー!これは魅力のように機能します! :)問題の詳細な解答と説明をありがとう。 ARGB値で画像に文字列を追加するたびに、imagejの私の問題でこれを行うこともできます。 – bpunzalan

関連する問題