scalaimgscalrtwelvemonkeys

Does TwelveMonkeys provide image crop functionality?


I'm trying to use the TwelveMonkeys Library to in image manipulation; but cannot find a method similar to the org.imgscalr.crop(BufferedImage src, int x, int y, int width, int height, BufferedImageOp... ops) which crop the input image according to the x, y, width, height params.


Solution

  • You don't need any special library to crop images in Java. Simply use plain Java2D and the BufferedImage.getSubimage(x, y, width, height) method:

    BufferedImage image = ...
    BufferedImage cropped = image.getSubimage(x, y, width, height);
    

    Note, however, the part in the JavaDoc that says:

    The returned BufferedImage shares the same data array as the original image.

    This means that any modification in one image will be reflected in the other. If you wish to avoid that, or be able to release the memory of the larger image, you can do something like this, to make a copy:

    ColorModel cm = cropped.getColorModel();
    BufferedImage copy = new BufferedImage(cm, cropped.getData(), cm.isAlphaPremultiplied(), null);
    

    The trick here is that BufferedImage.getData() creates a copy of the Raster.


    Alternatively, if you don't need the entire image at all, you can simply read the region of the image you want directly. This is a standard feature of the javax.imageio API, and is supported by the TwelveMonkeys plugins. Doing it this way, usually saves both time and memory:

    try (ImageInputStream input = ImageIO.createImageInputStream(file)) {
        ImageReader reader = ImageIO.getImageReaders(input).next(); // TODO: Handle no reader case
        reader.setInput(input);
    
        // Use reader.getNumImages(boolean) to get number of images in input if needed
        // Use reader.getWidth(int)/reader.getHeight(int) to get dimensions of image
    
        ImageReadParam param = reader.getDefaultReadParam();
        param.setSourceRegion(new Rectangle(x, y, width, height));
    
        BufferedImage image = reader.read(0, param); // Read first image
    }
    

    PS: My code samples are all Java as that is the "native language" of Java2D, but I'm sure you can easily convert it to Scala.