2016-12-15 41 views
0

我對字節級別的圖像壓縮比較新,目前正在處理一個java圖像預處理器,它將採用bmp圖像,將其轉換爲一個8位無符號灰度級,然後在輸出和壓縮之前將其字節按高低進行堆棧。經過一些廣泛的研究和測試字節提取的各種方法後,我仍然沒有看到我需要的結果。在繼續之前,應該指出,所有這些圖像最初都是DICOM格式,我使用ij.plugin.DICOM包將像素數據提取爲bmp圖像。解壓縮然後從圖像字節數組中堆疊高低字節

下面的描述由下面的代碼表示。目前,我正在讀取原始圖像中的緩衝圖像,將其轉換爲灰度,然後從Raster獲取圖像字節。然後我把這些字節,並使用我在stackoverflow上找到的其他代碼,並將它們「轉換」爲二進制位的字符串表示形式。然後我將該字符串發送給字符數組。下一步可能是無關緊要的,但我希望在刪除它之前得到你的輸入(因爲我是新手)。我製作一個Bitset並遍歷「二進制」字符數組。如果字符值是「1」,我將BitSet中的位置設置爲true。然後我發送BitSet到另一個字節數組。

然後我創建了兩個新的字節數組,一個用於高位,另一個用於低位字節。使用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(); 
} 

非常感謝你的幫助!我花了近20個小時試圖解決這個問題。這是一個非常頭痛的問題,任何你的洞察力都會受到讚賞。

編輯:這裏是getGreyScale功能:

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; 
} 

編輯2:我已經根據要求添加了一些圖片。

電流輸出:

current image

注意,我不能與「預期」的高字節和低字節結果發送圖像,由於我的名聲是低於10。

+0

一)「有圖像矩陣是‘分裂’,其所有高上半字節,下半部分包含所有低字節。「:所以你希望所有字節的高部分聚集在圖像的上半部分?預期的結果是什麼? b)也許這一切都與dicom有關,我不知道任何東西,但認爲處理它的簡單步驟應該是有意義的,你期望什麼,你會得到什麼 – gpasch

+0

@gpasch a)是的。圖像應該出現在頂部的所有高位字節聚集在一起,而所有低位字節聚集在底部。換句話說,最終的圖像應該是原始的尺寸,但圖像的上半部分是一個迷你的明亮圖像,下半部分是一個迷你的黑暗圖像。 b)對於所有意圖和目的,到DICOM正在處理時,它應該作爲一個正常的bmp。 – Sarah

回答

2

這說每4個字節的變化;那不是你想要什麼:

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,我不知道它是如何工作的,以及它是否正確;那麼中間的位有很多的擺弄 - 你有二進制我不知道爲什麼你需要所有的字符串和返回 - 最後你可以嘗試顯示圖像作爲一個JFrame之前壓縮等,以確保它是視覺上你所期望的 – gpasch

+0

添加功能的問題,所以你可以看看它。我不確定是否需要字符串和後面的部分。我只是不完全清楚Java如何處理二進制位,或者如果它處理二進制位,並且想要確定。你認爲它會抑制我的代碼嗎? – Sarah