소스 (BufferedImage
)의 ARGB 값 ()으로 복사본을 만들고 싶습니다. 합성하지 않아야합니다. ARGB 값이 0x8000BE50 인 픽셀 (128의 알파 값)을 복사하면 대상 픽셀은 정확히 0x8000BE50이어야하며 대상 픽셀을 완전히 무시해야합니다.Java : BufferedImage의 픽셀을 빠르게 복사하는 방법은 무엇입니까? (단위 테스트 포함)
나는 매우 정확한 질문을하고 내가 필요한 것을 보여주기 위해 단위 테스트를했다. 단위 테스트는 완벽하게 기능적이며 자급 자족하며 잘 통과하고 있으며 원하는대로 정확하게 테스트하고 있습니다.
그러나, 나는 더 빠르고 메모리 효율적인 방법은 copySrcIntoDstAt (...)를 대체합니다.
그게 내 질문의 핵심이다. 나는 이미지를 더 빠르게 채우는 방법이 아니다. (내가했던 것은 단위 테스트를하는 예제 일 뿐이다.) 내가 원했던 것은 이 무엇이 될 것인지를 아는 것이다. 빠른 속도와 메모리 효율적인 (즉, 빠르며 불필요한 객체를 생성하지 않는다).
필자가 만든 개념 증명 구현은 분명히 메모리 효율이 뛰어나지 만 속도가 느립니다 (각 픽셀에 대해 getRGB
과 setRGB
한 개를 수행함).
도식적으로,이있어 :
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAAAAAAAAA
여기서 'B :
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
(A는 복사하기 전에 대상 이미지에서 해당 픽셀을 나타내는 경우) 그리고 나는이 갖고 싶어 '는 src 이미지의 픽셀을 나타냅니다.
API 링크/견적이 아닌 copySrcIntoDstAt (...) 메서드의 정확한 대체품을 찾고 있습니다.
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 * 루프 및 System.arraycopy를 수동으로 수행하지 않고도 기존 작업을 수행 할 것으로 기대했을 것입니다. 하지만, 정말 멋지다. (그냥 시도해 보니 괜찮아 보인다.) – SyntaxT3rr0r
@WizardOfOds 감사합니다. 여러분은 오프셋을 이동하는 데 필요한 어떤 종류의 루프가 "더 빠르고 더 효율적입니다"라고 강조했습니다. 복사를하지 않고 객체를 생성하지 않고 내부 구조를 조작하면 JNI가 아닌 메소드가 더 잘 수행 될 것입니다. – stacker