2012.01.03 00:42
갤러리를 만들때 중요한게 바로 이미지로더입니다.

이미지를 불러와야 원하는  프로세싱을 적용할텐데, 로드조차 못한다면 이건 뭐...갤러리가 아닌게 되니...ㅋ

그래서 정말 열심히 검색을 해보았습니다. 하지만 자바의 내부 클래스들을 대충으로만 알고 있는 상태라서 영 감을 잡지 못했지요...

그러던 도중, 중요한 클래스 몇개를 발견하게 됩니다.

Image, BufferedImage, ImageIO, Toolkit 이정도...

먼저 파일 입출력, 정확히는 이미지파일 입출력을 먼저 했어야 했기에, 구글링 해보았습니다.

제일 많이 나온 구문이 바로 툴킷을 이용해서 불러오기더군요.
private Image loadImage (String pad){
     return Toolkit.getDefaultToolkit().getImage(getClass().getResource(pad));
}

하지만 툴킷으로 불러왔을때, 이 객체를 이미지에 담아도 툴킷이미지로 담기더라구요.... 이거 참....-_- ;
()

그래서 캐스팅을 해줬지만 그래도....-_- 뭐 일단 불러 왔으니, 그다음 RGB를 추출하려 했습니다.

받아온 Image를  BufferedImage로 강제 형변환! -> 실패ㅋ (다운캐스팅....;;;;;;)

그래서 Javadoc을 뒤져봅니다...

Image :  http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/Image.html 
BufferedImage   : http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/image/BufferedImage.html 

으음.....Image 자체엔 RGB 값을 가져올 수 있는게 없더군요.. 그래서  BufferedImage의 매소드를 가져와 쓰기로 결심, 다시 파일을 불러올때 아에  BufferedImage로 받아올 수 있는게 있는지 찾아보았습니다.

그러다가  ImageIO 를 사용하는 예제 몇개를 발견! 또 코드도 간결했습니다.
public static BufferedImage loadImage(String url) {
	BufferedImage image = null;
	try {
		image = ImageIO.read(new File(url));
	} catch (IOException e) {
		e.printStackTrace();
	}
	return image;
}

우오! 정말...간단합니다.. 그냥 read(파일(주소)).............이렇게 간단한걸 이틀간 찾아 해맸습니다...ㅋ

저렇게 받아오면, 바로  BufferedImage에 담을 수 있습니다.ㅋ 따라서 바로 픽셀 조작을 할 수 있다는 거죠!
BufferedImage image = loadImage(url);
		
int w = image.getWidth(null);
int h = image.getHeight(null);
		
int[] result = new int[w * h];
result = image.getRGB(0, 0, w, h, result, 0, w);

이런식으로 가로세로값을 가져오고, getRGB 매소드로 result 배열에 다 담아버리면 됩니다! 그런뒤, result 배열을 조작하면 되는거죠. (물론, 그릴땐, setRGB 매소드에 result 배열을 넣어줘야 한다는거 잊지 마세요.ㅋ)
//참고로, getRGB 의 인자는 startX, startY, width, height, rgb, offset, scansize 인데, scansize는 가로 크기를 넣어주면, 전체 이미지의 픽셀 ARGB값을 가져오게 됩니다.

저기서 제가 해맸던 부분이 옵져버에 관한 부분이었습니다. 툴킷 사용에서 이미지를 불러 왔지만, 막상 불러온 이미지에 대한 가로, 세로의 크기를 받아올 수 가 없었습니다. 왜?

이때 든 생각이, 파일을 불러오는데 시간이 걸려서 그 전에 가로, 세로 크기에 엑세스 하는바람에 -1이 리턴됬다.. 이렇게 생각했습니다. 뭐 맞는지는 모르겠지만, 귀찮아서 툴킷을 버렸습니다..

그다음 사용한게 ImageIO인데, 이건  BufferedImage로 받아오고, 가로/세로를 받아오려면 안에 인자로 옵져버(ImageObserver)를 원하더군요....옵져버? 스타에서처럼 뭔가 관측하는 넘인가..했는데, 말처럼 이미지의 상태? 를 관찰? 전달받는 객체더군요. 뭐 이건 아직 잘 몰라서;;; null로 줘도 된대서 일단 null로 줬습니다..

이 옵저버에 관한 내용은 나중에 알게됬을때 포스팅하기로 하고...;;

뭐 어쨋든 저렇게 해서 이미지를 불러오고, RGB 값을 얻어와 무언가의 작업을 할 수 있게 되었습니다.
(저의 경우엔 블러 적용..ㅋ)


그런데, 모든 픽셀의 RGB값이 음수로 저장되더라구요...

왜 그런지 생각해보면, 일단, 컴터는 2진수로 수를 계산합니다. 그리고, 프리미티브 타입인 int 의 범위가 -2,147,483,648 ~ 2,147,483,647 (16진수로는, 8000 0000 ~ 7FFF FFFF)인데, 우리가 쓰려는 RGB 값은 정확히로는 ARGB 즉 알파가 있는 색상값입니다. 뭐 저 범위랑은 상관없이, 
2진수만 생각해보면,
16진수 -> 2진수
8000 0000  -> 1000 0000 0000 0000
7FFF FFFF -> 0111 1111 1111 1111

맨 처음 비트가 부호 비트(?)입니다. 그래서 ARGB 값 0xFFFF FFFF 를 표현하게 되면, 부호비트가 무색해지게됩니다. 그러니까, 2진수로 표현하면 앞자리(부호비트)가 1이 되서(사진은 알파값이 FF이므로) 10진수로 찍었을땐, 음수가 나오는 상황이 됩니다. 

예를들어, 색상이 빨강(0xFFFF 0000) 이면, 바이너리(2진수)로는, 1111 1111 1111 1111 0000 0000 0000 0000가 됩니다. 

출력시엔 10진수로 출력하니, 맨 처음 비트는 부호비트, 따라서, 10진수로 음수가 나오게 됩니다. 뭘 이렇게 복잡하게 설명했는지..... 그런데, 갑자기 이상한게 있습니다.

(그런데 말야, 하얀색을 표현하면 0xFFFF FFFF 인데 왜 int 의 범위 밖인데도 int에 넣을 수 있는거야?)
바로 int 의 범위를 16진수로 표현했을때 인데요, 이 역시 맨 앞자리가 부호비트로 쓰여서 깍이게 된것입니다.
이 부호비트를 부호로써가 아니라 숫자로써 사용하게 됨에 따라 하얀색인 0xFFFF FFFF 를 표현할 수 있게 된것입니다.

마지막으로, 사용시엔 문제가 안되는것이, 색상에선 음수를 쓰지 않기에, 또 실제 사용하는 값이 2진수이기에 그냥 넣어서 계산하면 2진수기 때문에 별 차이가 없게 됩니다...;;;

그냥 차라리 혼란 없도록 int 를 unsigned로 선언! 하면 되겠지만, 자바에선 안되기에;;;;;ㅠㅠ

(그런데 이거.,..말투 어떻게 하지..ㅋㅋ 웹이라서 정말 애매하네.....)
저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Trackback 0 Comment 0


티스토리 툴바