Java Image I/O API 가이드:3 - Image I/O 어플리케이션의 작성 - xrath.com 에서 번역됨

목차 | 전의 항목 | 다음의 항목 | JavaTM Image I/O API 가이드

## 3.3 `ImageReader`

> 어플리케이션은,`ImageIO` 클래스를 사용해 이미지의 복호화 처리 전체를 실행하는 것이 아니라,`ImageIO` 클래스를 사용해 `ImageReader` 객체를 취득해 (아래의 코드예를 참조), 그 객체를 사용해 read를 실행할 수가 있습니다.

>     Iterator readers = ImageIO.getImageReadersByFormatName("gif");
>     ImageReader reader = (ImageReader) readers.next();

> read 객체는, 파일의 내용, 파일의 확장자(extension), 또는 MIME 타입에 근거해 취득할 수도 있습니다. read 객체를 검색해 인스턴스 생성하는 기구에서는,`javax.imageio.spi.ImageReaderSpi` 클래스를 이용합니다. 이 클래스를 사용하면(자), 플러그 인을 실제로 인스턴스 생성하지 않아도, read 플러그 인에 대한 정보를 취득할 수 있습니다. 「서비스 프로바이더 인터페이스」(service provider interface, SPI)의 개념에 대해서는, 다음의 장으로 자세하게 설명합니다.

> read 플러그 인을 취득한 뒤는, 그 객체에 입력 소스를 제공하지 않으면 안됩니다. 대부분의 read 객체는,`ImageInputStream` 로부터 데이터를 읽어들일 수 있습니다. 이것은, Image I/O API 에 의해 정의되고 있는 특수한 입력 소스입니다. 특수한 입력 소스를 사용하는 목적은, read 객체나 기입해 객체가, 파일 입출력과 스트림 입출력의 양쪽 모두를 간단하게 처리할 수 있도록(듯이) 하는 것입니다.

> `ImageInputStream` 를 취득하는 것은 간단합니다. 입력 소스가 `File` 또는 `InputStream` 의 형식인 경우,`ImageInputStream` 는, 다음과 같은 호출에 의해 생성할 수 있습니다.

>     Object source; // File or InputStream
>     ImageInputStream iis = ImageIO.createImageInputStream(source);

> 소스를 취득한 뒤는, 다음의 호출에 의해 그 소스를 읽어들여 객체에 접속할 수 있습니다.

>     reader.setInput(iis, true);

> 이 2 번째의 파라미터는, 원시 파일에 복수의 이미지가 포함되어 있어, 어플리케이션이 그러한 이미지를 차례로 읽어들일 수 있다고 하는 보증이 없는 경우에는, false 로 설정할 필요가 있습니다. 1 개의 파일에 1 개의 이미지 밖에 포함할 수 없는 파일 형식의 경우에는, 이 파라미터에 항상 true 를 설정하도록(듯이) 합니다.

> read 객체에 입력 소스를 설정한 뒤는, 반드시 이미지 데이터를 메모리내에 읽어들이지 않아도, 그 객체를 이용해 이미지에 대한 정보를 입수할 수 있습니다. 예를 들어,`reader.getImageWidth(0)` 를 호출하면, 파일에 포함되고 있는 최초의 이미지의 폭을 입수할 수 있습니다. 능숙하게 작성된 플러그 인이면, 이미지의 폭을 판별하는데 필요한 데이터만을 복호화 해, 픽셀은 읽어들이지 않게 할 것입니다.

> 이미지를 읽어들이려면 , 어플리케이션으로부터 `reader.read(imageIndex)` 를 호출합니다 (`imageIndex` 는, 파일내의 이미지의 인덱스). 이 호출의 결과는, 위에서 설명한 `ImageIO.read` 를 호출했을 때의 결과와 같습니다.

### 3.3. 1 `ImageReadParam`

> read 처리를 한층 더 상세하게 제어하려면 ,`read` 메소드에 `ImageReadParam` 형의 추가 파라미터를 지정합니다. `ImageReadParam` 를 사용하면(자), 복호화 된 이미지를 포함하는 목적지 이미지를 지정할 수 있으므로, 메모리의 사용을 효율적으로 제어할 수 있습니다. 또, 읽어들이고 싶은 영역을 지정하는 것이나, 이미지의 축소판을 취득하기 위해서 이용할 수 있는 서브 샘플링 계수를 지정하는 일도 가능합니다.

> 소스 영역이 설정되었을 경우는, 파일 형식이 부분적인 복호화를 허락하고 있는 한, read 플러그 인은, 설정된 영역만을 복호화 하려고 합니다. 어떤 경우에도, 설정된 영역의 외측에 있는 픽셀은 출력되지 않습니다. 이 기능에 의해, 매우 큰 이미지를 한정된 양의 메모리로 처리하는 것이 가능하게 됩니다.

> 예를 들어, 이미지의 좌상의 4 분의 1 구획만을 복호화 하려면 , 우선, 읽기 객체로 사용하기 위한 `ImageReadParam` 를 다음과 같이 해 가져옵니다.

>     ImageReadParam param = reader.getDefaultReadParam();

> 다음에, 읽어들이고 싶은 소스 영역을, 다음과 같이 해 `ImageReadParam` 로 설정합니다.

>     import java.awt.Rectangle;
>     int imageIndex = 0;
>     int half_width = reader.getImageWidth(imageIndex)/2;
>     int half_height = reader.getImageHeight(imageIndex)/2;
>     Rectangle rect = new Rectangle(0, 0, half_width, half_height);
>     param.setSourceRegion(rect);

> 그리고 마지막으로, 이 `ImageReadParam` 를 사용해, 다음과 같이 이미지를 읽어들입니다.

>     BufferedImage bi = reader.read(imageIndex, param);

> 이 결과적으로 출력되는 것은, 폭과 높이가 각각 원의 이미지의 반이 된 `BufferedImage` 입니다 (이미지의 폭이나 높이가 홀수의 경우, 끝수는 버릴 수 있습니다).

> 이후에, 이미지의 우하의 4 분의 1 구획을, 좌상의 4 분의 1 구획을 보관 유지하기 위해서 작성한 같은 `BufferedImage` 에 읽어들이려면 , 다음과 같이 해 이전의 픽셀 데이터를 덧쓰기합니다.

>     param.setDestination(bi);
>     rect = new Rectangle(half_width, half_height, half_width, half_height);
>     param.setSourceRegion(rect);
>     BufferedImage bi2 = reader.read(0, param);
>     if (bi == bi2) {
>     	System.out.println("The same BufferedImage was used! ");
>     } else {
>     	System.out.println("This can't happen! ");
>     }

> 실제로는, 결과를 어디에 할당하는지를 지정하지 않고 , 단지 `reader.read(0, param)` 를 호출할 수도 있습니다. 픽셀은 기존의 `BufferedImage` 인 `bi` 에 기입해진다고 하는 것을 알 수 있고 있기 때문입니다.

> 다른 예로서는, 이미지의 픽셀을 3 개에 1 개의 비율로 읽어들여, 원의 사이즈의 9 분의 1 의 이미지를 생성하기 위해(때문에), 다음과 같이 해,`ImageReadParam` 에 서브 샘플링 계수를 설정하는 일도 있습니다.

>     param = reader.getDefaultImageParam();
>     param.setSourceSubsampling(3, 3, 0, 0);
>     BufferedImage bi3 = reader.read(0, param);

### 3.3. 2 `IIOParamController`

> 플러그 인은, 옵션으로서`IIOParamController` 객체를 제공할 수가 있습니다. 이 객체는,`IIOReadParam` (또는 `IIOWriteParam`)를, 그래피컬 사용자 인터페이스 (GUI)나 그 외의 인터페이스를 이용해 셋업 하기 위해서 사용됩니다. read 플러그 인에서는, 작성한 임의의 `ImageReadParam` 객체에 대해서, 다음과 같이 해 `IIOParamController` 를 부가할 수 있습니다.

>     ImageReadParam param = reader.getDefaultImageParam();
>     IIOParamController controller = param.getController();
>     if (controller ! = null) {
>     	controller.activate(param);
>     }

> 콘트롤러 객체의 `activate` 메소드를 호출하면(자), GUI 가 표시되어 사용자가 슬라이더를 움직이거나 버튼을 클릭하거나 하는 이벤트가 처리됩니다. 일반적으로, 이 인터페이스에는 [OK] 또는 [적용] 버튼이 있어, 그 버튼이 클릭되면(자), activate 메소드로부터 돌아옵니다. 콘트롤러에는, 연결시킬 수 있었던 `ImageReadParam` 상태를 갱신하기 위한 메소드를 호출할 책임이 있습니다. 메소드의 호출은, 각 GUI 이벤트가 발생할 때마다 실행하는지,`activate` 메소드로부터 돌아오기 전에 모두 한 번에 실행할까의 어느 쪽인지입니다.

### 3.3. 3 멀티 이미지 파일로부터의 read

> `ImageReader` 클래스의 메소드 가운데, 이미지를 처리하는 메소드는 모두,`imageIndex` 파라미터를 취합니다. 이 파라미터를 사용해, 멀티 이미지 파일내의 임의의 이미지에 액세스 할 수 있습니다.

> `ImageReader.getNumImages` 메소드는, 입력 파일에 포함되고 있는 이미지의 수를 돌려줍니다. 이 메소드는, boolean 형의 파라미터 `allowSearch` 를 취합니다. 일부의 이미지 형식 (특히 GIF)에서는, 파일 전체를 읽어들이지 않고 이미지의 수를 판별하는 수단이 제공되고 있지 않습니다. 이것으로는 부하가 너무 걸리는 일이 있으므로,`allowSearch` 에 `false` 를 설정할 수가 있습니다. 그 경우, read 객체는 반환값으로서 실제의 이미지수는 아니고,`-1` 를 돌려줍니다. 이 파라미터가 `true` 의 경우, read 객체는 항상 실제의 이미지수를 돌려줍니다.

> 어플리케이션이 이미지의 수를 식별할 수 없는 경우에서도,`read(imageIndex)` 를 호출하는 것은 가능합니다. 인덱스가 너무 크면(자), 이 메소드는 예외 `IndexOutOfBoundsException` 를 throw 합니다. 따라서, 어플리케이션은, 예외를 받을 때까지, 인덱스를 늘리면서 이미지를 요구할 수가 있습니다.

### 3.3. 4 「썸네일」이미지의 read

> 일부의 이미지 형식에서는, 1 개(살)의 작은 프리뷰 이미지 (또는 복수의 프리뷰 이미지)를, 메인의 이미지와 함께 포함할 수 있습니다. 이 「썸네일」이미지는, 이미지 전체를 복호화 하는 필요없음에, 이미지 파일을 재빠르게 식별할 수 있어 편리합니다.

> 어플리케이션은, 다음의 호출에 의해, 특정의 이미지에 관련지을 수 있고 있는 썸네일의 수를 판별할 수 있습니다.

>     reader.getNumThumbnails(imageIndex);

> 썸네일 이미지가 존재하는 경우는, 다음과 같은 호출에 의해 취득할 수 있습니다.

>     int thumbailIndex = 0;
>     BufferedImage bi;
>     bi = reader.readThumbnail(imageIndex, thumbnailIndex);

목차 | 전의 항목 | 다음의 항목

Copyright © 2001 Sun Microsystems, Inc. All Rights Reserved.