How to split a large image based on white space?

0

So I currently have a long comic strip and I want to split the image based on white space so none of the text bubbles or backgrounds are cut off.

Currently, I'm splitting the image based on a set size for, e.g. if the image is 100k pixels tall, then it splits the image into 6 equal parts, so the current height (curr) would be 16666.

It then checks at (curr) if all the pixels are white, and also if the row of pixels at (curr+1) is also all white.

And if both rows of pixels are all white, then it logs the height in an array.

If any non-white pixel is detected, then 10 pixels is added to the current height and check again if the rows at (curr)

This continues until (curr) reaches the height of the long image, after which it creates images based on the logged height values.

This is the logic I was going by, however, like all CS things, it didn't work in practice.

I tried this code with multiple images, and I see the split images with top and bottom edges being non-white.

public void smartStitch(ArrayList<BufferedImage> images) throws IOException {
        BufferedImage concatImage = new BufferedImage(images.get(0).getWidth(), images.get(0).getHeight(), BufferedImage.TYPE_INT_RGB);

        // Stitches if there's multiple images
        if (images.size() > 1) {
            int concatHeight = 0;

            // Gets the total height of the stitches image and prepares a Graphics2D for it
            for (BufferedImage b : images) {
                concatHeight += b.getHeight();
                Graphics2D g2d = b.createGraphics();
                g2d.dispose();
            }

            int heightCurr = 0;

            concatImage = new BufferedImage(images.get(0).getWidth(), concatHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = concatImage.createGraphics();

            // Draws the images on the Graphics2D
            for (BufferedImage b : images) {
                g2d.drawImage(b, 0, heightCurr, null);
                heightCurr += b.getHeight();
            }
            g2d.dispose();
        }

        // Determines how many images to split into
        int num;
        if (concatImage.getHeight() < 5000) {
            num = 2;
        } else if (concatImage.getHeight() <  25000) {
            num = 4;
        } else if (concatImage.getHeight() <  100000) {
            num = 6;
        } else {
            num = 8;
        }

        // Splits it per white area
        new File(outputPath + "\\Azathoth\\").mkdirs();

        int parts = concatImage.getHeight() / num;
        int end = concatImage.getHeight() / num;
        boolean recheck = false;

        // Array of pixel heights to split
        ArrayList<Integer> cuts = new ArrayList<>();
        cuts.add(0);

        // Loops while the whole image isn't split yet
        while (end+2 < concatImage.getHeight()) {
            for (int x = 0; x < concatImage.getWidth(); x++) {
                int r = Color.WHITE.getRed();
                int g = Color.WHITE.getGreen();
                int b = Color.WHITE.getBlue();

                int c1 = concatImage.getRGB(x, end + 1);
                int r1 = (c1 & 0x00ff0000) >> 16;
                int g1 = (c1 & 0x0000ff00) >> 8;
                int b1 = c1 & 0x000000ff;

                int c2 = concatImage.getRGB(x, end);
                int r2 = (c2 & 0x00ff0000) >> 16;
                int g2 = (c2 & 0x0000ff00) >> 8;
                int b2 = c2 & 0x000000ff;


                // If the edge of first image is not white or edge of second image is not white
                // Then adds 10 pixels to the checked area and rechecks
                if ((r1 != r || g1 != g || b1 != b) || (r2 != r || g2 != g || b2 != b)) {
                    if (end + 1 > concatImage.getHeight()) {
                        end = concatImage.getHeight() - 1;
                        recheck = false; // Doesn't recheck if its at the bottom of the image
                    } else {
                        end += 10;
                        recheck = true;
                    }
                } else {
                    recheck = false;
                }
            }

            // If recheck is unnecessary, then adds the current height to the pixel height array
            // Then adds more pixels to the end variable to check after this loop
            if (!recheck) {
                cuts.add(end);
                if (end + parts > concatImage.getHeight()) {
                    end = concatImage.getHeight() - 1;
                } else {
                    end = end + parts;
                }
            }
        }
        // Sometimes, the last part of the image isn't rendered
        cuts.set(cuts.size() - 1, concatImage.getHeight());
        System.out.println(cuts.toString());

        // Creates the split images based off the image height array
        for (int i = 0; i < cuts.size() - 1; i++) {
            ImageIO.write(concatImage.getSubimage(0, cuts.get(i), concatImage.getWidth(), cuts.get(i + 1) - cuts.get(i)), "PNG",
                    new File(outputPath + "\\Azathoth\\" + nameField.getText() + (i+1) + ".png"));
        }

        // Finished message
        Alert a = new Alert(Alert.AlertType.CONFIRMATION);
        a.setContentText("Smart Stitch/Split Completed!");
        a.showAndWait();
    }
java
image
javafx
colors
bufferedimage
asked on Stack Overflow Oct 27, 2020 by Agramon

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0