如何用PixelReader与JavaFX提取子图?代码生成tile异常求助
问题分析与解决方法
嘿Paul,我一眼就看出问题出在哪啦!你创建tile的方式错了——new Image(ByteArrayInputStream)这个构造函数是用来加载编码后的标准图片文件(比如完整的PNG/JPEG字节流)的,但你传给它的是从PixelReader读取的原始BGRA像素数据,没有图片文件的头信息、压缩格式这些关键内容,JavaFX的图像解码器根本识别不了,所以才会返回一个宽高为0、没有PixelReader的无效图像。
要重建从原图像提取的像素区域,你应该用WritableImage——这是JavaFX专门用来直接操作像素数据的类,完美适配你的场景。这里有两种实现方式,都能解决你的问题:
方法一:直接复制像素(最简洁)
不需要手动维护buffer,直接让PixelWriter从源PixelReader复制像素:
// 加载原始大图(你的原有代码不变) Image image = new Image("file:ressources/spritesheets/Zelda_Overworld.png"); int tileWidth = 16; int tileHeight = 16; // 创建对应尺寸的可写图像 WritableImage tile = new WritableImage(tileWidth, tileHeight); PixelWriter tileWriter = tile.getPixelWriter(); PixelReader imageReader = image.getPixelReader(); // 从源图像的(0,0)位置复制16x16的像素到tile的(0,0)位置 tileWriter.setPixels(0, 0, tileWidth, tileHeight, imageReader, 0, 0);
方法二:使用自定义buffer(兼容你原有的buffer逻辑)
如果你想保留手动读取buffer的逻辑,也可以用PixelWriter把buffer里的像素写入WritableImage:
Image image = new Image("file:ressources/spritesheets/Zelda_Overworld.png"); int tileWidth = 16; int tileHeight = 16; // 计算所需buffer大小:16*16像素,每个BGRA像素占4字节,总共1024字节(你原来的buffer大小是对的) byte[] buffer = new byte[tileWidth * tileHeight * 4]; PixelReader pr = image.getPixelReader(); // 读取源图像的像素到buffer(注意最后一个参数是每行的字节数,16*4=64,你原来的这个参数是对的) pr.getPixels(0, 0, tileWidth, tileHeight, PixelFormat.getByteBgraInstance(), buffer, 0, 64); // 创建可写图像并写入buffer里的像素 WritableImage tile = new WritableImage(tileWidth, tileHeight); PixelWriter pw = tile.getPixelWriter(); pw.setPixels(0, 0, tileWidth, tileHeight, PixelFormat.getByteBgraInstance(), buffer, 0, tileWidth * 4);
补充说明:你原来的buffer数值是对的,但错在试图用原始像素数据直接构建Image——这个类只认标准图片格式的字节流,不认裸像素。而WritableImage就是为这种“手动操作像素”的场景设计的,用它就能得到正常显示的tile啦。
内容的提问来源于stack exchange,提问作者Paul Breugnot
相关产品推荐
相关产品推荐

