Какой тип массива требуется в методе WritableRaster setPixels()?
Я не понимаю, как работает класс WritableRaster Java. Я пытался просмотреть документацию, но не понимаю, как он принимает значения из массива пикселей. Кроме того, я не уверен, из чего состоит массив пикселей.
Здесь я объясняю.
То, что я хочу сделать, это: Секретный обмен Шамира на изображениях. Для этого мне нужно получить изображение в изображении BuferedImage. Я беру секретное изображение. Создайте акции, запустив "функцию" для каждого пикселя изображения. (в основном изменение значений пикселей на что-то)
Snippet:
int w = image.getWidth();
int h = image.getHeight();
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
int pixel = image.getRGB(j, i);
int red = (pixel >> 16) & 0xFF;
int green = (pixel >> 8) & 0xFF;
int blue = (pixel) & 0xFF;
pixels[j][i] = share1(red, green, blue);
// Теперь принимаем эти значения RGB. Я изменяю их с помощью некоторой функции и возвращаю значение типа int. Что-то вроде этого:
public int share1 (r, g, b)
{
a1 = rand.nextInt(primeNumber);
total1 = r+g+b+a1;
new_pixel = total1 % primeNumber;
return new_pixel;
}
// Этот пиксель двухмерного массива имеет все новые значения цвета, верно? Но теперь я хочу построить изображение, используя эти новые значения. Так что я сделал это. Сначала преобразовал этот массив пикселей в список. Теперь в этом списке есть значения пикселей нового изображения. Но чтобы построить изображение с помощью метода RasterObj.setPixels(), мне нужен массив со значениями RGB [Я МОГУ БЫ НЕПРАВИЛЬНО ЗДЕСЬ!] Поэтому я беру отдельные значения списка и нахожу значения rgb и последовательно помещаю их в новый 1D массив pixelvector.. примерно так (r1, g1, b1, r2, g2, b2, r3, g3, b3...)
Размер списка составляет w h, потому что он содержит одно пиксельное значение каждого пикселя. НО, размер нового массива pixelvector станет w h * 3, так как он содержит значения r, g, b каждого пикселя.
Затем для формирования изображения я делаю это: сниппет
BufferedImage image_share1 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
WritableRaster rast = (WritableRaster) image_share1.getData();
rast.setPixels(0, 0, w, h, pixelvector);
image_share1.setData(rast);
ImageIO.write(image_share1,"JPG",new File("share1.jpg"));
Если в метод setPixels() поместить массив с однопиксельными значениями, он не вернется из этой функции! Но если я добавлю массив с отдельными значениями r, g, b, он вернется из функции. Но делаю то же самое для share1, share 2 и т.д.. Я получаю только оттенки синего. Так что я даже не уверен, что смогу восстановить образ..
PS - Это может выглядеть как очень глупый код, который я знаю. Но у меня был всего один день, чтобы сделать это и узнать об изображениях на Java. Так что я делаю все, что могу.
Спасибо..
1 ответ
Raster
(лайк WriteableRaster
и его подклассы) состоит из SampleModel
и DataBuffer
, SampleModel
описывает образец макета (является ли он упакованным в пиксели, с чередованием пикселей, с чередованием полос? Сколько полос? и т.д....) и размерами, в то время как DataBuffer
описывает фактическое хранилище (образцы байт, короткие, целые, подписанные или беззнаковые? один массив или массив на полосу? и т. д...).
За BufferedImage.TYPE_INT_RGB
сэмплы будут упакованы в пиксели (все 3 сэмпла R, G и B упакованы в один int
для каждого пикселя), а также тип данных / передачи DataBuffer.TYPE_INT
,
Извините, что не ответили на ваш вопрос относительно WritableRaster.setPixels(...)
напрямую, но я не думаю, что это метод, который вы ищете (в большинстве случаев это не так).:-)
Для вашей цели, я думаю, что вы должны сделать что-то вроде:
// Pixels in TYPE_INT_RGB format
// (ie. 0xFFrrggbb, where rr is two bytes red, gg two bytes green etc)
int[] pixelvector = new int[w * h];
BufferedImage image_share1 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
WritableRaster rast = image_share1.getRaster(); // Faster! No copy, and live updated
rast.setDataElements(0, 0, w, h, pixelvector);
// No need to call setData, as we modified image_share1 via it's raster
ImageIO.write(image_share1,"JPG",new File("share1.jpg"));
Я предполагаю, что остальная часть вашего кода для изменения значения каждого пикселя верна.:-)
Но только совет: вы упростите для себя (и быстрее из-за меньшего количества преобразований), если будете использовать одномерный массив вместо двумерного. То есть:
int[] pixels = new int[w * h]; // instead of int[][] pixels = new int[w][h];
// ...
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
// ...
pixels[y * w + x] = share1(red, green, blue); // instead of pixels[x][y];
}
}