Image processing 使用PixelWriter/Reader滚动图像

Image processing 使用PixelWriter/Reader滚动图像,image-processing,javafx,Image Processing,Javafx,我正在尝试创建一个滚动图像,它环绕着画布跟随自己的尾巴。我一直在尝试使用像素书写器和读取器来保存从屏幕向西滚动的垂直像素线,并将其附加到新图像中,该图像应在屏幕的右侧(东部)生长 它会滚动,但就是这样。我不明白如何计算扫描线,因此对此部分表示歉意 谢谢你的帮助 package controller; import javafx.animation.AnimationTimer; import javafx.scene.canvas.Canvas; import javafx.scene.can

我正在尝试创建一个滚动图像,它环绕着画布跟随自己的尾巴。我一直在尝试使用像素书写器和读取器来保存从屏幕向西滚动的垂直像素线,并将其附加到新图像中,该图像应在屏幕的右侧(东部)生长

它会滚动,但就是这样。我不明白如何计算扫描线,因此对此部分表示歉意

谢谢你的帮助

package controller;

import javafx.animation.AnimationTimer;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import util.GraphicsUtils;

import java.io.File;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.nio.file.Paths;

class ImageContainer extends HBox {
int w, h;
int translatedAmount = 0;
Image image;
Canvas canvas;
long startNanoTime = System.nanoTime();
WritableImage eastImage = null;

public ImageContainer() {
    setVisible(true);
    load();
    w = (int) image.getWidth();
    h = (int) image.getHeight();
    canvas = new Canvas(w, h);
    int edgeX = (int) canvas.getWidth(); //You can set this a little west for visibility sake...whilst debugging
    getChildren().addAll(canvas);
    GraphicsContext gc = canvas.getGraphicsContext2D();
    canvas.setVisible(true);
    gc.drawImage(image, 0, 0, w, h);
    setPrefSize(w, h);
    eastImage = new WritableImage(translatedAmount+1, h); //create a new eastImage

    new AnimationTimer() {
        public void handle(long currentNanoTime) {
            if (((System.nanoTime() - startNanoTime) / 1000000000.0) < 0.05) {
                return;
            } else {
                startNanoTime = System.nanoTime();
            }

            translatedAmount++;

            Image westLine = getSubImageRectangle(image, 1, 0, 1, h); //get a 1 pixel strip from west of main image
            PixelReader westLinepixelReader = westLine.getPixelReader(); //create a pixel reader for this image
            byte[] westLinePixelBuffer = new byte[1 * h * 4]; //create a buffer to store the pixels collected from the about to vanish westLine
            westLinepixelReader.getPixels(0, 0, 1, h, PixelFormat.getByteBgraInstance(), westLinePixelBuffer, 0, 4); //collect the pixels from westLine strip

            Image tempImg = eastImage; //save away the current east side image

            byte[] tempBuffer = new byte[(int)tempImg.getWidth() * h * 4];
            PixelReader tempImagePixelReader = tempImg.getPixelReader(); //create a pixel reader for our temp copy of the east side image
            tempImagePixelReader.getPixels(0, 0, (int)tempImg.getWidth(), h, PixelFormat.getByteBgraInstance(), tempBuffer, 0, 4); //save the tempImage into the tempBuffer

            eastImage = new WritableImage(translatedAmount+1, h); //create a new eastImage, but one size larger
            PixelWriter eastImagePixelWriter = eastImage.getPixelWriter(); //create a pixel writer for this new east side image
            eastImagePixelWriter.setPixels(1, 0, (int)tempImg.getWidth(), h, PixelFormat.getByteBgraInstance(), tempBuffer, 0, 4); //copy the temp image in at x=1
            eastImagePixelWriter.setPixels((int)tempImg.getWidth(), 0, 1, h, PixelFormat.getByteBgraInstance(), westLinePixelBuffer, 0, 4); //copy the westLine at x=tempImg.width

            image = getSubImageRectangle(image, 1, 0, (int) image.getWidth() - 1, h);
            gc.drawImage(image, 0, 0); //draw main image
            System.out.println(edgeX-eastImage.getWidth());
            gc.drawImage(eastImage, edgeX-eastImage.getWidth(), 0); //add lost image lines
        }
    }.start();
}

public void load() {
    Path imagePath = Paths.get("./src/main/resources/ribbonImages/clouds.png");
    File f = imagePath.toFile();
    assert f.exists();
    image = new Image(f.toURI().toString());
}

public Image getSubImageRectangle(Image image, int x, int y, int w, int h) {
    PixelReader pixelReader = image.getPixelReader();
    WritableImage newImage = new WritableImage(pixelReader, x, y, w, h);
    ImageView imageView = new ImageView();
    imageView.setImage(newImage);
    return newImage;
}
}
包装控制器;
导入javafx.animation.AnimationTimer;
导入javafx.scene.canvas.canvas;
导入javafx.scene.canvas.GraphicsContext;
导入javafx.scene.image.*;
导入javafx.scene.layout.*;
导入util.GraphicsUtils;
导入java.io.File;
导入java.nio.ByteBuffer;
导入java.nio.file.Path;
导入java.nio.file.path;
类ImageContainer扩展了HBox{
int w,h;
int translatedAmount=0;
图像;
帆布;
long startNanoTime=System.nanoTime();
WritableImage eastImage=null;
公共图像容器(){
setVisible(真);
加载();
w=(int)image.getWidth();
h=(int)image.getHeight();
画布=新画布(w,h);
int-edgeX=(int)canvas.getWidth();//为了可见性,您可以在调试时将其设置为稍微向西一点
getChildren().addAll(画布);
GraphicsContext gc=canvas.getGraphicsContext2D();
canvas.setVisible(true);
绘制图像(图像,0,0,w,h);
setPrefSize(w,h);
eastImage=新的可写映像(translatedAmount+1,h);//创建新的eastImage
新的AnimationTimer(){
公共无效句柄(长currentnotime){
如果(((System.nanoTime()-startNanoTime)/100000000.0)<0.05){
返回;
}否则{
startNanoTime=System.nanoTime();
}
translatedAmount++;
Image westLine=getSubImageRectangle(Image,1,0,1,h);//从主图像的西部获取一个1像素的条带
PixelReader westLinepixelReader=westLine.getPixelReader();//为此图像创建像素读取器
byte[]westLinePixelBuffer=新字节[1*h*4];//创建一个缓冲区来存储从即将消失的westLine收集的像素
westLinepixelReader.getPixels(0,0,1,h,PixelFormat.getByteBgraInstance(),westLinePixelBuffer,0,4);//从WestlineStrip收集像素
Image tempImg=eastImage;//保存当前的东侧图像
byte[]tempBuffer=新字节[(int)tempImg.getWidth()*h*4];
PixelReader tempImagePixelReader=tempImg.getPixelReader();//为东区图像的临时副本创建一个像素读取器
tempImagePixelReader.getPixels(0,0,(int)tempImg.getWidth(),h,PixelFormat.getByteBgraInstance(),tempBuffer,0,4);//将tempImage保存到tempBuffer中
eastImage=new WritableImage(translatedAmount+1,h);//创建一个新的eastImage,但大小要大一点
PixelWriter eastImagePixelWriter=eastImage.getPixelWriter();//为新的东区图像创建像素写入器
eastImagePixelWriter.setPixels(1,0,(int)tempImg.getWidth(),h,PixelFormat.getByteBgraInstance(),tempBuffer,0,4);//在x=1时复制临时图像
eastImagePixelWriter.setPixels((int)tempImg.getWidth(),0,1,h,PixelFormat.getByteBgraInstance(),westLinePixelBuffer,0,4);//在x=tempImg.width处复制西线
image=getSubImageRectangle(image,1,0,(int)image.getWidth()-1,h);
gc.drawImage(image,0,0);//绘制主图像
System.out.println(edgeX eastImage.getWidth());
gc.drawImage(eastImage,edgeX eastImage.getWidth(),0);//添加丢失的图像行
}
}.start();
}
公共空荷载(){
Path imagePath=Path.get(“./src/main/resources/ribbonImages/clouds.png”);
文件f=imagePath.toFile();
断言f.exists();
图像=新图像(f.toURI().toString());
}
公共图像getSubImageRectangle(图像图像,整数x,整数y,整数w,整数h){
PixelReader PixelReader=image.getPixelReader();
WritableImage newImage=新的WritableImage(像素阅读器,x,y,w,h);
ImageView ImageView=新的ImageView();
setImage(newImage);
返回新图像;
}
}

为什么要让这变得比必要的更困难?只需在
画布上绘制图像两次:

public static void drawImage(Canvas canvas, Image sourceImage, double offset, double wrapWidth) {
    GraphicsContext gc = canvas.getGraphicsContext2D();
    gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());

    // make |offset| < wrapWidth
    offset %= wrapWidth;
    if (offset < 0) {
        // make sure positive offsets do not result in the previous version
        // of the image not being drawn
        offset += wrapWidth;
    }
    gc.drawImage(sourceImage, -offset, 0);
    gc.drawImage(sourceImage, wrapWidth - offset, 0);
}

@Override
public void start(Stage primaryStage) {
    Image image = new Image("https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/402px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg");
    Canvas canvas = new Canvas(image.getWidth(), image.getHeight());
    primaryStage.setResizable(false);

    Scene scene = new Scene(new Group(canvas));

    DoubleProperty offset = new SimpleDoubleProperty();
    offset.addListener((observable, oldOffset, newOffset) -> drawImage(canvas, image, newOffset.doubleValue(), canvas.getWidth()));
    Timeline timeline = new Timeline(
            new KeyFrame(Duration.ZERO, new KeyValue(offset, 0, Interpolator.LINEAR)),
            new KeyFrame(Duration.seconds(10), new KeyValue(offset, image.getWidth()*2, Interpolator.LINEAR))
    );
    timeline.setCycleCount(Animation.INDEFINITE);
    timeline.play();

    primaryStage.setScene(scene);
    primaryStage.sizeToScene();
    primaryStage.show();
}
publicstaticvoiddrawimage(画布、图像源图像、双偏移、双宽度){
GraphicsContext gc=canvas.getGraphicsContext2D();
gc.clearRect(0,0,canvas.getWidth(),canvas.getHeight());
//使|偏移|drawImage(canvas,image,newOffset.doubleValue(),canvas.getWidth());
时间线=新时间线(
新关键帧(Duration.ZERO,新关键帧值(offset,0,Interpolator.LINEAR)),
新关键帧(持续时间.秒(10),新关键值(偏移,image.getWidth()*2,插值器.LINEAR))
);
timeline.setCycleCount(Animation.unfinite);
timeline.play();
初级阶段。场景(场景);
primaryStage.sizeToScene();
primaryStage.show();
}

谢谢你的回答,等我找到后再试试