ImageIO读jpg的时候出现exception:bandOffsets.length is wrong,我的解决方法

本文介绍了一种解决Java中使用ImageIO读取损坏的JPEG图片时出现的异常问题的方法。当JPEG图片的ICC信息被破坏导致ImageIO无法正常工作时,可以采用ThumbnailConvert工具结合ImageMagick将CMYK颜色空间转换为RGB来解决此问题。

用java处理图片的时候,ImageIO读jpg的时候出现exception:bandOffsets.length is wrong。我也遇到过,最终也解决啦,把成果跟大家分享。

原因可能是JPEG图片的ICC信息可能已经被破坏了,所以ImageIO会抛出异常

解决办法:

BufferedImage bis = null;
   try{
       bis = ImageIO.read(file);
       bis.getWidth();
       bis.getHeight();
   }catch(Exception e){
    try
    {
     ThumbnailConvert tc = new ThumbnailConvert();
     tc.setCMYK_COMMAND(file.getPath());
     Image image =null;
     image = Toolkit.getDefaultToolkit().getImage(file.getPath());
       MediaTracker mediaTracker = new MediaTracker(new Container());
     mediaTracker.addImage(image, 0);
     mediaTracker.waitForID(0);
      image.getWidth(null);
     image.getHeight(null);
    }catch (Exception e1){
     e1.printStackTrace();
    }
   }

这两句代码,是处理cmyk类型的图片,需要ImageMagick的支持

ThumbnailConvert tc = new ThumbnailConvert();
     tc.setCMYK_COMMAND(file.getPath());//用于把cmyk转成rgb

ImageMagick的具体指令是:mogrify -colorspace RGB -quality 100 file1

你遇到的错误: ``` Caused by: java.lang.IllegalArgumentException: category unknown! ``` 通常发生在你尝试调用 `IIORegistry.deregisterServiceProvider()` 或 `deregisterAll()` 时,传入的 SPI 类没有正确注册到 ImageIO 的某个插件类别(category)中。 --- ## ❓ 错误原因分析 `IIORegistry.deregisterAll(Class<?> providerClass)` 的实现逻辑是: - 它会查找这个 `providerClass` 所属的插件类别(如 `ImageReaderSpi.class`、`ImageWriterSpi.class` 等) - 如果这个类不是有效的 SPI 实现类(没有继承 `ImageReaderSpi`、`ImageWriterSpi` 等),就会抛出 `"category unknown!"` 例如,如果你这样写: ```java registry.deregisterAll(Class.forName("com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi")); ``` 而 `JPEGImageReaderSpi` 没有被正确加载或不属于任何 SPI 类别,就会触发这个错误。 --- ## ✅ 正确解决方案 ### ✅ 方法一:使用 SPI 基类来注销插件(推荐) ```java import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.IIORegistry; public class PluginManager { public static void deregisterJDKJPEGPlugins(IIORegistry registry) { // 注销所有 JDK JPEG ImageReaderSpi for (ImageReaderSpi spi : ImageIO.getReaderSpis()) { if (spi.getClass().getName().startsWith("com.sun.imageio.plugins.jpeg.")) { registry.deregisterServiceProvider(spi, ImageReaderSpi.class); } } // 注销所有 JDK JPEG ImageWriterSpi for (ImageWriterSpi spi : ImageIO.getWriterSpis()) { if (spi.getClass().getName().startsWith("com.sun.imageio.plugins.jpeg.")) { registry.deregisterServiceProvider(spi, ImageWriterSpi.class); } } } public static void registerTwelveMonkeysJPEG(IIORegistry registry) { registry.registerServiceProvider(new JPEGImageReaderSpi()); registry.registerServiceProvider(new JPEGImageWriterSpi()); } public static void init() { IIORegistry registry = IIORegistry.getDefaultInstance(); deregisterJDKJPEGPlugins(registry); registerTwelveMonkeysJPEG(registry); } } ``` ### ✅ 方法二:手动指定 SPI 基类注销 ```java try { Class<?> jdkReaderSpiClass = Class.forName("com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi"); registry.deregisterServiceProvider(jdkReaderSpiClass, ImageReaderSpi.class); } catch (ClassNotFoundException e) { // 忽略:JDK SPI 不存在 } ``` --- ## ✅ 方法三:避免注销,只注册 TwelveMonkeys(简单场景) 如果你只是想让 TwelveMonkeys 的插件优先,而不是完全注销 JDK 的,可以简单地: ```java IIORegistry registry = IIORegistry.getDefaultInstance(); registry.registerServiceProvider(new JPEGImageReaderSpi()); registry.registerServiceProvider(new JPEGImageWriterSpi()); ``` 因为 `ImageIO` 的 SPI 机制是 **后注册优先**,所以只要 TwelveMonkeys 的 SPI 最后注册,就会被优先使用。 --- ## ✅ 示例验证代码 ```java public class PluginChecker { public static void main(String[] args) { System.out.println("Current JPEG Readers:"); ImageIO.getImageReadersByFormatName("jpeg").forEachRemaining(r -> { System.out.println(" -> " + r.getClass().getName()); }); System.out.println("Current JPEG Writers:"); ImageIO.getImageWritersByFormatName("jpeg").forEachRemaining(w -> { System.out.println(" -> " + w.getClass().getName()); }); } } ``` --- ## ✅ 总结 | 问题 | 原因 | 解决方案 | |------|------|-----------| | `IllegalArgumentException: category unknown!` | 使用了不正确的 SPI 类或未指定 SPI 基类 | 使用 `deregisterServiceProvider(spi, category)` 方法 | | JDK 插件仍然优先 | 插件注册顺序不对 | 手动注册 TwelveMonkeys SPI 并确保其最后注册 | | 类找不到 | JDK SPI 不存在于某些 JRE 中 | 使用 try-catch 捕获 `ClassNotFoundException` | --- ##
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值