Skew or Distort Image object in Java

前端 未结 2 1209
挽巷
挽巷 2021-01-22 17:33

Is it possible to skew or distort an Image object in Java? I \'pull\' one side of an image out, making it seem closer to me. (LIke 3D).

Any suggestions?

相关标签:
2条回答
  • 2021-01-22 17:34

    Yes. Lots of ways but I would start with the Advanced Imaging API. It provides a ton of advanced imaging functionality.

    But just to do the type of transform that you're talking about you might just need an Affine Transform. Sample results here for the previous link.

    0 讨论(0)
  • 2021-01-22 17:40

    You can also do this with JavaFX.

    The following example uses PerspectiveTransform and a bit of rotation on the BufferedImage.

    It turns this image

    Stack Overflow logo

    into this

    Stack Overflow logo distorted

    import javafx.application.Platform;
    import javafx.embed.swing.JFXPanel;
    import javafx.embed.swing.SwingFXUtils;
    import javafx.scene.SnapshotParameters;
    import javafx.scene.canvas.Canvas;
    import javafx.scene.canvas.GraphicsContext;
    import javafx.scene.effect.PerspectiveTransform;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    import javafx.scene.paint.Color;
    
    import javax.imageio.ImageIO;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.net.URL;
    import java.util.concurrent.CountDownLatch;
    
    /**
    * Distorts images using transformations.
    * <p>
    * Created by Matthias Braun on 2018-09-05.
    */
    public class Distortion {
    
        public static void main(String... args) throws IOException {
            URL imgUrl = new URL("https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a");
            BufferedImage img = ImageIO.read(imgUrl);
            BufferedImage distorted = distortImg(img);
    
            File newImgFile = new File(System.getenv("HOME") + "/distorted.png");
            System.out.println("Saving to: " + newImgFile);
            ImageIO.write(distorted, "png", newImgFile);
    
            // Since we started a JavaFX thread in distortImg we have to shut it down. Otherwise the JVM won't exit
            Platform.exit();
        }
    
        /**
        * Applies perspective transformations to a copy of this {@code image} and rotates it.
        * <p>
        * Since this method starts a JavaFX thread, it's important to call {@link Platform#exit()} at the end of
        * your application. Otherwise the thread will prevent the JVM from shutting down.
        *
        * @param image the image we want to distort
        * @return the distorted image
        */
        private static BufferedImage distortImg(BufferedImage image) {
            // Necessary to initialize the JavaFX platform and to avoid "IllegalStateException: Toolkit not initialized"
            new JFXPanel();
    
            // This array allows us to get the distorted image out of the runLater closure below
            final BufferedImage[] imageContainer = new BufferedImage[1];
    
            // We use this latch to await the end of the JavaFX thread. Otherwise this method would finish before
            // the thread creates the distorted image
            final CountDownLatch latch = new CountDownLatch(1);
    
            // To avoid "IllegalStateException: Not on FX application thread" we start a JavaFX thread
            Platform.runLater(() -> {
                int width = image.getWidth();
                int height = image.getHeight();
                Canvas canvas = new Canvas(width, height);
                GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
                ImageView imageView = new ImageView(SwingFXUtils.toFXImage(image, null));
    
                PerspectiveTransform trans = new PerspectiveTransform();
                trans.setUlx(0);
                trans.setUly(height / 4);
                trans.setUrx(width);
                trans.setUry(0);
                trans.setLrx(width);
                trans.setLry(height);
                trans.setLlx(0);
                trans.setLly(height - height / 2);
    
                imageView.setEffect(trans);
    
                imageView.setRotate(2);
    
                SnapshotParameters params = new SnapshotParameters();
                params.setFill(Color.TRANSPARENT);
    
                Image newImage = imageView.snapshot(params, null);
                graphicsContext.drawImage(newImage, 0, 0);
    
                imageContainer[0] = SwingFXUtils.fromFXImage(newImage, image);
                // Work is done, we decrement the latch which we used for awaiting the end of this thread
                latch.countDown();
            });
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return imageContainer[0];
        }
    }
    
    0 讨论(0)
提交回复
热议问题