Java - BufferedImage 到 int[] 像素似乎已损坏
Java - BufferedImage to int[] pixels seems corrupted
我一直在尝试为每个像素使用 int
数组来显示图像 (BufferedImage
),但每次我将数组作为参数传递时,结果都是损坏的 image.The图片没有 alpha
或 transparent
像素。
SpriteSheet Class
public class SpriteSheet {
public int width;
public int height;
public int[] pixels;
BufferedImage image;
public SpriteSheet(String path) {
image = null;
try {
image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path));
} catch (IOException ex) {
Logger.getLogger(SpriteSheet.class.getName()).log(Level.SEVERE, null, ex);
}
if (image == null) {
return;
}
this.width = image.getWidth();
this.height = image.getHeight();
pixels = image.getRGB(0, 0, width, height, null, 0, width);
}
}
显示Class
public class Display {
private GameWindow displayWin;
private BufferedImage displayImage;
public int[] imagePixels;
private BufferStrategy graphBuffer;
private SpriteSheet sheet;
private int width;
private int height;
public Display(int width,int height,GameWindow win,SpriteSheet sheet) {
this.displayImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
this.imagePixels = ((DataBufferInt) this.displayImage.getRaster().getDataBuffer()).getData();
this.sheet=sheet;
this.width=width;
this.height=height;
this.displayWin = win;
this.displayWin.createBufferStrategy(3);
this.graphBuffer= displayWin.getBufferStrategy();
}
public void renderFinal(){
Level test = new Level(this.sheet, 1);
test.render(this);
Graphics g = graphBuffer.getDrawGraphics();
g.drawRect(0, 0, width, height);
g.drawImage(this.displayImage,0, 0,this.displayImage.getWidth(),this.displayImage.getHeight(), null);
g.dispose();
graphBuffer.show();
}
public int getWidth(){
return this.width;
}
public int getHeight(){
return this.height;
}
}
等级Class
public class Level {
private SpriteSheet levelSheet;
private int level;
public Level(SpriteSheet levelSheet,int newLevel) {
this.levelSheet = levelSheet;
this.level=newLevel;
}
public void render(Display displayLevel){
if(this.level == 1){
for (int y = 8; y <280; y++) {
for (int x=0; x < 230; x++) {
displayLevel.imagePixels[x+y*displayLevel.getWidth()]
= this.levelSheet.pixels[x+y*displayLevel.getWidth()];
}
}
}
}
}
例如,我想将图像从 0 剪切到 230,从 8 剪切到 280。这似乎是您正在尝试执行的操作。将一个图像部分剪切成另一个图像。图片大小不同,因此在传输时必须考虑宽度,如您所见,wcxhc 为 500x500
我使用以下
public void test() {
String image=".............";
BufferedImage bim=null;
try {
bim=ImageIO.read(new File(image));
}
catch (Exception ex) { System.out.println("error in b "+ex); }
int wc=bim.getWidth(), hc=bim.getHeight();
int[] pix2=bim.getRGB(0, 0, wc, hc, null, 0, wc);
int[] pix=new int[500*500];
for (int y = 8; y <280; y++) {
for (int x=0; x < 230; x++) {
pix[x+y*500]
= pix2[x+y*wc];
}
}
BufferedImage bm=new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
bm.setRGB(0, 0, 500, 500, pix, 0, 500);
}
}
您必须小心图像编码:颜色或灰度级。
使用 BufferedImage,您有两个 "good" 解决方案来访问像素。 getRGB() 很简单,但要慢得多。
1 - 使用光栅更容易,因为它会自动处理编码,但速度较慢。
WritableRaster r = image.getRaster() ;
for (int y=0, nb=0 ; y < image.getHeight() ; y++)
for (int x=0 ; x < image.getWidth() ; x++, nb++)
pixels[nb] = r.getSample(x, y, 0) ; // For a gray level image.
2 - 使用 DataBuffer,速度最快,因为直接访问像素,但您必须处理编码。
switch ( image.getType() )
{
case BufferedImage.TYPE_BYTE_GRAY : // Classical gray level images.
byte[] bb = ((DataBufferByte)image.getRaster().getDataBuffer()).getData() ;
for (int i=0 ; i < bb.length ; i++)
pixels[i] = bb[i] & 0xFF ;
break ;
}
我一直在尝试为每个像素使用 int
数组来显示图像 (BufferedImage
),但每次我将数组作为参数传递时,结果都是损坏的 image.The图片没有 alpha
或 transparent
像素。
SpriteSheet Class
public class SpriteSheet {
public int width;
public int height;
public int[] pixels;
BufferedImage image;
public SpriteSheet(String path) {
image = null;
try {
image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path));
} catch (IOException ex) {
Logger.getLogger(SpriteSheet.class.getName()).log(Level.SEVERE, null, ex);
}
if (image == null) {
return;
}
this.width = image.getWidth();
this.height = image.getHeight();
pixels = image.getRGB(0, 0, width, height, null, 0, width);
}
}
显示Class
public class Display {
private GameWindow displayWin;
private BufferedImage displayImage;
public int[] imagePixels;
private BufferStrategy graphBuffer;
private SpriteSheet sheet;
private int width;
private int height;
public Display(int width,int height,GameWindow win,SpriteSheet sheet) {
this.displayImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
this.imagePixels = ((DataBufferInt) this.displayImage.getRaster().getDataBuffer()).getData();
this.sheet=sheet;
this.width=width;
this.height=height;
this.displayWin = win;
this.displayWin.createBufferStrategy(3);
this.graphBuffer= displayWin.getBufferStrategy();
}
public void renderFinal(){
Level test = new Level(this.sheet, 1);
test.render(this);
Graphics g = graphBuffer.getDrawGraphics();
g.drawRect(0, 0, width, height);
g.drawImage(this.displayImage,0, 0,this.displayImage.getWidth(),this.displayImage.getHeight(), null);
g.dispose();
graphBuffer.show();
}
public int getWidth(){
return this.width;
}
public int getHeight(){
return this.height;
}
}
等级Class
public class Level {
private SpriteSheet levelSheet;
private int level;
public Level(SpriteSheet levelSheet,int newLevel) {
this.levelSheet = levelSheet;
this.level=newLevel;
}
public void render(Display displayLevel){
if(this.level == 1){
for (int y = 8; y <280; y++) {
for (int x=0; x < 230; x++) {
displayLevel.imagePixels[x+y*displayLevel.getWidth()]
= this.levelSheet.pixels[x+y*displayLevel.getWidth()];
}
}
}
}
}
例如,我想将图像从 0 剪切到 230,从 8 剪切到 280。这似乎是您正在尝试执行的操作。将一个图像部分剪切成另一个图像。图片大小不同,因此在传输时必须考虑宽度,如您所见,wcxhc 为 500x500
我使用以下
public void test() {
String image=".............";
BufferedImage bim=null;
try {
bim=ImageIO.read(new File(image));
}
catch (Exception ex) { System.out.println("error in b "+ex); }
int wc=bim.getWidth(), hc=bim.getHeight();
int[] pix2=bim.getRGB(0, 0, wc, hc, null, 0, wc);
int[] pix=new int[500*500];
for (int y = 8; y <280; y++) {
for (int x=0; x < 230; x++) {
pix[x+y*500]
= pix2[x+y*wc];
}
}
BufferedImage bm=new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
bm.setRGB(0, 0, 500, 500, pix, 0, 500);
}
}
您必须小心图像编码:颜色或灰度级。
使用 BufferedImage,您有两个 "good" 解决方案来访问像素。 getRGB() 很简单,但要慢得多。
1 - 使用光栅更容易,因为它会自动处理编码,但速度较慢。
WritableRaster r = image.getRaster() ;
for (int y=0, nb=0 ; y < image.getHeight() ; y++)
for (int x=0 ; x < image.getWidth() ; x++, nb++)
pixels[nb] = r.getSample(x, y, 0) ; // For a gray level image.
2 - 使用 DataBuffer,速度最快,因为直接访问像素,但您必须处理编码。
switch ( image.getType() )
{
case BufferedImage.TYPE_BYTE_GRAY : // Classical gray level images.
byte[] bb = ((DataBufferByte)image.getRaster().getDataBuffer()).getData() ;
for (int i=0 ; i < bb.length ; i++)
pixels[i] = bb[i] & 0xFF ;
break ;
}