2016-12-15 42 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