How to rotate JPEG images based on the orientation metadata?

后端 未结 8 1725
轻奢々
轻奢々 2020-11-27 12:30

I have some server code that is generating thumbnails when an image is uploaded. The issue is that when the image was taken and the camera/device was rotated, the thumbnail

相关标签:
8条回答
  • 2020-11-27 13:19

    Based on the answers of Antoine Martin I created an own class for correcting the orientation of a given jpeg image (in my case as an input stream) based on the exif information of the image. With his solution I had the problem, that the colors of the resulting image were wrong, therefore I created this one. For retrieving the metadata of the image I used the metadata-extractor library.

    I hope it will help some people.

    public class ImageOrientationUtil {
    
    /**
     * Checks the orientation of the image and corrects it if necessary.
     * <p>If the orientation of the image does not need to be corrected, no operation will be performed.</p>
     * @param inputStream
     * @return
     * @throws ImageProcessingException
     * @throws IOException
     * @throws MetadataException
     */
    public static BufferedImage correctOrientation(InputStream inputStream) throws ImageProcessingException, IOException, MetadataException {
        Metadata metadata = ImageMetadataReader.readMetadata(inputStream);
        if(metadata != null) {
            if(metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
                // Get the current orientation of the image
                Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
                int orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
    
                // Create a buffered image from the input stream
                BufferedImage bimg = ImageIO.read(inputStream);
    
    
                // Get the current width and height of the image
                int[] imageSize = {bimg.getWidth(), bimg.getHeight()};
                int width = imageSize[0];
                int height = imageSize[1];
    
                // Determine which correction is needed
                AffineTransform t = new AffineTransform();
                switch(orientation) {
                case 1:
                    // no correction necessary skip and return the image
                    return bimg;
                case 2: // Flip X
                    t.scale(-1.0, 1.0);
                    t.translate(-width, 0);
                    return transform(bimg, t);
                case 3: // PI rotation 
                    t.translate(width, height);
                    t.rotate(Math.PI);
                    return transform(bimg, t);
                case 4: // Flip Y
                    t.scale(1.0, -1.0);
                    t.translate(0, -height);
                    return transform(bimg, t);
                case 5: // - PI/2 and Flip X
                    t.rotate(-Math.PI / 2);
                    t.scale(-1.0, 1.0);
                    return transform(bimg, t);
                case 6: // -PI/2 and -width
                    t.translate(height, 0);
                    t.rotate(Math.PI / 2);
                    return transform(bimg, t);
                case 7: // PI/2 and Flip
                    t.scale(-1.0, 1.0);
                    t.translate(height, 0);
                    t.translate(0, width);
                    t.rotate(  3 * Math.PI / 2);
                    return transform(bimg, t);
                case 8: // PI / 2
                    t.translate(0, width);
                    t.rotate(  3 * Math.PI / 2);
                    return transform(bimg, t);
                }
            }
        }
    
        return null;
    }
    
    /**
     * Performs the tranformation
     * @param bimage
     * @param transform
     * @return
     * @throws IOException
     */
    private static BufferedImage transform(BufferedImage bimage, AffineTransform transform) throws IOException {
        // Create an transformation operation
        AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BICUBIC);
    
        // Create an instance of the resulting image, with the same width, height and image type than the referenced one
        BufferedImage destinationImage = new BufferedImage( bimage.getWidth(), bimage.getHeight(), bimage.getType() );
        op.filter(bimage, destinationImage);
    
       return destinationImage;
    }
    }
    
    0 讨论(0)
  • 2020-11-27 13:21

    The Thumbnailator library honors EXIF orientation flags. To read an image at full size with correct orientation:

    BufferedImage image = Thumbnails.of(inputStream).scale(1).asBufferedImage();
    
    0 讨论(0)
提交回复
热议问题