Gladiator9120
Gladiator9120

Reputation: 117

Create Two Row image from Text in Java

I already have a working API in java that takes text in request, and creates a PNG image from this text using custom fonts and returns a BASE64 encoded data of the image.

Now, I need to modify this method to support two row to be displayed in scrolling on a physical hardware device.

Requirement : if the text input in request contains pipe ('|') it's a two row content.

Existing code for single row image (this works fine) :

 String text = request.getTextValue();

        ClassPathResource resource = new ClassPathResource("/font/pg-led-16pt.ttf");

        InputStream inputStream = resource.getInputStream();
        Font font = Font.createFont(Font.PLAIN, inputStream).deriveFont(Font.PLAIN, 14f);

        BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = img.createGraphics();

        g2d.setFont(font);
        FontMetrics fm = g2d.getFontMetrics();
        int width = fm.stringWidth(text);
        int height = fm.getHeight();
        g2d.dispose();

        Color customTextColor = new Color(request.getDisplayColor().getR(), request.getDisplayColor().getG(), request.getDisplayColor().getB());

        img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        g2d = img.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
        g2d.setFont(font);
        fm = g2d.getFontMetrics();
        g2d.setColor(customTextColor);
        g2d.drawString(text, 0, fm.getAscent());
        g2d.dispose();

        BufferedImage newImage;
        if (img.getWidth() < 60) {
            newImage = ImageUtilities.addBlackBackground(img, request.getBackgroundColor(), request.getAlignment() == null ? null : request.getAlignment());
        } else {
            newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            g2d = newImage.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
            g2d.setColor(request.getBackgroundColor() == null ? Color.BLACK : new Color(
                    request.getBackgroundColor().getR(),
                    request.getBackgroundColor().getG(),
                    request.getBackgroundColor().getB()
            ));
            g2d.fillRect(0, 0, width, height);
            g2d.drawImage(img, 0, 0, null);
            g2d.dispose();
        }

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMddHHmm");
        String fileName = name == null ? ZonedDateTime.now().format(formatter) : name;
        File file = new File(fileName.concat(".png"));

        try {
            BufferedImage resizedImage = ImageUtilities.resizeImage(newImage, newImage.getWidth(),
                    request.getHeight() == null ||  request.getHeight() == 0 ? 16 : request.getHeight(),
                    request.getScaling(), Image.SCALE_DEFAULT);

            ImageIO.write(resizedImage, "png", file);

            String imageName = file.getName();
            String url = null;
            byte[] response = FileUtils.readFileToByteArray(file);

            File ppmFile = null ;

            if (request.getImageType()!=null && request.getImageType().equals(ImageFormat.PPM)){
                ppmFile = ImageUtilities.convertPngToPPM(file,imageName, null, true);
                response = FileUtils.readFileToByteArray(ppmFile);
            }

            if (request.getCreateFile()!= null && request.getCreateFile()){
                String key = folderKey == null ? "s3/customers/"+request.getCustomerId()+"/textpreviews/" : folderKey;

                if (request.getImageType()==null || request.getImageType().toString().isEmpty() || request.getImageType().equals(ImageFormat.PNG)){
                    url = s3Factory.uploadFile(file, key);
                }

                if (request.getImageType()!=null && request.getImageType().equals(ImageFormat.PPM)){
                    url = s3Factory.uploadFile(ppmFile, key);
                }
            }
            TextToImageResponse finalResponse = new TextToImageResponse();
            finalResponse.setCode(response);
            finalResponse.setHeight(resizedImage.getHeight());
            finalResponse.setWidth(resizedImage.getWidth());
            finalResponse.setS3Url(url);
            file.delete();
            return AppResponse.responseOk("Success", finalResponse);

        } catch (IOException ex) {
            ex.printStackTrace();
            return AppResponse.responseError(400, "Something went wrong while processing the Image");
        }

    public static BufferedImage addBlackBackground(BufferedImage img, DisplayColor backgroundColor, Alignment alignment) {
        // Default values for background color and alignment
        Color background = (backgroundColor != null) ?
                new Color(backgroundColor.getR(), backgroundColor.getG(), backgroundColor.getB()) :
                Color.BLACK;

        // Calculate X and Y offsets based on the alignment
        int x = 0;
        int y;
        int imageWidth = img.getWidth();
        int imageHeight = img.getHeight();

        if (alignment == null) {
            x = (60 - img.getWidth()) / 2;
            y = (16 - img.getHeight()) / 2;
        } else {
            y = switch (alignment) {
                case left -> (16 - imageHeight) / 2;
                case center -> {
                    x = (60 - imageWidth) / 2;
                    yield (16 - imageHeight) / 2;
                }
                case right -> {
                    x = 60 - imageWidth;
                    yield (16 - imageHeight) / 2;
                }
            };
        }

        BufferedImage newImage = new BufferedImage(60, 16, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = newImage.createGraphics();
        g2d.setColor(background);
        g2d.fillRect(0, 0, 60, 16);
        g2d.drawImage(img, x, y, null);
        g2d.dispose();

        return newImage;
    }

    public static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight, Integer scale, int scalingProperty) {

        if (scale != null && scale > 1) {
            targetHeight = targetHeight * scale;
            targetWidth = targetWidth * scale;
        }

        Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, scalingProperty);
        BufferedImage outputImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
        outputImage.getGraphics().drawImage(resultingImage, 0, 0, null);
        return outputImage;
    }


**Two Row image code (doesn't work) : **

        String text = request.getTextValue();

        // Check for two-row text logic
        String[] textRows = text.split("\\|", 2);
        String topRow = textRows[0].trim();
        String bottomRow = textRows.length > 1 ? textRows[1].trim() : null;

        // Use special font for two-row text if applicable
        Font font;
        if (bottomRow != null) {
            ClassPathResource specialFontResource = new ClassPathResource("/font/pg-led-9-pt.ttf");
            InputStream specialFontInputStream = specialFontResource.getInputStream();
            font = Font.createFont(Font.PLAIN, specialFontInputStream).deriveFont(Font.PLAIN, 14f);
        } else {
            ClassPathResource defaultFontResource = new ClassPathResource("/font/pg-led-16pt.ttf");
            InputStream defaultFontInputStream = defaultFontResource.getInputStream();
            font = Font.createFont(Font.PLAIN, defaultFontInputStream).deriveFont(Font.PLAIN, 14f);
        }

        BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = img.createGraphics();
        g2d.setFont(font);
        FontMetrics fm = g2d.getFontMetrics();
        int topRowWidth = fm.stringWidth(topRow);
        int height = fm.getHeight();
        g2d.dispose();

        Color customTextColor = new Color(request.getDisplayColor().getR(), request.getDisplayColor().getG(), request.getDisplayColor().getB());

        // Create image for top row
        BufferedImage imgTopRow = new BufferedImage(topRowWidth, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2dTopRow = imgTopRow.createGraphics();
        g2dTopRow.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
        g2dTopRow.setFont(font);
        fm = g2dTopRow.getFontMetrics();
        g2dTopRow.setColor(customTextColor);
        g2dTopRow.drawString(topRow, 0, fm.getAscent());
        g2dTopRow.dispose();

        // Create image for bottom row if applicable
        BufferedImage imgBottomRow = null;
        if (bottomRow != null) {
            int bottomRowWidth = fm.stringWidth(bottomRow);
            imgBottomRow = new BufferedImage(bottomRowWidth, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2dBottomRow = imgBottomRow.createGraphics();
            g2dBottomRow.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
            g2dBottomRow.setFont(font);
            fm = g2dBottomRow.getFontMetrics();
            g2dBottomRow.setColor(customTextColor);
            g2dBottomRow.drawString(bottomRow, 0, fm.getAscent());
            g2dBottomRow.dispose();
        }

        // Combine images if there is a bottom row
        BufferedImage newImage;
        if (imgBottomRow != null) {
            newImage = ImageUtilities.combineImages(imgTopRow, imgBottomRow);
        } else {
            newImage = imgTopRow;
        }

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMddHHmm");
        String fileName = name == null ? ZonedDateTime.now().format(formatter) : name;
        File file = new File(fileName.concat(".png"));

        try {
            BufferedImage resizedImage = ImageUtilities.resizeImage(newImage, newImage.getWidth(),
                    request.getHeight() == null ||  request.getHeight() == 0 ? 16 : request.getHeight(),
                    request.getScaling(), Image.SCALE_DEFAULT);

            ImageIO.write(resizedImage, "png", file);

            String imageName = file.getName();
            String url = null;
            byte[] response = FileUtils.readFileToByteArray(file);

            File ppmFile = null ;

            if (request.getImageType()!=null && request.getImageType().equals(ImageFormat.PPM)){
                ppmFile = ImageUtilities.convertPngToPPM(file,imageName, null, true);
                response = FileUtils.readFileToByteArray(ppmFile);
            }

            if (request.getCreateFile()!= null && request.getCreateFile()){
                String key = folderKey == null ? "s3/customers/"+request.getCustomerId()+"/textpreviews/" : folderKey;

                if (request.getImageType()==null || request.getImageType().toString().isEmpty() || request.getImageType().equals(ImageFormat.PNG)){
                    url = s3Factory.uploadFile(file, key);
                }

                if (request.getImageType()!=null && request.getImageType().equals(ImageFormat.PPM)){
                    url = s3Factory.uploadFile(ppmFile, key);
                }
            }
            TextToImageResponse finalResponse = new TextToImageResponse();
            finalResponse.setCode(response);
            finalResponse.setHeight(resizedImage.getHeight());
            finalResponse.setWidth(resizedImage.getWidth());
            finalResponse.setS3Url(url);
            file.delete();
            return AppResponse.responseOk("Success", finalResponse);

        } catch (IOException ex) {
            ex.printStackTrace();
            return AppResponse.responseError(400, "Something went wrong while processing the Image");
        }
    }

    public static BufferedImage combineImages(BufferedImage topImage, BufferedImage bottomImage) {
        int combinedWidth = Math.max(topImage.getWidth(), bottomImage.getWidth());
        int combinedHeight = 16; // Set height to a fixed value (16 in this case)

        BufferedImage combinedImage = new BufferedImage(combinedWidth, combinedHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = combinedImage.createGraphics();

        g2d.drawImage(topImage, 0, 0, null);
        g2d.drawImage(bottomImage, 0, 8, null);

        g2d.dispose();

        return combinedImage;
    }

Image generated using the two Row code :

enter image description here

Upvotes: 1

Views: 23

Answers (0)

Related Questions