用java将图像的像素复制到画布
编辑:我修改了一些代码,以反映AlamasB所说的内容。我仍然不明白应该如何填充字节数组,以及需要进行哪些转换 我试图操纵用户上传的图像的像素,并将新图像写入画布。现在我只是想复制原始图像,而不改变像素的RGB。我已经在同一个地方呆了很长时间,不知道下一步该去哪里。在代码的第一部分,我复制了用户上传的原始图像用java将图像的像素复制到画布,java,javafx,Java,Javafx,编辑:我修改了一些代码,以反映AlamasB所说的内容。我仍然不明白应该如何填充字节数组,以及需要进行哪些转换 我试图操纵用户上传的图像的像素,并将新图像写入画布。现在我只是想复制原始图像,而不改变像素的RGB。我已经在同一个地方呆了很长时间,不知道下一步该去哪里。在代码的第一部分,我复制了用户上传的原始图像 Image image = imageView.getImage(); PixelReader pixelReader = image.getPixelReader();
Image image = imageView.getImage();
PixelReader pixelReader = image.getPixelReader();
PixelFormat format = pixelReader.getPixelFormat();
int width= (int)image.getWidth();
int height = (int) image.getHeight();
GraphicsContext gc = canvas.getGraphicsContext2D();
PixelWriter pw = gc.getPixelWriter();
byte[] imageData = new byte[width * height * 4];
imageData = createImageData(imageData, pixelReader, width, height);
//..
//...the next function populates my byte array with what's in the image
public byte[] createImageData(byte[] imageData, PixelReader pr, int width, int height){
int i = 0;
for(int y=0; y<height; y++){
for(int x = 0; x < width; x++){
int argb = pixelReader.getArgb(x, y);
imageData[i] = (byte) argb;
imageData[i+1] = (byte) argb;
imageData[i+2] = (byte) argb;
i+=3;
pw.setArgb(x, y, argb);
}
}
return imageData;
}
Image=imageView.getImage();
PixelReader PixelReader=image.getPixelReader();
PixelFormat=pixelReader.getPixelFormat();
int width=(int)image.getWidth();
int height=(int)image.getHeight();
GraphicsContext gc=canvas.getGraphicsContext2D();
PixelWriter pw=gc.getPixelWriter();
字节[]图像数据=新字节[宽度*高度*4];
imageData=createImageData(imageData、pixelReader、宽度、高度);
//..
//…下一个函数用图像中的内容填充我的字节数组
公共字节[]createImageData(字节[]imageData,像素阅读器pr,整数宽度,整数高度){
int i=0;
对于(int y=0;y考虑到PixelReader
在这种情况下提供的最佳选择可能是使用32位表示法。随后将其转换为4字节数组,即宽度*高度*4
。最后用于绘制图像
int argb = pixelReader.getArgb(x, y);
// populate imageData[i,i+1,i+2,i+3] by converting argb
...
// convert imageData[i,i+1,i+2,i+3] into a 32bit argb, say int argb2
pixelWriter.setArgb(x, y, argb2);
或者,您可以使用颜色的getOpacity()
从RGBA
获取A
。同样,使用32位表示法
至少这将为您提供一个最小的工作示例,然后您可以对其进行扩展
下面是一个快速版本(自包含,只需复制和粘贴):
导入javafx.application.application;
导入javafx.scene.Parent;
导入javafx.scene.scene;
导入javafx.scene.image.*;
导入javafx.scene.layout.HBox;
导入javafx.scene.paint.Color;
导入javafx.stage.stage;
导入java.nio.ByteBuffer;
导入java.util.array;
公共类ImageOperationApp扩展了应用程序{
专用静态最终int APP_W=800;
专用静态最终int APP_H=600;
私有父createContent(){
Image Image=makeMockImage();
字节[]imageData=imageToData(图像);
字节[]modifiedImageData=修改(图像数据);
图像修改图像=数据到图像(修改图像数据);
HBox根=新的HBox(25);
root.getChildren().addAll(新图像视图(image)、新图像视图(modifiedImage));
返回根;
}
私有映像makeMockImage(){
WritableImage=新的WritableImage(应用程序W/2,应用程序H);
PixelWriter=image.getPixelWriter();
对于(int y=0;y
oracle方法示例不起作用或者您想了解它的工作原理,这也是一个很好的开始阅读的问题。您提供的方法不会创建图像的副本。我很高兴您链接到setPixels()方法,因为这让我很困惑。它说前两个参数是写入数据的x和y坐标。它是指画布的x和y,还是我需要知道相对于根对象的x和y位置?你指的是哪种方法?是我的创建方法还是绘制方法?这对我有所帮助,但我仍然感到困惑d、 您的示例中的argb2是什么?文档中说getArgb()和setArgb()都使用32位格式,因此需要进行哪种类型的转换。我也不知道如何填充imageData字节数组。如果您想查看您填充的示例,我更新了我的OPbyte[]
对于图像数据,我只是指出应该使用4个字节来表示像素,而不是3个。如果argb
是原始的未修改的像素数据,那么argb2
就是修改的像素数据。我所说的转换是指将32位值转换为4字节数组,因为您使用它作为中介
int argb = pixelReader.getArgb(x, y);
// populate imageData[i,i+1,i+2,i+3] by converting argb
...
// convert imageData[i,i+1,i+2,i+3] into a 32bit argb, say int argb2
pixelWriter.setArgb(x, y, argb2);
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.*;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.nio.ByteBuffer;
import java.util.Arrays;
public class ImageManipulationApp extends Application {
private static final int APP_W = 800;
private static final int APP_H = 600;
private Parent createContent() {
Image image = makeMockImage();
byte[] imageData = imageToData(image);
byte[] modifiedImageData = modify(imageData);
Image modifiedImage = dataToImage(modifiedImageData);
HBox root = new HBox(25);
root.getChildren().addAll(new ImageView(image), new ImageView(modifiedImage));
return root;
}
private Image makeMockImage() {
WritableImage image = new WritableImage(APP_W / 2, APP_H);
PixelWriter writer = image.getPixelWriter();
for (int y = 0; y < APP_H; y++) {
for (int x = 0; x < APP_W / 2; x++) {
writer.setColor(x, y, Math.random() < 0.00005 ? Color.YELLOW : Color.BLACK);
}
}
return image;
}
/**
* Modifies the pixel data.
*
* @param data original image data
* @return modified image data
*/
private byte[] modify(byte[] data) {
// this is where changes happen
return data;
}
private byte[] imageToData(Image image) {
int width = (int) image.getWidth();
int height = (int) image.getHeight();
byte[] data = new byte[width * height * 4];
int i = 0;
for (int y = 0; y < height; y++){
for (int x = 0; x < width; x++){
int argb = image.getPixelReader().getArgb(x, y);
byte[] pixelData = ByteBuffer.allocate(4).putInt(argb).array();
data[i++] = pixelData[0];
data[i++] = pixelData[1];
data[i++] = pixelData[2];
data[i++] = pixelData[3];
}
}
return data;
}
private Image dataToImage(byte[] data) {
// if we don't know the image size beforehand we can encode width and height
// into image data too
WritableImage image = new WritableImage(APP_W / 2, APP_H);
PixelWriter writer = image.getPixelWriter();
int i = 0;
for (int y = 0; y < APP_H; y++) {
for (int x = 0; x < APP_W / 2; x++) {
int argb = ByteBuffer.wrap(Arrays.copyOfRange(data, i, i + 4)).getInt();
writer.setArgb(x, y, argb);
i += 4;
}
}
return image;
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}