10

Is there a framework which is able to remove the white space (rectangular) of an image. We create Image Thumbnails from technical drawings which are unfortunately in PDF format. We convert the PDF to SVG and then to JPG. Often the technical drawings are very small and now placed in the upper left corner of the thumbnail:

+---------+----------------------+
|         |                      |
| (image) |                      |
|         |                      |
+---------+                      |
|                                |
|                                |
|                                |
|                                |
|              (empty space)     |
|                                |
|                                |
+--------------------------------+

So how can I easily remove the empty space and shrink the JPG file?

sehe
  • 374,641
  • 47
  • 450
  • 633
Christopher Klewes
  • 11,181
  • 18
  • 74
  • 102
  • I would have thought that was fairly easy to do yourself with a few loops to check whole rows/columns were the same colour. (Or the empty colour) – Peter Lawrey Sep 12 '11 at 09:24
  • 5
    BTW: converting line art to JPEG seems a bad choice. Why not use PNG? – Sean Patrick Floyd Sep 12 '11 at 09:29
  • 2
    Do the PDFs also include the whitespace or are the appropriately-sized for the content? If they are correctly sized, then you might want to check each step of your conversion pipeline if it's discarding some size information. – Joachim Sauer Sep 12 '11 at 09:36

3 Answers3

9

It can be done in JAI as is demonstrated in this thread. Or here's some Java code I just wrote which can be used to do it:

public class TrimWhite {
    private BufferedImage img;

    public TrimWhite(File input) {
        try {
            img = ImageIO.read(input);
        } catch (IOException e) {
            throw new RuntimeException( "Problem reading image", e );
        }
    }

    public void trim() {
        int width  = getTrimmedWidth();
        int height = getTrimmedHeight();

        BufferedImage newImg = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        Graphics g = newImg.createGraphics();
        g.drawImage( img, 0, 0, null );
        img = newImg;
    }

    public void write(File f) {
        try {
            ImageIO.write(img, "bmp", f);
        } catch (IOException e) {
            throw new RuntimeException( "Problem writing image", e );
        }
    }

    private int getTrimmedWidth() {
        int height       = this.img.getHeight();
        int width        = this.img.getWidth();
        int trimmedWidth = 0;

        for(int i = 0; i < height; i++) {
            for(int j = width - 1; j >= 0; j--) {
                if(img.getRGB(j, i) != Color.WHITE.getRGB() &&
                        j > trimmedWidth) {
                    trimmedWidth = j;
                    break;
                }
            }
        }

        return trimmedWidth;
    }

    private int getTrimmedHeight() {
        int width         = this.img.getWidth();
        int height        = this.img.getHeight();
        int trimmedHeight = 0;

        for(int i = 0; i < width; i++) {
            for(int j = height - 1; j >= 0; j--) {
                if(img.getRGB(i, j) != Color.WHITE.getRGB() &&
                        j > trimmedHeight) {
                    trimmedHeight = j;
                    break;
                }
            }
        }

        return trimmedHeight;
    }

    public static void main(String[] args) {
        TrimWhite trim = new TrimWhite(new File("...\\someInput.bmp"));
        trim.trim();
        trim.write(new File("...\\someOutput.bmp"));
    }
}
Mike Kwan
  • 24,123
  • 12
  • 63
  • 96
8

For Android users, here is an example using Mike Kwan Answer:

    public static Bitmap TrimImage(Bitmap bmp) {
    int imgHeight = bmp.getHeight();
    int imgWidth  = bmp.getWidth();

    //TRIM WIDTH
    int widthStart  = imgWidth;
    int widthEnd = 0;
    for(int i = 0; i < imgHeight; i++) {
        for(int j = imgWidth - 1; j >= 0; j--) {
            if(bmp.getPixel(j, i) != Color.TRANSPARENT &&
                    j < widthStart) {
                widthStart = j;
            }
            if(bmp.getPixel(j, i) != Color.TRANSPARENT &&
                    j > widthEnd) {
                widthEnd = j;
                break;
            }
        }
    }
    //TRIM HEIGHT
    int heightStart = imgHeight;
    int heightEnd = 0;
    for(int i = 0; i < imgWidth; i++) {
        for(int j = imgHeight - 1; j >= 0; j--) {
            if(bmp.getPixel(i, j) != Color.TRANSPARENT &&
                    j < heightStart) {
                heightStart = j;
            }
            if(bmp.getPixel(i, j) != Color.TRANSPARENT &&
                    j > heightEnd) {
                heightEnd = j;
                break;
            }
        }
    }

    int finalWidth = widthEnd - widthStart;
    int finalHeight = heightEnd - heightStart;

    return Bitmap.createBitmap(bmp, widthStart,heightStart,finalWidth, finalHeight);
}

Hope this help someone :)

EDIT:

Guys, I just updated my answer cuz last code was just trimming the end of the image, not the beginning. This one is working just great :)

JannGabriel
  • 302
  • 5
  • 14
0

This is the fastest.

public static Bitmap TrimBitmap(Bitmap bmp) {
    final int imgHeight = bmp.getHeight();
    final int imgWidth  = bmp.getWidth();

    //Take Data
    int[] pixels = new int[imgWidth * imgHeight];
    bmp.getPixels(pixels, 0, imgWidth, 0, 0, imgWidth, imgHeight);
    int[] horizontalData=new int[imgHeight],verticalData=new int[imgWidth];
    int num=0;
    for (int pixel:pixels){
        horizontalData[num/imgWidth]|=pixel;
        verticalData[num%imgWidth]|=pixel;
        num++;
    }


    


    //TRIM WIDTH - RIGHT
    int endWidth  = imgWidth;
    for(int x = imgWidth - 1; x >= 0; x--) {
        int data = verticalData[x];
        if ((data>>24)!=0)
            break;
        endWidth--;
    }



    


    //TRIM HEIGHT - BOTTOM
    int endHeight = imgHeight;
    for(int x = imgHeight - 1; x >= 0; x--) {
        int data =horizontalData[x];
        if ((data>>24)!=0)
            break;
        endHeight--;
    }


    return Bitmap.createBitmap(
            bmp,
            0,
            0,
            endWidth,
            endHeight
    );

}
rayray
  • 1
  • 1