Java压缩图片

目的

压缩分为有损压缩和无损压缩。我做的是有损压缩。只是将图片比如5M大小压到100K以内甚至是50K。为了更加快速的展示图片。

要求

	不要小看任何一个功能,可能看起来很简单,当做的的时候会遇到很多问题。

任务
(1)制作一个压缩的工具类。输入File file,输出File file 中间将图片缩小并按一定的规则命名并保存在同一级目录下。为了更加灵活还可以传入缩小后图片的宽高,还有不能将图片放大。传入文件是否是图片也要进行判断。
(2)将一服务器上所有图片都压缩一下,原图片保存,新图片以比如在原图片名称前面加thumbnail,就是thumbnail+file.getName.(实现方法可以在本地利用工具类写个main方法遍历某个文件夹下所有文件,是图片的就转一下。)

代码

工具类:ImgCompressUtil.java

public class ImgCompressUtil {
	private static Image img;
	private static int width;
	private static int height;

	public static void main(String[] args) throws Exception {
//		File file = new File("E:\\c4f31814503ebfa49d3a5 - 副本 (1).PNG");
//		File smallfile = ImgCompressUtil.imgComp(file, 0, 0);
		file 原始图片文件 		 smallfile 压缩后的图片文件
//		System.out.println(smallfile.getName());
	}

	/**
	 * <p>
	 * Title: isimg</p>
	 * <p>
	 * Description:// 通过ImageReader来解码这个file并返回一个BufferedImage对象 //
	 * 如果找不到合适的ImageReader则会返回null,我们可以认为这不是图片文件 // 或者在解析过程中报错,也返回false </p>
	 * 
	 * @param file
	 * @return
	 * @author yuh
	 */
	public static boolean isimg(File file) {
		try {
			Image image = ImageIO.read(file);
			img = ImageIO.read(file); // 构造Image对象
			width = img.getWidth(null); // 得到源图宽
			height = img.getHeight(null); // 得到源图长
			return image != null;
		} catch (Exception ex) {
			return false;
		}
	}

	/**
	 * 强制压缩/放大图片到固定的大小
	 * 
	 * @param w int 新宽度
	 * @param h int 新高度
	 * @return
	 */
	@SuppressWarnings("restriction")
	public static File resize(File file, int w, int h) throws IOException {
		// SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的 优先级比速度高 生成的图片质量比较好 但速度慢
		BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
		image.getGraphics().drawImage(img, 0, 0, w, h, null); // 绘制缩小后的图
		File destFile = new File(file.getPath().substring(0, file.getPath().lastIndexOf(".")) + "_small"+file.getName().substring(file.getName().lastIndexOf(".")));
		FileOutputStream out = new FileOutputStream(destFile); // 输出到文件流
		// 可以正常实现bmp、png、gif转jpg
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		encoder.encode(image); // JPEG编码
		out.close();
		return destFile;
	}

	/**
	 * 
	 * <p>
	 * Title: imgComp</p>
	 * <p>
	 * Description: 对图片进行压缩返回small图片,默认宽高可以传0,默认宽高为500</p>
	 * 
	 * @param file File 原始图片
	 * @param w    int 新宽度
	 * @param h    int 新高度
	 * @return file File 缩略图 返回null,转换失败
	 * @author yuh
	 */
	public static File imgComp(File file, int w, int h) {
		if (isimg(file)) {
			if (w == 0) {
				w = 300;
			}
			if (h == 0) {
				h = 300;
			}
			System.out.println("开始:" + new Date().toString());
			try {
				if(width>=w && height>=h) {
					if (width / height > w / h) {
						h = (int) (height * w / width);
					} else {
						w = (int) (width * h / height);
					}
				}else {
					w=width;
					h=height;		
				}
				System.out.println("结束:" + new Date().toString());
				return resize(file, w, h);
			} catch (Exception e) {
				return null;
			}
		} else {
			System.out.println("结束:文件格式有误");
			return null;
		}

	}

}

中间遇到的问题

转换开始是没有问题的。我转过BMP、JPG、JPEG、PNG、GIF。
转换过程中遇到一个转不了的图片开始是PNG,后来改成上面任何格式图片都不行。转换是报错如下

Exception in thread "main" java.lang.IllegalArgumentException: Numbers of source Raster bands and source color space components do not match
	at java.awt.image.ColorConvertOp.filter(ColorConvertOp.java:482)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.acceptPixels(JPEGImageReader.java:1268)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1236)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1039)

java - IllegalArgumentException:源栅格波段和源颜色空间组件的数量不匹配对于彩色图像异常
此图像阅读器试图对JPEG错误宽容,并且比标准Java JPEGImageReader稍微强大。但是,您的JPEG文件似乎有许多问题,因此无法100%读取:首先,图像中的ICC颜色配置文件有4个颜色组件,而图像数据只有3个颜色组件(这导致你见的例外)。根本原因可能是糟糕的转换软件。异常原因(没办法,这种图片用这转不了).

虽然不能转但还是要复制一份与原图一样但名字要匹配的,不能只转一部分。不然数据会很混乱。

将一个文件夹下所有图片都压缩一边代码


import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import com.sun.image.codec.jpeg.*;


/**
 * <p>
 * Title: ImgCompressUtil</p>
 * <p>
 * Description:图片压缩处理。 调用imgComp方法即可参数file,width,height。 width,height可默认为0。
 * 例如File smallfile = ImgCompressUtil.imgComp(file, 0, 0);
 * 如果原始宽高比比新宽高比大则以新宽等比缩放,否则以新高等比缩放。</p>
 * 
 * @author yuh
 * @date 2019年3月12日
 */
public class ImgCompressUtil {
	private static Image img;
	private static int width;
	private static int height;

	public static void main(String[] args) throws Exception {
			getFileList("E:\\临时文件\\uploadimg");
//		File fi = new File("E:\\临时文件\\bbb6d9.jpg");
//			File file = new File("E:\\临时文件\\93f3bbb6d9.jpg");
//			File smallfile = ImgCompressUtil.imgComp(file, 0, 0);
//		file 原始图片文件 		 smallfile 压缩后的图片文件
//		System.out.println(smallfile.getName());
	}

	/**
	 * <p>
	 * Title: isimg</p>
	 * <p>
	 * Description:// 通过ImageReader来解码这个file并返回一个BufferedImage对象 //
	 * 如果找不到合适的ImageReader则会返回null,我们可以认为这不是图片文件 // 或者在解析过程中报错,也返回false </p>
	 * 
	 * @param file
	 * @return
	 * @author yuh
	 */
	public static boolean isimg(File file) {
		try {
			Image image = ImageIO.read(file);
			img = ImageIO.read(file); // 构造Image对象
			width = img.getWidth(null); // 得到源图宽
			height = img.getHeight(null); // 得到源图长
			return image != null;
		} catch (IOException ex) {
			return false;
		}
	}

	/**
	 * 强制压缩/放大图片到固定的大小
	 * 
	 * @param w int 新宽度
	 * @param h int 新高度
	 * @return
	 */
	@SuppressWarnings("restriction")
	public static File resize(File file, int w, int h) throws IOException {
		// SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的 优先级比速度高 生成的图片质量比较好 但速度慢
		BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
		image.getGraphics().drawImage(img, 0, 0, w, h, null); // 绘制缩小后的图
		File destFile = new File(file.getPath().substring(0, file.getPath().lastIndexOf(".")) + "_small"+file.getName().substring(file.getName().lastIndexOf(".")));
		FileOutputStream out = new FileOutputStream(destFile); // 输出到文件流
		// 可以正常实现bmp、png、gif转jpg
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		encoder.encode(image); // JPEG编码
		out.close();
		return destFile;
	}

	/**
	 * 
	 * <p>
	 * Title: imgComp</p>
	 * <p>
	 * Description: 对图片进行压缩返回small图片,默认宽高可以传0,默认宽高为500</p>
	 * 
	 * @param file File 原始图片
	 * @param w    int 新宽度
	 * @param h    int 新高度
	 * @return file File 缩略图
	 * @author yuh
	 */
	public static File imgComp(File file, int w, int h) {
		if (isimg(file)) {
			if (w == 0) {
				w = 300;
			}
			if (h == 0) {
				h = 300;
			}
			System.out.println("开始:" + new Date().toString());
			try {
				if(width>=w && height>=h) {
					if (width / height > w / h) {
						h = (int) (height * w / width);
					} else {
						w = (int) (width * h / height);
					}
				}else {
					w=width;
					h=height;		
				}
				System.out.println("结束:" + new Date().toString());
				return resize(file, w, h);
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
		} else {
			System.out.println("结束:文件格式有误");
			return null;
		}

	}
//	BMP、JPG、JPEG、PNG、GIF
	public static List<File> getFileList(String strPath) {
		File dir = new File(strPath);
		File[] files = dir.listFiles(); // 该文件目录下文件全部放入数组
//		for (int i = 0; i < files.length; i++) {
//			System.out.println(files[i].getPath());
//		}
		List<File> filelist = new ArrayList<File>();
		if (files != null) {
			boolean isEx = false; 
			for (int i = 0; i < files.length; i++) {
				String fileName = files[i].getName();
				if (files[i].isDirectory()) { // 判断是文件还是文件夹
					getFileList(files[i].getAbsolutePath()); // 获取文件绝对路径
				} else if (fileName.endsWith("BMP") || fileName.endsWith("JPG") || fileName.endsWith("JPEG")|| fileName.endsWith("PNG")|| fileName.endsWith("GIF") || fileName.endsWith("bmp") || fileName.endsWith("jpg") || fileName.endsWith("jpeg")|| fileName.endsWith("png")|| fileName.endsWith("gif")) { // 判断文件名是否以.avi结尾
					try {
						Image image = ImageIO.read(files[i]);
						String strFileName = files[i].getAbsolutePath();
						File smallfile = ImgCompressUtil.imgComp(files[i], 0, 0);
						System.out.println("---" + strFileName);
						filelist.add(files[i]);
					} catch (Exception e) {
						File destFile = new File(files[i].getPath().substring(0, files[i].getPath().lastIndexOf(".")) + "_small"+files[i].getName().substring(files[i].getName().lastIndexOf(".")));
						try {
							copyFile3( files[i].getPath(),destFile.getPath());
							System.out.println("copysuccess");
						} catch (IOException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
						isEx = true; 
						 continue;
					}
				} else {
					continue;
				}
			}

		}
		return filelist;
	}
/**
 * 复制
* <p>Title: copyFile3</p>
* <p>Description: </p>
* @param srcPath
* @param destPath
* @throws IOException
* @author yuh
 */
    public static void copyFile3(String srcPath, String destPath) throws IOException {
        
        // 打开输入流
        FileInputStream fis = new FileInputStream(srcPath);
        // 打开输出流
        FileOutputStream fos = new FileOutputStream(destPath);
        
        // 读取和写入信息
        int len = 0;
        // 创建一个字节数组,当做缓冲区
        byte[] b = new byte[1024];
        while ((len = fis.read(b)) != -1) {
            fos.write(b, 0, len);
        }
        
        // 关闭流  先开后关  后开先关
        fos.close(); // 后开先关
        fis.close(); // 先开后关
        
    }

}

因为用到了com.sun.image.codec.jpeg.*;问题

编译可能会报缺少程序包com.sun.image.codec.jpeg缺少,
我当时使用命令编译的(复习一下)
XXX.java在某个目录中,Shift+Ctrl+鼠标右键,在此处打开命令窗口,
输入:javac XXX.java 进行编译。success就会生成class文件
输入:Java XXX.class 执行。

Java项目将
将它设置为Warning即可
Maven项目
解决方法

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值