我们都把一个图片信息转换成字符数组
只需要调用ImageIO中的write方法
设置好Image对象,输出格式Format 输出目标--output
把其中的输出目标output用我们需要的ByteArryOutputStream来实现就可以完成了
ImageIO默认的write方法
能支持各种类型的Format
但是当我们需要限制输出的文件大小的时候
ImageIO中实现的write方法就有些力不从心了
在我们的远程监控系统实施过程中
如果要用UDP组播来实现屏幕的传送
又必须把BufferedImage变为64KB一下的一个文件
所以
我们就必须要想办法把一个图片按质量压缩
并且用byte[]的形式来保存压缩好的数据
以便在网络中传输
昨天百度了又google
google了又百度
忙活了半天
还是没找到合适的相关方法
(再一次体现自己查资料能力的问题,下篇日志总结资料搜集的方法)
最后好不容易进了个英文网站
勉强看懂了作者的意思
现在把自己实现的代码及思路小结一下
首先,如前所述
ImageIO虽然能支持选定格式的输出
但是不能自己设置质量
上网查了有关图片格式相关信息后
得到
gif是目前无损压缩做的比较好的
jpeg能支持多种格式程度的压缩方式
压缩效果较好
昨天的测试代码已经表明了
一个截屏保存为GIF的时候
打包成字符数组需要大概2S,图片大小大概为100KB
ImageIO默认的Jpg格式 压缩大概0.5S 图片大小大概200KB
现在我们开始实现按给定压缩质量压缩文件成JPEG的代码
/**
*
* 自己设置压缩质量来把图片压缩成byte[]
* @param image
* 压缩源图片
* @param quality
* 压缩质量,在0-1之间,
* @return 返回的字节数组
*/
private byte[] bufferedImageTobytes(Image image, float quality) {
System.out.println(quality+"质量开始打包"+getCurrentTime());
//如果图片空,返回空
if (image == null) {
return null;
}
// 重新设定图片的宽和高
BufferedImage bImage = new BufferedImage(image.getWidth(null), image
.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics bg = bImage.getGraphics();
bg.drawImage(image, 0, 0, null);
bg.dispose();
// 得到指定Format图片的writer
Iterator<ImageWriter> iter = ImageIO
.getImageWritersByFormatName("jpeg");// 得到迭代器
ImageWriter writer = (ImageWriter) iter.next(); // 得到writer
// 得到指定writer的输出参数设置(ImageWriteParam )
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // 设置可否压缩
iwp.setCompressionQuality(quality); // 设置压缩质量参数
iwp.setProgressiveMode(ImageWriteParam.MODE_DISABLED );
ColorModel colorModel = ColorModel.getRGBdefault();
// 指定压缩时使用的色彩模式
iwp.setDestinationType(
new javax.imageio.ImageTypeSpecifier(
colorModel,
colorModel.createCompatibleSampleModel(16, 16)) );
// 开始打包图片,写入byte[]
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // 取得内存输出流
IIOImage iIamge = new IIOImage(bImage, null, null);
try {
//此处因为ImageWriter中用来接收write信息的output要求必须是ImageOutput
//通过ImageIo中的静态方法,得到byteArrayOutputStream的ImageOutput
writer.setOutput(ImageIO.createImageOutputStream(byteArrayOutputStream));
writer.write(null, iIamge, iwp);
} catch (IOException e) {
System.out.println("write errro");
e.printStackTrace();
}
System.out.println(quality+"质量完成打包-----"+getCurrentTime()+"------size------"+byteArrayOutputStream.toByteArray().length);
return byteArrayOutputStream.toByteArray();
}
代码挺容易看懂的,难点主要在
//通过ImageIo中的静态方法,得到byteArrayOutputStream的ImageOutput
writer.setOutput(ImageIO.createImageOutputStream(byteArrayOutputStream));
为了从byteArrayOutputStream到ImageOutputStream画了我将近2个小时。。
代码出来了
现在我们开始用测试结果来展示各种新式图片的压缩时间、压缩后大小
压缩后图片内容
测试代码如下
package cn.mzd.newIM.test;
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
public class ImageSizeTest {
/**
* @param args
* @throws AWTException
*/
public void getImageSize() throws AWTException {
java.awt.Robot rb = new java.awt.Robot();
Dimension d = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
Rectangle rt = new Rectangle(0, 0, (int) d.getWidth(), (int) d
.getHeight());
for (int i = 0; i < 1000; i++) {
BufferedImage image = rb.createScreenCapture(rt);
bufferedImageTobytes(image,"gif");
bufferedImageTobytes(image,"jpeg");
bufferedImageTobytes(image,(float) 0.3);
}
}
/**
* 用Format对应格式中ImageIO默认参数把IMAGE打包成BYTE[]
* @param image
* @return
*/
private byte[] bufferedImageTobytes(BufferedImage image,String format) {
System.out.println(format+"格式开始打包"+getCurrentTime());
BufferedImage bImage = new BufferedImage(image.getWidth(null), image
.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics bg = bImage.getGraphics();
bg.drawImage(image, 0, 0, null);
bg.dispose();
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
ImageIO.write(bImage, format, out);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(format+"格式完成打包-----"+getCurrentTime()+"----lenth------"+out.toByteArray().length);
return out.toByteArray();
}
/**
*
* 自己设置压缩质量来把图片压缩成byte[]
* @param image
* 压缩源图片
* @param quality
* 压缩质量,在0-1之间,
* @return 返回的字节数组
*/
private byte[] bufferedImageTobytes(Image image, float quality) {
System.out.println("jpeg"+quality+"质量开始打包"+getCurrentTime());
//如果图片空,返回空
if (image == null) {
return null;
}
// 重新设定图片的宽和高
BufferedImage bImage = new BufferedImage(image.getWidth(null), image
.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics bg = bImage.getGraphics();
bg.drawImage(image, 0, 0, null);
bg.dispose();
// 得到指定Format图片的writer
Iterator<ImageWriter> iter = ImageIO
.getImageWritersByFormatName("jpeg");// 得到迭代器
ImageWriter writer = (ImageWriter) iter.next(); // 得到writer
// 得到指定writer的输出参数设置(ImageWriteParam )
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // 设置可否压缩
iwp.setCompressionQuality(quality); // 设置压缩质量参数
iwp.setProgressiveMode(ImageWriteParam.MODE_DISABLED );
ColorModel colorModel = ColorModel.getRGBdefault();
// 指定压缩时使用的色彩模式
iwp.setDestinationType(
new javax.imageio.ImageTypeSpecifier(
colorModel,
colorModel.createCompatibleSampleModel(16, 16)) );
// 开始打包图片,写入byte[]
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // 取得内存输出流
IIOImage iIamge = new IIOImage(bImage, null, null);
try {
//此处因为ImageWriter中用来接收write信息的output要求必须是ImageOutput
//通过ImageIo中的静态方法,得到byteArrayOutputStream的ImageOutput
writer.setOutput(ImageIO.createImageOutputStream(byteArrayOutputStream));
writer.write(null, iIamge, iwp);
} catch (IOException e) {
System.out.println("write errro");
e.printStackTrace();
}
System.out.println("jpeg"+quality+"质量完成打包-----"+getCurrentTime()+"----lenth----"+byteArrayOutputStream.toByteArray().length);
return byteArrayOutputStream.toByteArray();
}
/**
* 自己定义格式,得到当前系统时间
* @return
*/
private String getCurrentTime() {
Calendar c = new GregorianCalendar();
int hour = c.get(Calendar.HOUR_OF_DAY);
int min = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
int millsecond = c.get(Calendar.MILLISECOND);
String time = hour + "点" + min + "分" + second + "秒" + millsecond;
return time;
}
public static void main(String args[]) throws Exception {
ImageSizeTest test = new ImageSizeTest();
test.getImageSize();
}
}
gif格式开始打包22点44分2秒776
gif格式完成打包-----22点44分4秒219----lenth------88597
jpeg格式开始打包22点44分4秒220
jpeg格式完成打包-----22点44分4秒579----lenth------193017
jpeg0.03质量开始打包22点44分4秒581
jpeg0.03质量完成打包-----22点44分4秒860----lenth----55348
gif格式开始打包22点44分5秒19
gif格式完成打包-----22点44分6秒941----lenth------93604
jpeg格式开始打包22点44分6秒941
jpeg格式完成打包-----22点44分7秒451----lenth------210974
jpeg0.03质量开始打包22点44分7秒453
jpeg0.03质量完成打包-----22点44分7秒722----lenth----58728
gif格式开始打包22点44分7秒906
gif格式完成打包-----22点44分9秒234----lenth------120938
jpeg格式开始打包22点44分9秒234
jpeg格式完成打包-----22点44分9秒545----lenth------214277
jpeg0.03质量开始打包22点44分9秒546
jpeg0.03质量完成打包-----22点44分9秒801----lenth----57217
gif格式开始打包22点44分9秒927
gif格式完成打包-----22点44分11秒395----lenth------133633
jpeg格式开始打包22点44分11秒397
jpeg格式完成打包-----22点44分11秒884----lenth------262952
jpeg0.03质量开始打包22点44分11秒885
jpeg0.03质量完成打包-----22点44分12秒286----lenth----65639
gif格式开始打包22点44分12秒458
gif格式完成打包-----22点44分14秒321----lenth------135386
jpeg格式开始打包22点44分14秒322
jpeg格式完成打包-----22点44分14秒823----lenth------262394
jpeg0.03质量开始打包22点44分14秒824
jpeg0.03质量完成打包-----22点44分15秒233----lenth----65774
gif格式开始打包22点44分15秒432
gif格式完成打包-----22点44分17秒297----lenth------137548
jpeg格式开始打包22点44分17秒299
jpeg格式完成打包-----22点44分17秒786----lenth------272242
jpeg0.03质量开始打包22点44分17秒787
jpeg0.03质量完成打包-----22点44分18秒192----lenth----67039
gif格式开始打包22点44分18秒367
gif格式完成打包-----22点44分20秒201----lenth------138447
jpeg格式开始打包22点44分20秒201
jpeg格式完成打包-----22点44分20秒732----lenth------272076
jpeg0.03质量开始打包22点44分20秒733
jpeg0.03质量完成打包-----22点44分21秒134----lenth----66780
gif格式开始打包22点44分21秒277
gif格式完成打包-----22点44分22秒453----lenth------98671
jpeg格式开始打包22点44分22秒453
jpeg格式完成打包-----22点44分22秒762----lenth------227669
jpeg0.03质量开始打包22点44分22秒764
jpeg0.03质量完成打包-----22点44分23秒28----lenth----61676
jpeg压缩只有当质量为0.03时,才能达到满足效果的小于64KB
而0.03是什么概念呢?
压缩质量是从0-1的一个数,0表示最小
而0。03………………………………………………
图片几乎看不清楚。。。。
应该是不符合我们的传输要求的
所以,本次试验
还是以失败告终
从本次试验中
学到的东西
1.其实API没那么难看懂 其实英文网站可以读懂
2.教会了我查资料应该怎么下手,如何确定自己需要的到底是什么
3.读了很多API 也算是个成长吧。。
恩
还有
明白了图片格式,储存,压缩大概是怎么回事
分享到:
相关推荐
- `q`:JPEG质量因子(0~100),数值越小,图像压缩程度越高,质量越差。 - **示例**: - `imwrite(f, 'output.tif')`:保存为TIFF格式。 - `imwrite(f, 'output.jpg', 'quality', 80)`:保存为JPEG格式,质量...
实例92 字母大小写转换 120 实例93 去除多余的空白 120 实例94 原始数组类型的String形式 121 实例95 Java合法标识符 122 实例96 显示一周各星期的名称 123 实例97 构造空心方框 124 实例98 这...
实例92 字母大小写转换 120 实例93 去除多余的空白 120 实例94 原始数组类型的String形式 121 实例95 Java合法标识符 122 实例96 显示一周各星期的名称 123 实例97 构造空心方框 124 实例98 这一天是星期几 125 实例...
实例92 字母大小写转换 120 实例93 去除多余的空白 120 实例94 原始数组类型的String形式 121 实例95 Java合法标识符 122 实例96 显示一周各星期的名称 123 实例97 构造空心方框 124 实例...
实例92 字母大小写转换 120 实例93 去除多余的空白 120 实例94 原始数组类型的String形式 121 实例95 Java合法标识符 122 实例96 显示一周各星期的名称 123 实例97 构造空心方框 124 实例98 这一天是星期几 125 实例...
实例92 字母大小写转换 120 实例93 去除多余的空白 120 实例94 原始数组类型的String形式 121 实例95 Java合法标识符 122 实例96 显示一周各星期的名称 123 实例97 构造空心方框 124 实例98 这一天是星期几 ...
在PHP开发过程中,提高... 小结 以上就是提高 PHP 编程效率的 53 个要点,涵盖了从代码编写、数据库查询优化到服务器设置等多个方面。通过实施这些建议,开发者可以在很大程度上提高 PHP 应用程序的性能和可维护性。
公历转换为农历.ec 六六自用 模块.ec 六十四卦相.ec 关于窗口.ec 关于菜单的一些修改操作.ec 关机管理.ec 关联.ec 关联 数据库和新表格.ec 关联文件.ec 关联程序.ec 关闭托盘图标.ec 关闭窗口或进程.ec 内存专用模块...
公历转换为农历.ec 六六自用 模块.ec 六十四卦相.ec 关于窗口.ec 关于菜单的一些修改操作.ec 关机管理.ec 关联.ec 关联 数据库和新表格.ec 关联文件.ec 关联程序.ec 关闭托盘图标.ec 关闭窗口或进程.ec 内存专用模块...
- **1.7.4 小结**:总结指针、数组和字符串的相关知识。 **1.8 多文件程序的结构** - **源文件与头文件**:源文件(.cpp)存放代码实现,头文件(.h)存放函数声明。 - **模块化设计**:通过将程序拆分成多个文件来...
- **应用场景**: 在软件工程中,可能指组成大型系统的小部件或模块。 - **相关概念**: - **Assembly Language (组合语言)**: 即汇编语言,是一种低级程序设计语言,每一指令对应计算机处理器的一条机器码指令。 ##...