Я хочу сделать копию (области прямоугольника) значений ARGB от источника BufferedImage
в пункт назначения BufferedImage
. Никакой компоновки не должно быть сделано: если я копирую пиксель с ARGB значением 0x8000BE50 (значение альфа на 128), то целевой пиксель должен быть ровно 0x8000BE50, полностью перекрывая пиксель назначения.Java: как сделать быструю копию пикселей BufferedImage? (включенный тест)
У меня есть очень точный вопрос, и я сделал единичный тест, чтобы показать, что мне нужно. Единичный тест полностью функциональный и автономный и проходит отлично и делает именно то, что я хочу.
Однако, я хочу эффективный методбыстрее и больше памяти для замены copySrcIntoDstAt (...).
В этом весь мой вопрос: я не знаю, как «заполнить» изображение быстрее (то, что я сделал, является просто примером для модульного теста). Все, что я хочу, - это знать, что может сделать быстрый и эффективный способ сделать это (то есть быстро и не создавать ненужные объекты).
Реализация концептуальной концепции, которую я сделал, очевидно, очень эффективна с точки зрения памяти, но она медленная (делает один getRGB
и один setRGB
для каждого пикселя).
Схематично, у меня есть это: (где А обозначает соответствующие пиксели от целевого изображения до копии)
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
И я хочу, чтобы это:
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAAAAAAAAA
где «B 'представляет пиксели изображения src.
Обратите внимание, что я ищу точную замену метода copy44rsIntoDstAt (...) , а не для ссылки/цитаты API.
import org.junit.Test;
import java.awt.image.BufferedImage;
import static org.junit.Assert.*;
public class TestCopy {
private static final int COL1 = 0x8000BE50; // alpha at 128
private static final int COL2 = 0x1732FE87; // alpha at 23
@Test
public void testPixelsCopy() {
final BufferedImage src = new BufferedImage( 5, 5, BufferedImage.TYPE_INT_ARGB);
final BufferedImage dst = new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB);
convenienceFill(src, COL1);
convenienceFill(dst, COL2);
copySrcIntoDstAt(src, dst, 3, 4);
for (int x = 0; x < dst.getWidth(); x++) {
for (int y = 0; y < dst.getHeight(); y++) {
if (x >= 3 && x <= 7 && y >= 4 && y <= 8) {
assertEquals(COL1, dst.getRGB(x,y));
} else {
assertEquals(COL2, dst.getRGB(x,y));
}
}
}
}
// clipping is unnecessary
private static void copySrcIntoDstAt(
final BufferedImage src,
final BufferedImage dst,
final int dx,
final int dy
) {
// TODO: replace this by a much more efficient method
for (int x = 0; x < src.getWidth(); x++) {
for (int y = 0; y < src.getHeight(); y++) {
dst.setRGB(dx + x, dy + y, src.getRGB(x,y));
}
}
}
// This method is just a convenience method, there's
// no point in optimizing this method, this is not what
// this question is about
private static void convenienceFill(
final BufferedImage bi,
final int color
) {
for (int x = 0; x < bi.getWidth(); x++) {
for (int y = 0; y < bi.getHeight(); y++) {
bi.setRGB(x, y, color);
}
}
}
}
+1 очень приятно ... Я никогда не думал, что с помощью нескольких * System.arraycopy * будет в путь. Я полагаю, что каждый BufferedImage всегда имеет растр и что здесь нет никакого создания объекта !? Это очень приятно, но в то же время это кажется немного странным: я бы ожидал, что что-то уже существовало, выполняя эту работу, не делая вручную * for * loop и System.arraycopy вручную. Но, да, действительно хорошо (просто попробовал это кстати, и это кажется прекрасным :) – SyntaxT3rr0r
@WizardOfOds Спасибо, вы подчеркнули, что «быстрее и эффективнее с точки зрения памяти» какой-то цикл необходим для перемещения смещений. Манипулируя внутренними структурами, не делая копии и создавая объекты, я сомневаюсь, что будет работать не более JNI-метод. – stacker