2016-06-21 5 views
-3

ImageIO을 사용하여 이미지를 가져 와서 이미지 구성 요소 (알파, 레드, 그린, 블루)를 바이트 배열에 저장합니다. 나중에이 바이트 배열에서 읽을 필요가 있지만 구성 요소를 어떤 순서로 알 수 없습니다 (첫 번째 요소가 알파인지, 두 번째 빨간색인지 또는 배열에 있는지) 모르면 저장되지 않습니다. 알파도 저장 했습니까?BufferedImage 유형을 어떻게 바꿀 수 있습니까?

기본 시퀀스가 ​​있습니까? 또는 ABGR이나 ARGB 등과 같이 원하는 순서로 시퀀스를 변경하는 방법이 있습니까?

배열의 구성 요소를 가져 오기위한 현재 코드입니다.

BufferedImage temp; 

    try{ 
     temp = ImageIO.read(new File(path)); 
     ImageArray = ((DataBufferByte)temp.getRaster().getDataBuffer()).getData(); 
    }catch(IOException ex){ 
     ex.printStackTrace(); 
    } 

자바 문서가 전혀 도움이되지 못했습니다.

int getRGB(int x, int y) 

void setRGB(int x, int y, int rgb) 

두 경우 화소 채널와 항상 관계없이 픽처 설치 방법과 동일한 방식을 따르 자바

+1

코드가 이미지 구성 요소를 바이트 배열에 저장하는 방법을 보여주십시오. – VGR

+1

@VGR 코드가 업로드되었습니다. 이제는 구성 요소가 배열에 어떻게 배열되지 않습니다. –

+0

제목이 귀하의 질문과 관련이 없습니다. – EJP

답변

2

않는 BufferedImage 객체는 두 개의 중요한 방법이있다. int rgb는 4 바이트 정수입니다.

왼쪽 가장 큰 바이트는 알파이며 그 다음에는 빨간색, 파란색, 녹색 순입니다. 즉, argb입니다. 1 바이트는 0에서 255까지의 작은 정수를 저장할 수 있기 때문에 각 바이트에는 256 개의 서로 다른 개별 강도가 있습니다. 실제 비트는 다음과 같다 :

aaaaaaaarrrrrrrrggggggggbbbbbbbb 

당신이 비트 연산자를 사용하여 액세스하고자하는 색상이나 알파를 추출하려면.

int rgb = image.getRGB(x, y); 
int a = (rgb >> 24) & 0x000000ff; 
int r = (rgb >> 16) & 0x000000ff; 
int g = (rgb >> 8) & 0x000000ff; 
int b =  (rgb) & 0x000000ff; 

는 방법을 볼 수 있습니다 : 나는 예를 들어, 바로 빨간색을 원하는 경우

, 나는 그냥 채널을 추출하는 16 진수 값 함께 다음 16 곳 오른쪽으로 비트를 이동하기 위해 bitshift의 OPERATOR 시스템을 사용할 수 있습니다 밖으로 나가는.

00000000 00000000 00101011 10101010 

공지 사항, 지금은 알파가 여전히 존재 ... 그리고 우리는 그것을 원하지 않는다 :

rgb -> the binary 00101011 10101010 11111111 00000000 

그런 다음 오른쪽으로 16 비트를 이동 할 수 있습니다 : 우리는 이미 색을 가지고 가정하자. 그래서 우리는 AND 연산 그들에 의해 붉은 비트를 제외한 모든 선택을 취소합니다 : 당신은 또한에 생각의 같은 라인을 사용하여 비트의 세 채널을 설정할 수 있습니다 10101010

색상의 단지 빨간색 구성 요소입니다

00000000 00000000 00101011 10101010 
and 00000000 00000000 00000000 11111111 
    = 00000000 00000000 00000000 10101010 

을 역방향 :

int rgb = (a << 24) | (r << 16) | (g << 8) | b; 

... 각 채널이 이미 0-255 사이에 있다고 가정합니다.

니모닉 "set-or clear-and"를 사용하여 비트 연산자를 사용하는 방법을 항상 기억합니다. 즉 비트를 1로 설정하려면 "또는"을 사용합니다. 비트를 0으로 지우려면 "and"를 사용하십시오. "< <"및 ">>"는 화살표 오른쪽에있는 피연산자에 의해 지정된 횟수만큼 비트를 왼쪽 또는 오른쪽으로 시프트합니다.(코드는 질문에 추가 후)

개정 된 답는 성능과 명확성을 이유로 권장하지 않습니다하더라도

, 래스터 직접 다양한 배열로 액세스 할 수 있습니다. 이러한 경우 바이트 순서는 이미지의 유형 및 색상 모델을 따릅니다. 여기에 하나의 예이다 : 당신이 TYPE_3BYTE_RGBTYPE_3BYTE_BGR을 변경한다면, 모든 세 번째 바이트 (3N)가 대신 위의 예에서 파란색의 빨간색 것

BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR); 
// If we swap the type, what we put in our for loop will vary greatly 
DataBufferByte dbb = ((DataBufferByte)img.getRaster().getDataBuffer()); 
byte[] bytes = dbb.getData(); 
for (int i = 0; i < bytes.length; i++) { 
    // modify byte array here with bytes[i]; 
} 
try { 
    SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, 100, 100, 3, 100*3, new int[]{2, 1, 0}); 
    DataBuffer dataBuffer = new DataBufferByte(bytes, bytes.length); 
    Raster raster = Raster.createRaster(sampleModel, dataBuffer, null); 
    img.setData(raster); 
} catch stuff...... 

; 또한 세 번째 플러스 두 (3n + 2) 바이트는 빨간색 대신 파란색입니다. 이것은 기본적으로 빨간색과 파란색 바이트를 스왑합니다.

BYTE에서 INT으로 변경되면 배열은 int 대신 바이트 배열이됩니다.

+1

즉, Array [0]은 알파, Array [1]은 빨강, Array [2]는 녹색, Array [3]은 파란색을 의미합니다. 권리 ? –

+0

DataBufferByte에 대한 각 인덱스가 올바르게 기억되면 단지 바이트입니다. 그래서 예, 픽셀 당 4 개가 있어야합니다. 확인을 위해 샘플 프로젝트를 시작하고 있습니다. 바로 다시 연락 드리겠습니다. –

+0

실제 래스터에서 바이트를 수정하는 수준에 도달하면 채널 및 순서의 크기는 구성 요소 모델에 따라 달라집니다. 이것은 버퍼링 된 이미지에서 $ img.getColorModel(). getComponentSize() $ 호출을 사용하여 얻을 수 있습니다. 생성자에 의해 버퍼 된 이미지를 생성하는 경우이 형식은 BufferedImage.TYPE을 사용하여 전달됩니다. –