• 通过ImageReader进行图像裁剪时出现NoSuchElementException异常


    首先放上最初的Image工具类

    package util;
    
    import java.awt.Rectangle;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.FileInputStream;
    import java.util.Iterator;
    
    import javax.imageio.ImageIO;
    import javax.imageio.ImageReadParam;
    import javax.imageio.ImageReader;
    import javax.imageio.stream.ImageInputStream;
    
    public class ImageUtil {
    
        private ImageUtil() {
        }
        
        /**
         * 裁剪图像
         * 
         * @param x,y 起始点
         * @param width,height 宽高
         * @param srcpath 被裁减图像路径
         * @param subpath 裁剪后保存路径
         * @param type 图像类型
         * @throws Exception
         */
        public static void cut(int x, int y, int width, int height, String srcpath,
                String subpath, String type) throws Exception {
            FileInputStream is = null;
            ImageInputStream iis = null;
            try {
                // 读取图片文件
                is = new FileInputStream(srcpath);
                Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(type);
                ImageReader reader = it.next();
                // 获取图片流
                iis = ImageIO.createImageInputStream(is);
                reader.setInput(iis, true);
                ImageReadParam param = reader.getDefaultReadParam();
                Rectangle rect = new Rectangle(x, y, width, height);
                // 提供一个 BufferedImage,将其用作解码像素数据的目标。
                param.setSourceRegion(rect);
                BufferedImage bi = reader.read(0, param);
                ImageIO.write(bi, type, new File(subpath));
            } finally {
                if (is != null)
                    is.close();
                if (iis != null)
                    iis.close();
            }
        }
    
        /**
         * 获取图像真实类型
         * 
         * @param path 图像路径
         * @return 图像类型
         * @throws Exception
         */
        public static String getTypeByStream(String path) throws Exception {
            FileInputStream is = new FileInputStream(path);
            String type = "";
            byte[] b = new byte[4];
            try {
                is.read(b, 0, b.length);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (null != is) {
                    is.close();
                }
            }
            type = bytesToHexString(b).toUpperCase();
            if (type.contains("FFD8FF")) {
                return "jpg";
            } else if (type.contains("89504E47")) {
                return "png";
            } else if (type.contains("47494638")) {
                return "gif";
            } else if (type.contains("49492A00")) {
                return "tif";
            } else if (type.contains("424D")) {
                return "bmp";
            }
            return type;
        }
    
        /**
         * byte数组转换成16进制字符串
         * 
         * @param src
         * @return
         */
        private static String bytesToHexString(byte[] src) {
            StringBuilder stringBuilder = new StringBuilder();
            if (src == null || src.length <= 0) {
                return null;
            }
            for (int i = 0; i < src.length; i++) {
                int v = src[i] & 0xFF;
                String hv = Integer.toHexString(v);
                if (hv.length() < 2) {
                    stringBuilder.append(0);
                }
                stringBuilder.append(hv);
            }
            return stringBuilder.toString();
        }
    
    }
    ImageUtil-origin

    以前使用ImageReader对jpg图像进行裁剪没有任何异常,这几天接到新的需求,要能对tif图像进行裁剪。原以为只需将传入的type值改为tif即可,但报出了NoSuchElementException异常

    java.util.NoSuchElementException
        at javax.imageio.spi.FilterIterator.next(ServiceRegistry.java:825)
        at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:528)
        at javax.imageio.ImageIO$ImageReaderIterator.next(ImageIO.java:513)

    网上查了半天,各种说法都有,最终找到了问题所在:

    在jdk下的src中可以看到jdk自带支持的imageio类型——bmp、gif、jpeg(jpg)、png等,就 是 没 有 tif !!!

    所以就有了解决的方向——导入tif的imageio,需要的jar包有3个jai_codec、jai_core、jai_imageio

    导入3个jar包后,对工具类进行测试,发现不报异常了,图像也正确切割了

    原本到此应该就已经结束了,但是。。。

    放到web项目中又报出了NoSuchElementException的异常

    于是又是一顿搜索和实验,终于找到了正解——要在迭代器中注册tif的imageio类

    IIORegistry registry = IIORegistry.getDefaultInstance();  
    registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi());  
    registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi());

    加上这段代码后,在web中终于不会报异常了

    所以最后的图片工具类就变成了这样

    import java.awt.Rectangle;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.FileInputStream;
    import java.util.Iterator;
    
    import javax.imageio.ImageIO;
    import javax.imageio.ImageReadParam;
    import javax.imageio.ImageReader;
    import javax.imageio.spi.IIORegistry;
    import javax.imageio.stream.ImageInputStream;
    
    public class ImageUtil {
    
        private ImageUtil() {
        }
        
        static {
            IIORegistry registry = IIORegistry.getDefaultInstance();  
            registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi());  
            registry.registerServiceProvider(new com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi());
        }
    
        /**
         * 裁剪图像
         * 
         * @param x,y 起始点
         * @param width,height 宽高
         * @param srcpath 被裁减图像路径
         * @param subpath 裁剪后保存路径
         * @param type 图像类型
         * @throws Exception
         */
        public static void cut(int x, int y, int width, int height, String srcpath,
                String subpath, String type) throws Exception {
            FileInputStream is = null;
            ImageInputStream iis = null;
            try {
                // 读取图片文件
                is = new FileInputStream(srcpath);
                Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(type);
                ImageReader reader = it.next();
                // 获取图片流
                iis = ImageIO.createImageInputStream(is);
                reader.setInput(iis, true);
                ImageReadParam param = reader.getDefaultReadParam();
                Rectangle rect = new Rectangle(x, y, width, height);
                // 提供一个 BufferedImage,将其用作解码像素数据的目标。
                param.setSourceRegion(rect);
                BufferedImage bi = reader.read(0, param);
                ImageIO.write(bi, type, new File(subpath));
            } finally {
                if (is != null)
                    is.close();
                if (iis != null)
                    iis.close();
            }
        }
    
        /**
         * 获取图像真实类型
         * 
         * @param path 图像路径
         * @return 图像类型
         * @throws Exception
         */
        public static String getTypeByStream(String path) throws Exception {
            FileInputStream is = new FileInputStream(path);
            String type = "";
            byte[] b = new byte[4];
            try {
                is.read(b, 0, b.length);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (null != is) {
                    is.close();
                }
            }
            type = bytesToHexString(b).toUpperCase();
            if (type.contains("FFD8FF")) {
                return "jpg";
            } else if (type.contains("89504E47")) {
                return "png";
            } else if (type.contains("47494638")) {
                return "gif";
            } else if (type.contains("49492A00")) {
                return "tif";
            } else if (type.contains("424D")) {
                return "bmp";
            }
            return type;
        }
    
        /**
         * byte数组转换成16进制字符串
         * 
         * @param src
         * @return
         */
        private static String bytesToHexString(byte[] src) {
            StringBuilder stringBuilder = new StringBuilder();
            if (src == null || src.length <= 0) {
                return null;
            }
            for (int i = 0; i < src.length; i++) {
                int v = src[i] & 0xFF;
                String hv = Integer.toHexString(v);
                if (hv.length() < 2) {
                    stringBuilder.append(0);
                }
                stringBuilder.append(hv);
            }
            return stringBuilder.toString();
        }
    
    }
    ImageUtil

    和初始的工具类相比没什么太多的变动。。。

    最后是3个包的下载地址 https://gitee.com/shizuru/ImageUtil/tree/master

  • 相关阅读:
    C++ IO: File Read Write
    C++ 作用域与存储类型及预编译指令及文件结构
    Power Threading Library
    C++ 类和对象,继承,派生
    面试题:李白喝酒的问题
    计算机科学与技术 转
    [Buzz Today]2012.02.24
    [Buzz.Today]2013.03.28
    [Buzz.Today]2013.03.14
    [Tips] 网间流传的Document.ready实现
  • 原文地址:https://www.cnblogs.com/s1165482267/p/8717407.html
Copyright © 2020-2023  润新知