Buffered image pixel manipulation

匿名 (未验证) 提交于 2019-12-03 02:33:02

问题:

I have this code:

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); } 

It throws NPE or when array is used or ArrayOutOfBoundsException when I allocate array before passing it getRGB. I check in debugger and image has the size and is allocated.

UPDATE: The 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,&nbsp;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; } 

回答1:

Your code will throw a NullPointerException because you are never assigning a non-null reference to the rgb variable. Hence, references to it (e.g. rgb[index]) will generate the exception. If you wish to pass in a null array to getRGB you need to ensure you assign the result array returned by the method; e.g.

int[] rgb = originalImage.getRGB(0, 0, imageWidth, imageHeight, rgb, 0,imageWidth); 

If you were to uncomment the code commented out there is a bug in that you are allocating the array as imageWidth * imageWidth instead of imageWidth * imageHeight, which is why you're seeing an ArrayIndexOutOfBoundsException.



回答2:

There are two problems:

  1. The width of the array is not the width of the image but the "scan size" (some image sizes get padded with extra pixels)

  2. If you call getRGB() with a null array, the method will create an array but it won't change the rgb reference - Java doesn't support "out parameters".

To make this work, use

rgb = originalImage.getRGB(0, 0, imageWidth, imageHeight, null, 0,imageWidth); 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!