티스토리 뷰
관련 라이브러리
IM4J (ImageMagick) - link
- 오랜시간 사용 되고있는 image I/O 오픈소스 라이브러리
- 이미지 편집, 포맷 변경 등 다양한 기능을 제공
TwelveMonkeys - link
- Java의 ImageIO를 위한 plugin 및 extension을 지원하는 오픈소스 라이브러리
- 다양한 파일 포맷의 Read/Write를 지원함
JDeli - link
- Java Image I/O 및 편집을 지원
- license 구독을 해야함
Aspose.PSD for Java - link
- Photoshop으로 만들어진 파일을 조작할 수 있는 라이브러리
- 이미지 편집, 워터마크 등 여러 기능 사용가능
- license 구독을 해야함
ImageIO.write jpeg 파일에 이미지가 만들어 지지않는 문제
- 테스트로 받은 psd 파일 2개 중 하나에서 (test.psd: 42.9MB) 문제 발생
- jpeg format이 아니라 png format으로 변환 시 문제없이 변환이 됨
처음에는 javax.imageio.IIOException: Invalid argument to native writeImage 에러 메세지가 노출됨
- open JDK 에서 oracle JDK 변경 후 메세지가 노출되지 않음
- open JDK 에서는 native JPEG encoder를 지원하지 않는다고 함 - link
하지만 여전히 psd → jpeg(ImageIO.write) 변환 시, 최종 JPG 파일에 이미지가 변환되지 않은 상태
- jpeg에서 AlphaChannel 를 지원하지 않음 → 워터마크 이미지 투명도 설정에 AlphaComposite 이 사용됨
- 다른 psd 파일(test2.psd: 8.9MB)에서는 정상적으로 변환이 됨
- 비슷한 문제?(link)
JPEG 압축 방식
문제의 원인
InputStream으로 들어오는 source file의 BufferedImage type이 TYPE_4BYTE_ABGR (has alpha channel) 이기 때문에 JPEG로 ImageIO.write 하는 것에서 문제가 생긴 것으로 추정됨
- 다른 PSD 파일(test2.psd)은 TYPE_3BYTE_BGR 타입으로 alpha channel이 없음
TYPE_4BYTE_ABGR 에 대한 설명
Represents an image with 8-bit RGBA color components with the colors Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The image has a ComponentColorModel with alpha. The color data in this image is considered not to be premultiplied with alpha. The byte data is interleaved in a single byte array in the order A, B, G, R from lower to higher byte addresses within each pixel.
psd → watermarked jpeg 프로세스를 수정
Alpha channel이 포함된 bufferedImage에 대해서 수행
- ImageIO.read(sourceInputStream) 으로 psd file BufferedImage 생성(psd plugin)
- 워터마크를 넣기 위해 sourceImage.graphics as Graphics2D graphics 생성
- 워터마크 graphics2D.drawImage 로 그리기
- val newImage = BufferedImage(sourceImage.width, sourceImage.height, BufferedImage.TYPE_INT_RGB) 로 새로운 BufferedImage 생성
- ImageIO.write(newImage, .. , ..) 로 watermarked jpeg file 최종 생성
Image I/O 처리 최적화
- 파일의 사이즈가 큰 경우 ImageIO.read 에서 꽤 많은 시간이 소요되는 것으로 보임
- javax ImageIO에서 read, write 작업 시 Cache Directory에 temporary file을 저장함(ImageIO.getCacheDirectory() 로 확인가능)→ 디스크 기반 캐시 파일을 사용할지 여부
- ImageIO에서 control cache의 의미는?
- BufferedImage I/O 작업을 할때 cache를 사용하지않고 작업을 한다면?
- Input/OutputStream은 캐싱처리를 하지 않으면 data를 re-read 할 수 없다
Sets a flag indicating whether a disk-based cache file should be used when creating ImageInputStreams and ImageOutputStreams. When reading from a standard InputStream, it may be necessary to save previously read information in a cache since the underlying stream does not allow data to be re-read. Similarly, when writing to a standard OutputStream, a cache may be used to allow a previously written value to be changed before flushing it to the final destination. The cache may reside in main memory or on disk. Setting this flag to false disallows the use of disk for future streams, which may be advantageous when working with small images, as the overhead of creating and destroying files is removed. On startup, the value is set to true.
- ImageIO.setUseCache(false) 처리로 sample file(test.psd: 42.9MB)의 워터마크 처리가 4.x secs → 3.x secs로 대략 1초 정도 단축됨
- 구현 코드
ImageMagick으로 개발
JMagick 세팅
- 단순히 gradle dependencies 추가만 해서는 빌드가 안됨 - link
- setup process
// mac
$ brew install imagemagick
$ git clone <https://github.com/techblue/jmagick.git>
$ cd jmagick
$ autoreconf --force --install
$ automake --add-missing
$ ./configure --with-java-home=/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home --with-magick-home=/usr/local/Cellar/imagemagick/7.0.11-9
$ make
$ make all
Java Image converting & replacing 실제 경험에 의한 비교 - Link
JMagick의 단점?
JMagick had support for many formats, but had no stream support, which is very bad when working with web architectures. Temporary writing to disk increases the response time, and slows down overall performance. Plus the lack of binary compatibility from version to version and being a nightmare to install.
None of the libraries had proper support for PSD format (JMagick didn't support reading individual layers)
'ETC' 카테고리의 다른 글
Java & Kotlin 의 null 에 대해서 (0) | 2022.03.09 |
---|---|
Gatsby를 git page 연결 (0) | 2019.03.13 |