缓冲图像像素操作

发布于 2024-12-09 11:43:00 字数 3729 浏览 0 评论 0原文

我有这样的代码:

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 或当使用数组时或当我在传递 getRGB 之前分配数组时抛出 ArrayOutOfBoundsException 。我检查调试器,图像具有大小并已分配。

更新: 获取RGB

 /**
 * 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;
}

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谁把谁当真 2024-12-16 11:43:00

有两个问题:

  1. 数组的宽度不是图像的宽度,而是“扫描大小”(某些图像大小会用额外的像素填充)

  2. 如果您使用 null 数组调用 getRGB(),该方法将创建一个数组,但它不会改变rgb 参考 - Java 不支持“输出参数”。

为了使这项工作正常进行,请使用

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

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);
穿越时光隧道 2024-12-16 11:43:00

您的代码将引发 NullPointerException,因为您从未将非空引用分配给 rgb 变量。因此,对它的引用(例如rgb[index])将生成异常。如果您希望将空数组传递给 getRGB,则需要确保分配该方法返回的结果数组;例如,

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

如果您要取消注释注释掉的代码,则存在一个错误,即您将数组分配为 imageWidth * imageWidth 而不是 imageWidth * imageHeight,这就是您的原因看到ArrayIndexOutOfBoundsException

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文