저는 바이트 수준에서 이미지 압축을하는 것이 비교적 새롭습니다. 현재 bmp 이미지를 취할 수있는 Java 이미지 전 처리기에서 작업하고 있습니다. 8 비트 부호없는 그레이 스케일을 생성 한 다음 바이트를 내보내고 압축하기 전에 높이 및 낮음에 따라 스택합니다. 몇 가지 광범위한 연구와 바이트 추출의 다양한 방법을 테스트 한 후에도 필자는 필요한 결과를 보지 못했습니다. 계속하기 전에이 모든 이미지는 원래 DICOM 형식으로되어 있으며 ij.plugin.DICOM 패키지를 사용하여 픽셀 데이터를 bmp 이미지로 추출합니다.압축을 풀고 이미지 바이트 배열에서 상위 및 하위 바이트를 쌓습니다.
다음 설명은 아래 코드로 표시됩니다. 현재 원본 이미지를 버퍼링 된 이미지로 읽고 회색 음영으로 변환 한 다음 래스터에서 이미지 바이트를 가져옵니다. 그런 다음 그 바이트를 가져 와서 stackoverflow에서 찾은 다른 코드를 사용하여 이진 비트의 문자열 표현으로 변환합니다. 그런 다음 해당 문자열을 문자 배열로 보냅니다. 다음 단계는 관계가 없지만 삭제하기 전에 사용자의 의견을 듣고 싶었습니다. Bitset을 만들고 "binary"문자 배열을 반복합니다. 문자 값이 "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 시간을 보냈습니다. 엄청난 두통이었고, 당신이 가진 통찰력은 인정 될 것입니다.
편집 :
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 : 나는 요청에 따라 일부 이미지를 추가 한 다음은 getGreyScale 기능입니다.
전류 출력 :
주, 나는 때문에 내 명성보다 낮은 10 인에 "기대"상위 바이트와 하위 바이트 결과와 이미지를 게시 할 수 없습니다.
가) 모든 높은 포함 된 상위 절반 분할 ""이미지 매트릭스가 될 수있는 방법 " 바이트와 아래쪽 절반은 모두 하위 바이트를 포함합니다. ": 그래서 당신은 모든 바이트의 높은 부분을 이미지의 위쪽 부분에 함께 모으고 싶습니까? 예상되는 결과는 무엇입니까? b) 어쩌면 그것 모두는 내가 잘 모르는 dicom과 관련이있다. 그러나 처리의 간단한 단계로 생각하면 무엇을 기대하고 무엇을 얻을 수 있는지 이해해야한다. – gpasch
@gpasch a) 예. 이미지는 모든 상위 바이트가 맨 위에 놓여지고 모든 하위 바이트는 맨 아래에 묶입니다. 즉, 최종 이미지는 원본 크기 여야하지만 이미지의 상단 절반은 미니 밝은 이미지이며 하단은 미니 어두운 이미지입니다. b) 모든 의도와 목적을 위해 DICOM이 처리 될 때까지는 정상 bmp로 작동해야합니다. – Sarah