Java - записывать BufferedImage без потери качества изображения - PullRequest
0 голосов
/ 19 июня 2020

У меня есть этот кусок кода, который записывает BufferedImage в IIOImage. Моя проблема в том, что исходная фотография по-прежнему имеет лучшее качество по сравнению с новым сгенерированным изображением (мне нужно записать некоторые данные на изображении, и я использую Graphics2D). Вторая проблема заключается в том, что новое изображение намного больше исходного (исходное 1,7 МБ, новое 4,8 МБ). Другой способ сделать это - использовать ImageIO.write (), но тогда я не могу установить качество сжатия изображения. Есть ли способ преобразовать byte [] в BufferedImage, затем написать что-нибудь на изображении с помощью Graphics2D, а затем получить новое изображение с хорошим качеством и таким же размером?

   private void getJPGBytes(BufferedImage bi, ByteArrayOutputStream baos, 
                                String format) {
        try {
            JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
            jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            jpegParams.setCompressionQuality(1L);

            final ImageWriter writer = ImageIO.getImageWritersByFormatName(format).next();
            writer.setOutput(ImageIO.createImageOutputStream(baos));

            writer.write(null, new IIOImage(bi, null, null), jpegParams);
            writer.dispose();
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
    }
    public byte[] drawData(byte[] bytes, List<AIResponse> data) {
        try {
            ImageReader reader = ImageIO.getImageReadersBySuffix(getExtensionFromImage(bytes)).next();
            reader.setInput(ImageIO.createImageInputStream(new ByteArrayInputStream(bytes)));

            BufferedImage bi = reader.read(0);
            Graphics2D g2d = (Graphics2D) bi.getGraphics();

            g2d.setColor(new Color(168, 61, 40, 255));
            Stroke stroke = new BasicStroke(5.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            g2d.setStroke(stroke);

            for (AIResponse aiResponse : data) {
                Polygon poly = new Polygon();

                aiResponse.getCoordinates().forEach(coordinate -> {
                    poly.addPoint(coordinate.get(0).intValue(), coordinate.get(1).intValue());
                });
                g2d.drawPolygon(poly);
            }

            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            String format = getExtensionFromImage(bytes).toLowerCase();
            if (format.equals("jpg") || format.equals("jpeg")) {
                getJPGBytes(bi, baos, format);
            } else {
                getPNGBytes(bi, baos, bytes);
            }
            bytes = baos.toByteArray();

        } catch (IOException e) {
            throw new ApplicationException(e.getMessage());
        }
        return bytes;
    } 
...