2016-12-15 8 views
0

バイトレベルで画像圧縮を行うのは比較的新しいですが、現在Javaイメージプリプロセッサで作業しています。 8ビットの符号なしグレースケールを作成し、そのバイトをエクスポートおよび圧縮する前に高および低に応じてスタックします。いくつかの広範な研究とバイト抽出のさまざまな方法のテストの後、私はまだ私が必要な結果を見ていない。私が続行する前に、これらの画像はすべて元々DICOM形式であり、ij.plugin.DICOMパッケージを使用してピクセルデータをbmp画像として抽出しています。イメージバイトの配列から上位バイトと下位バイトをスタックします。

以下の説明は以下のコードで表されます。現在、私はバッファリングされたイメージとして元のイメージを読み込み、グレースケールに変換してから、イメージ・バイトをRasterから取得しています。その後、私はそれらのバイトを取って、私はstackoverflowで見つけたいくつかの他のコードを使用し、バイナリビットの文字列表現に変換します。その文字列を文字配列に送ります。次のステップは余計なものかもしれませんが、削除する前に入力を受けたいと思っています(私はこれを初めて使っています)。私はBitsetを作り、「バイナリ」文字配列を通して繰り返します。文字の値が "1"の場合、BitSetのその位置をtrueに設定します。次に、別のバイト配列にBitSetを送信します。

次に2つの新しいバイト配列を作成します.1つは高位バイト配列、もう1つは低位バイト配列です。 forループを使用して、私は配列内のどこにあるかに応じて、 "ビット"配列を繰り返し、上位または下位バイトに4ビットごとに格納します。

最後に、私はDICOMタグデータを取り出し、バイト配列を作成して、タグ配列、上位バイト配列、および下位バイト配列をスタックします。私の意図した結果は、上の半分がすべての上位バイトを含み、下半分がすべての下位バイトを含む「イメージ・マトリックス」を「分割」することです。私はタグのバイトが非常に小さく、最終的な結果に影響を与えるべきではないと言われています(私はそれらを使わずに画像をテストしました。確かに、目に見える違いはありませんでした)。

以下はコードです。ご不明な点がありましたら教えてください。関連するすべてのデータを含めるようにしました。あなたがもっと必要ならば教えてください。

 BufferedImage originalImage = getGrayScale(img.getBufferedImage());//returns an 8-bit unsigned grayscale conversion of the original image 
     byte[] imageInByte = ((DataBufferByte) originalImage.getRaster().getDataBuffer()).getData(); 
     String binary = toBinary(imageInByte); //converts to a String representation of the binary bits 
     char[] binCharArray = binary.toCharArray(); 
     BitSet bits = new BitSet(binCharArray.length); 
     for (int i = 0; i < binCharArray.length; i++) { 
      if (binCharArray[i] == '1') { 
       bits.set(i); 
      } 
     } 
     imageInByte = bits.toByteArray(); 

     byte[] high = new byte[(int) imageInByte.length/2]; 
     byte[] low = new byte[(int) imageInByte.length/2]; 

     int highC = 0; 
     int lowC = 0; 
     boolean change = false; //start out storing in the high bit 
     //change will = true on very first run. While true, load in the high byte array. Else low byte 
     for(int i = 0; i < imageInByte.length; i++){ 
      if(i % 4 == 0){ 
       change = !change; 
      } 
      if(change){ 
       high[highC] = imageInByte[i]; 
       highC++; 
      } else { 
       low[lowC] = imageInByte[i]; 
       lowC++; 
      } 
     } 
     //old code from a previous attempt. 
    // for (int j = 0; j < imageInByte.length; j++) { 
    //  byte h = (byte) (imageInByte[j] & 0xFF); 
    //  byte l = (byte) ((imageInByte[j] >> 8) & 0xFF); 
    //  high[j] = h; 
    //  low[j] = l; 
    // } 

     OutputStream out = null; 
     //add this array to the image array. It goes at the beginning. 
     byte[] tagBytes = dicomTags.getBytes(); 
     currProcessingImageTagLength = tagBytes.length; 
     imageInByte = new byte[high.length + low.length + tagBytes.length]; 
     System.arraycopy(tagBytes, 0, imageInByte, 0, tagBytes.length); 
     System.arraycopy(high, 0, imageInByte, tagBytes.length, high.length); 
     System.arraycopy(low, 0, imageInByte, tagBytes.length + high.length, low.length); 

     BufferedImage bImageFromConvert = new BufferedImage(dimWidth, dimHeight, BufferedImage.TYPE_BYTE_GRAY);//dimWidth and dimHeight are the image dimensions, stored much earlier in this function 
     byte[] bufferHolder = ((DataBufferByte) bImageFromConvert.getRaster().getDataBuffer()).getData(); 
     System.arraycopy(imageInByte, 0, bufferHolder, 0, bufferHolder.length); 
    //This is where I try and write the final image before sending it off to an image compressor 
     ImageIO.write(bImageFromConvert, "bmp", new File(
       directory + fileName + "_Compressed.bmp")); 
     return new File(directory + fileName + "_Compressed.bmp"); 

以下、あなたが興味を持っていた場合はtoBinary機能である:

private static String toBinary(byte[] bytes) { 
    StringBuilder sb = new StringBuilder(bytes.length * Byte.SIZE); 
    for (int i = 0; i < Byte.SIZE * bytes.length; i++) { 
     sb.append((bytes[i/Byte.SIZE] << i % Byte.SIZE & 0x80) == 0 ? '0' : '1'); 
    } 
    return sb.toString(); 
} 

はあなたの助けのためにありがとうございました!私は今、この1つの問題を解決しようとしている20時間近くを費やしました。それは大きな頭痛であり、あなたが持っているどんな洞察も高く評価されます。

EDIT:

public static BufferedImage getGrayScale(BufferedImage inputImage) { 
    BufferedImage img = new BufferedImage(inputImage.getWidth(), inputImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY); 
    Graphics g = img.getGraphics(); 
    g.drawImage(inputImage, 0, 0, null); 
    g.dispose(); 
    return img; 
} 

EDIT 2:私は、要求に応じて、いくつかの画像を追加しました。ここgetGreyScale機能です。

電流出力:

current image

注、私が原因私の評判は10よりも低いに上位バイトと下位バイトの成果を「期待」で画像を投稿することはできません。

+0

からa)すべての高を含む上半分に分割 『「画像行列とを持つこと』、これでそれに代わります下位半分にはすべての下位バイトが含まれています」:すべてのバイトの上位部分をイメージの上部にまとめるには?期待される結果は何ですか? b)多分それは私が何も知らないdicomと関係しているかもしれませんが、処理の簡単なステップとして考えて、あなたが何を期待して何を得るのか理解してください。 – gpasch

+0

@gpasch a)はい。イメージは、すべての高位バイトが最上部で束ねられ、すべての低位バイトが最下部で束ねられて表示されます。換言すれば、最終画像は元の寸法でなければならないが、画像の上半分はミニ明るい画像であり、下半分はミニ・ダーク画像である。 b)すべての目的と目的のために、DICOMが処理されるまでには、通常のbmpとして機能するはずです。 – Sarah

答えて

2

これは、4バイトごとに変化します。あなたが意図したものではないthatsの:

for(int i = 0; i < imageInByte.length; i++){ 
     if(i % 4 == 0){ 
      change = !change; 
     } 
     if(change){ 
      high[highC] = imageInByte[i]; 
      highC++; 
     } else { 
      low[lowC] = imageInByte[i]; 
      lowC++; 
     } 
    } 

私はあなたの以前の試み

for (int j = 0; j < imageInByte.length; j+=2) { 
     byte h = (byte) (imageInByte[j] & 0xF0); 
     byte h2 = (byte) (imageInByte[j+1] & 0xF0); 
     byte l = (byte) (imageInByte[j] & 0x0f); 
     byte l2 = (byte) (imageInByte[j+1] & 0x0f); 
     high[j/2] = h|(h2>>4); 
     low[j/2] = (l<<4)|l2; 
    } 
+0

ええ、間違いなく、私が必要とするものにもっと近く見えますが、まだまだ少しです。コードを見て、私がやっていることではないことを確認しましょう。 – Sarah

+0

私はそれがどのように動作するか、その正しいかどうかわからない最初の部分toGrayがあります。その中にビットがたくさんあります。バイナリを持っているのですが、なぜそれがStringとBackに必要なのかわかりません。最後に、圧縮前などにJFrameとしてイメージを表示しようとすることができます。視覚的にあなたが期待しているもの – gpasch

+0

質問に関数を追加しました。私はストリングとバックの部分が必要かどうかわからない。私は、Javaがバイナリ・ビットを扱う方法やバイナリ・ビットを扱う方法を完全には明確にしておらず、確かにしたいと思っていました。あなたは私のコードを禁止していると思いますか? – Sarah

関連する問題