'How to compress jpg and png images in java?
I used ImageIO library and tried to compress Multipart File but if the extension is jpg then it works fine, but when I used png file then it's not working.
I got this error while executing this code
byte[] byteArr = multipartFile.getBytes();
InputStream inputStream = new ByteArrayInputStream(byteArr);
BufferedImage image = ImageIO.read(inputStream);
public String compressImage(MultipartFile multipartFile, BufferedImage image) throws IOException {
String filePath = System.getProperty("java.io.tmpdir");
File compressedImageFile = new File(filePath);
OutputStream os = new FileOutputStream(compressedImageFile.getName());
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(FilenameUtils.getExtension(multipartFile.getOriginalFilename()));
ImageWriter writer = writers.next();
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
writer.setOutput(ios);
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.5f);
writer.write(null, new IIOImage(image, null, null), param);
os.close();
ios.close();
writer.dispose();
return String.valueOf(compressedImageFile);
}
Method threw 'java.lang.UnsupportedOperationException' exception." stack trace
ERROR TextMessaging:309 - An exception occured while executing sendMessage.json:
java.lang.UnsupportedOperationException: Compression not supported.
at javax.imageio.ImageWriteParam.setCompressionMode(ImageWriteParam.java:914) ~[?:1.8.0_301]
at com.starbucks.amazon.services.impl.ImageCompression.compressImage(ImageCompression.java:36) ~[classes/:?]
at com.starbucks.amazon.services.impl.ImageCompression$$FastClassBySpringCGLIB$$9a83d3e.invoke(<generated>) ~[classes/:?]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.6.jar:5.3.6]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) ~[spring-aop-5.3.6.jar:5.3.6]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.6.jar:5.3.6]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.6.jar:5.3.6]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.6.jar:5.3.6]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.6.jar:5.3.6]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.6.jar:5.3.6]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.6.jar:5.3.6]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.6.jar:5.3.6]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.6.jar:5.3.6]
at com.starbucks.amazon.services.impl.ImageCompression$$EnhancerBySpringCGLIB$$87686d38.compressImage(<generated>) ~[classes/:?]
at com.starbucks.amazon.restcalls.TextMessaging.sendMessage(TextMessaging.java:222) ~[classes/:?]
Solution 1:[1]
As seen from the stack trace, the problem is param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT)
. This is perhaps counter-intuitive based on the fact that PNG does indeed support compression, so I fully understand the confusion. However, the API is what it is...
Change:
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.5f);
To:
if (param.canWriteCompressed()) {
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.5f);
}
PNG format will be written compressed regardless, as PNG always use zlib/deflate compression.
PS: In more recent versions of the JDK, the PNGImageWriteParam
supports specifying the compression level (from JDK 9, backport exists for JDK 7 and 8). The above code will work anyway, but it will affect the compression ratio (lower numbers means less quality/more compression). You might want to handle compressions for different formats more explicitly.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |