Управление пикселями в BufferedImage через массив

В настоящее время я слежу за серией статей о разработке игр на Java с нуля. Я понимаю большинство концепций java и oop, но у меня очень мало опыта работы с графикой и аппаратным ускорением.

Строки кода, которые я подвергаю сомнению:

 private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
 private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

Переменная «изображение» BufferedImage всегда является переменной, рисуемой на экране с помощью метода рендеринга. Обычно что-то вроде:

 public void render() {
    BufferStrategy bs = this.getBufferStrategy;
    if(bs == null) { this.createBufferStrategy(3); return; }
    Graphics g = bs.getDrawGraphics();
    g.drawImage(image, 0, 0, WIDTH, HEIGHT, null);
    g.dispose();
    bs.show();
 }

Я понимаю, что массив пикселей содержит каждый пиксель в BufferedImage, однако кажется, что каждый раз, когда этот массив заполняется значениями, он напрямую влияет на содержимое переменной «изображение». Никогда не используется метод, используемый для копирования значений массива пикселей в изображение.

Действительно ли эти переменные связаны таким образом? Используется ли:

private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

создать автоматическую связь между изображением и массивом, создаваемым в приведенном выше коде? Может быть, я схожу с ума и просто что-то пропустил, но я просматривал код несколько раз, и ни разу не манипулировали переменным «изображением» после его первоначального создания. (конечно, помимо рендеринга на экране.) Это всегда массив «пикселей», который просто заполняется разными значениями, что вызывает изменение визуализируемого изображения.

Некоторое понимание этого было бы замечательно. Заранее спасибо!


person Corderro Artz    schedule 29.11.2013    source источник
comment
По сути, когда вы запрашиваете массив пикселей, у вас есть прямой доступ к данным изображения. Поэтому каждый раз, когда вы меняете массив, он сразу же изменяется...   -  person MadProgrammer    schedule 30.11.2013


Ответы (2)


Почему бы тебе не позвонить

image.getData()

вместо

private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

image.getData() возвращает копию растра. getRaster() возвращает WriteableRaster с возможностью изменения пикселей. Я предполагаю, но getRaster(), вероятно, возвращает дочерний элемент изображения Raster и, следовательно, доступен для записи, если вы изменяете массив. Попробуйте image.getData(), чтобы увидеть, работает ли он. Если нет, напишите сюда, я посмотрю повнимательнее.

Я изучал это дальше. Исходный код, поставляемый с JDK, показывает, что image.getRaster().getDataBuffer().getData() возвращает исходный массив данных. image.getData() действительно возвращает копию. Если изображение изменено, данные в getData() не будут изменены.

Вы можете вызвать getPixels для возвращенного растра:

public int[] getPixels(int x,
              int y,
              int w,
              int h,
              int[] iArray)

Возвращает массив целых чисел, содержащий все выборки для прямоугольника пикселей, по одной выборке на элемент массива. Исключение ArrayIndexOutOfBoundsException может быть выдано, если координаты не находятся в границах. Однако явная проверка границ не гарантируется.

person mttdbrd    schedule 29.11.2013
comment
image.getData() возвращает растр. Однако, похоже, он не позволяет мне хранить возвращаемые данные в виде массива целых чисел. Дословно код обрабатывается следующим образом: image.getRaster() // возвращает растр изображения .getDataBuffer() // возвращает буферный объект .getData() // возвращает данные в растре в виде массива Затем приводит их к DataBufferInt гарантирует, что данные, хранящиеся в возвращаемом, если DataBufferInt — подкласс DataBuffer. Отсюда и новая часть частных пикселей int[]. - person Corderro Artz; 30.11.2013
comment
Вызовите getPixels() для возвращенного растра, чтобы получить массив пикселей int[]. Смотрите мое новое редактирование в моем ответе. - person mttdbrd; 30.11.2013
comment
Я не понимаю новые изменения в вашем комментарии. Не могли бы вы уточнить? Вы можете получить int[] из растра, вызвав getPixels(), как я писал выше. - person mttdbrd; 30.11.2013
comment
`` private int[] Pixels = img.getData().getPixels(0, 0, WIDTH, HEIGHT, null); `` Я получаю сообщение об ошибке. Метод getPixels(int, int, int, int, int[]) неоднозначен для типа Raster. Другими словами, я думаю, что он хочет убедиться, что растр относится к типу DataBuffer, будь то DataBufferInt или DataBufferDouble или так у вас. Это причина расширенного фрагмента кода в моем первоначальном вопросе. Вы следуете? Я знаю, что путаю даже себя. - person Corderro Artz; 30.11.2013
comment
Странный. Я посмотрю на это. - person mttdbrd; 30.11.2013
comment
Это потому, что есть три метода, которые принимают эти параметры. Приведите возвращаемое значение к типу (int[]) и посмотрите, поможет ли это. - person mttdbrd; 30.11.2013
comment
Я выйду ненадолго. Я загляну сюда позже. - person mttdbrd; 30.11.2013

Используйте int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); вместо image.getData(). image.getData() просто возвращает копию данных изображения, где image.getRaster() возвращает исходный массив пикселей, позволяющий фактически записывать в него пиксели.

person Martin Kersten    schedule 21.02.2016