Java - 图像BMP标头

时间:2016-11-08 23:00:07

标签: java arrays image image-processing bmp

如果有人能帮助我,我会有一点问题,我会很高兴。 我试图进行下一步操作

  1. 阅读BMP图片
  2. 将图像转换为byte []
  3. 以90度(字节数组)
  4. 旋转图像
  5. 并在某个文件夹中写入新图像
  6. 我的问题是......在我尝试编写新图像的那一刻,我对BMP标题有一些问题而且我不知道为什么。如果有人知道这件衣服,请给我一些建议。

    将图像转换为byte []

    private static byte[] convertAnImageToPixelsArray(File file) throws FileNotFoundException {
        FileInputStream fis = new FileInputStream(file);
    
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        try {
            for (int readNum; (readNum = fis.read(buf)) != -1; ) {
                bos.write(buf, 0, readNum);
            }
        } catch (IOException ex) {
            Logger.getLogger(ConvertImage.class.getName()).log(Level.SEVERE, null, ex);
        }
        return bos.toByteArray();
    }
    

    旋转

    private static byte[] rotate(double angle, byte[] pixels, int width, int height) {
        final double radians = Math.toRadians(angle), cos = Math.cos(radians), sin = Math.sin(radians);
        final byte[] pixels2 = new byte[pixels.length];
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                final int
                        centerx = width / 2,
                        centery = height / 2,
                        m = x - centerx,
                        n = y - centery,
                        j = ((int) (m * cos + n * sin)) + centerx,
                        k = ((int) (n * cos - m * sin)) + centery;
                if (j >= 0 && j < width && k >= 0 && k < height)
                    pixels2[(y * width + x)] = pixels[(k * width + j)];
            }
        }
        arraycopy(pixels2, 0, pixels, 0, pixels.length);
        return pixels2;
    }
    

    将byte []转换为图像

    private static void convertArrayPixelsIntoImage(byte[] bytes) throws IOException {
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        Iterator<?> readers = ImageIO.getImageReadersByFormatName("bmp");
    
        ImageReader reader = (ImageReader) readers.next();
        Object source = bis;
        ImageInputStream iis = ImageIO.createImageInputStream(source);
        reader.setInput(iis, true);
        ImageReadParam param = reader.getDefaultReadParam();
    
        Image image = reader.read(0, param);
        BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
    
        Graphics2D g2 = bufferedImage.createGraphics();
        g2.drawImage(image, null, null);
    
        File imageFile = new File("Images/Output.bmp");
        ImageIO.write(bufferedImage, "bmp", imageFile);
    }
    

    主要

    public static void main(String[] args) throws IOException {
        File file = new File("Images/Input-1.bmp");
        Image img = ImageIO.read(file);
        convertArrayPixelsIntoImage(rotate(90,convertAnImageToPixelsArray(file),img.getWidth(null),img.getHeight(null)));
    }
    

    以下是错误消息:

      

    线程中的异常&#34; main&#34; javax.imageio.IIOException:无法读取图像标题。

    有什么建议吗?

2 个答案:

答案 0 :(得分:1)

问题是您在旋转图像时没有考虑BMP文件的结构。

你只是从文件中读取byte[],就像从任何文件中读取的那样 - 它只是一个字节流。

但在您的rotate方法中,您假设像素值为:

  • 每像素1个字节;
  • 从数组开始处开始。

事实并非如此。除了每个像素几乎肯定会被多个字节编码的事实之外,BMP file format以标题和其他元数据开头。

虽然您显然可以解决如何正确解码数据,但我强烈反对。您已经使用ImageIO(Image img = ImageIO.read(file);)阅读图像,因此您无需重新发明轮子:只需使用Java现有的图像处理功能。

答案 1 :(得分:0)

您错过了BMP图像具有与任何其他格式一样的标题。当您尝试旋转图像时,您正在更改字节顺序,因此标头会在其他位置而不是开始丢失。尝试将前54个字节提取到另一个数组,旋转其他字节,然后先写入文件头,然后写入第二个字节