我對字節級別的圖像壓縮比較新,目前正在處理一個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:我已經根據要求添加了一些圖片。
電流輸出:
注意,我不能與「預期」的高字節和低字節結果發送圖像,由於我的名聲是低於10。
一)「有圖像矩陣是‘分裂’,其所有高上半字節,下半部分包含所有低字節。「:所以你希望所有字節的高部分聚集在圖像的上半部分?預期的結果是什麼? b)也許這一切都與dicom有關,我不知道任何東西,但認爲處理它的簡單步驟應該是有意義的,你期望什麼,你會得到什麼 – gpasch
@gpasch a)是的。圖像應該出現在頂部的所有高位字節聚集在一起,而所有低位字節聚集在底部。換句話說,最終的圖像應該是原始的尺寸,但圖像的上半部分是一個迷你的明亮圖像,下半部分是一個迷你的黑暗圖像。 b)對於所有意圖和目的,到DICOM正在處理時,它應該作爲一個正常的bmp。 – Sarah