缓冲的图像像素处理
问题描述:
我有这样的代码:缓冲的图像像素处理
public Image toNegative()
{
int imageWidth = originalImage.getWidth();
int imageHeight = originalImage.getHeight();
int [] rgb = null; // new int[imageWidth * imageWidth];
originalImage.getRGB(0, 0, imageWidth, imageHeight, rgb, 0,imageWidth);
for (int y = 0; y < imageHeight; y++)
{
for (int x = 0; x < imageWidth; x++)
{
int index = y * imageWidth + x;
int R = (rgb[index] >> 16) & 0xff; //bitwise shifting
int G = (rgb[index] >> 8) & 0xff;
int B = rgb[index] & 0xff;
R = 255 - R;
G = 255 - R;
B = 255 - R;
rgb[index] = 0xff000000 | (R << 16) | (G << 8) | B;
}
}
return getImageFromArray(rgb, imageWidth, imageHeight);
}
它将引发NPE或使用或ArrayOutOfBoundsException阵列时,当我传递之前的getRGB分配阵列。我检查调试器和图像的大小和分配。
UPDATE: 的的getRGB
/**
* Returns an array of integer pixels in the default RGB color model
* (TYPE_INT_ARGB) and default sRGB color space,
* from a portion of the image data. Color conversion takes
* place if the default model does not match the image
* <code>ColorModel</code>. There are only 8-bits of precision for
* each color component in the returned data when
* using this method. With a specified coordinate (x, y) in the
* image, the ARGB pixel can be accessed in this way:
* </p>
*
* <pre>
* pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)]; </pre>
*
* <p>
*
* An <code>ArrayOutOfBoundsException</code> may be thrown
* if the region is not in bounds.
* However, explicit bounds checking is not guaranteed.
*
* @param startX the starting X coordinate
* @param startY the starting Y coordinate
* @param w width of region
* @param h height of region
* @param rgbArray if not <code>null</code>, the rgb pixels are
* written here
* @param offset offset into the <code>rgbArray</code>
* @param scansize scanline stride for the <code>rgbArray</code>
* @return array of RGB pixels.
* @see #setRGB(int, int, int)
* @see #setRGB(int, int, int, int, int[], int, int)
*/
public int[] getRGB(int startX, int startY, int w, int h,
int[] rgbArray, int offset, int scansize) {
int yoff = offset;
int off;
Object data;
int nbands = raster.getNumBands();
int dataType = raster.getDataBuffer().getDataType();
switch (dataType) {
case DataBuffer.TYPE_BYTE:
data = new byte[nbands];
break;
case DataBuffer.TYPE_USHORT:
data = new short[nbands];
break;
case DataBuffer.TYPE_INT:
data = new int[nbands];
break;
case DataBuffer.TYPE_FLOAT:
data = new float[nbands];
break;
case DataBuffer.TYPE_DOUBLE:
data = new double[nbands];
break;
default:
throw new IllegalArgumentException("Unknown data buffer type: "+
dataType);
}
if (rgbArray == null) {
rgbArray = new int[offset+h*scansize];
}
for (int y = startY; y < startY+h; y++, yoff+=scansize) {
off = yoff;
for (int x = startX; x < startX+w; x++) {
rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x,
y,
data));
}
}
return rgbArray;
}
答
您的代码会抛出一个NullPointerException
因为你从来没有指派一个非空参照rgb
变量。因此,对其的引用(例如rgb[index]
)将产生异常。如果你想传递一个null数组到getRGB,你需要确保你分配了方法返回的结果数组;例如
int[] rgb = originalImage.getRGB(0, 0, imageWidth, imageHeight, rgb, 0,imageWidth);
如果要取消注释代码注释掉存在这样的错误你是分配数组作为imageWidth * imageWidth
,而不是imageWidth * imageHeight
,这就是为什么你看到的ArrayIndexOutOfBoundsException
。
答
有两个问题:
数组的宽度不是图像的宽度,但“扫描尺寸”(一些图像尺寸得到额外的像素填充)
如果您使用
null
数组调用getRGB()
,该方法将创建一个数组,但它不会更改rgb
引用 - Java不支持“out参数”。
为了使这项工作,使用
rgb = originalImage.getRGB(0, 0, imageWidth, imageHeight, null, 0,imageWidth);
都能跟得上。里面的getRGB是if(rgbArray == null){rgbArray = new int [offset + h * scansize]; }至少有哪些NetBeans显示 –
getRGB可能会执行空检查(我没有看过),但是您仍尝试在代码中进一步索引到null数组中,这就是为什么您会看到NullPointerException。如果你想传入一个空数组,你需要将getRGB的结果赋给你的rgb引用,以避免NPE(参见我的编辑)。 – Adamski
啊它被扔到别的地方了 –