Объект Skew или Distort Image в Java

Можно ли исказить или исказить объект изображения в Java? Я «вытягиваю» одну сторону изображения, делая его ближе ко мне. (как 3D).

Какие-либо предложения?


person Hidde    schedule 09.09.2011    source источник
comment
возможный дубликат преобразования изображения Java   -  person trashgod    schedule 09.09.2011


Ответы (2)


да. Способов много, но я бы начал с API Advanced Imaging. Он предоставляет массу расширенных функций обработки изображений.

Но просто для того, чтобы выполнить преобразование, о котором вы говорите, вам может понадобиться Аффинное преобразование. Пример результатов здесь для предыдущей ссылки.

person Paul Sasik    schedule 09.09.2011
comment
Хороший совет по JAI, но я не думаю, что одного AffineTransform достаточно, как предложено здесь. - person trashgod; 09.09.2011
comment
Я тоже не уверен, что это правильное преобразование. Вот почему я добавил результат поиска изображений для подтверждения. - person Paul Sasik; 10.09.2011
comment
Возможно, PerspectiveTransform? - person trashgod; 10.09.2011
comment
Trashgod, PerspectiveTransform — это то, что мне было нужно. Мне нужна перспектива и прямота линий. Спасибо. - person Hidde; 13.09.2011

Вы также можете сделать это с помощью JavaFX.

В следующем примере используется PerspectiveTransform и небольшая ротация BufferedImage.

Это превращает этот образ

логотип переполнения стека

в это

Логотип переполнения стека искажен

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];
    }
}
person Matthias Braun    schedule 05.09.2018