在一次做考试系统的时候,有一个场景是考生开考前需要通过系统做拍照并进行脸部信息的比对;脸部信息的计算使用FACE++(旷视科技)的接口,但是发现查看拍照的照片信息是,考生的照片显示十分模糊,对比度变低,有验证的泛红!经过检查发现报错在Oracle 数据库的blob 字段直接查看信息是正常的,再看看在程序里生成的图片缓存文件是模糊的图像;查看生成图片的代码,十分简单,如下:

//生成图片返回图片路径

public static String createImg(byte[] bytes,String imgName,String path){
StringBuilder fullPath = new StringBuilder(imgFile(path)).append(File.separator).append(imgName).append("."+ImgType);
File img = null;
try {
img = new File(fullPath.toString());
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
BufferedImage bi =ImageIO.read(bais);      
ImageIO.write(bi, ImgType, img);//
bais.close();
} catch (Exception e) {
e.printStackTrace();
}
return filePath+File.separator+imgName+"."+ImgType;
}

代码中只是简单的将图片的二进制信息写成了图片。

网上了解了一下图片生成的问题,在二进制转换成BufferedImage 对象时可以生成的图片指定BGR 颜色模型;查看BufferedImage 的API 发现有一个构造函数是需要传如图片的宽度、高度和预定义图像类型 BufferedImage(int width, int height, int imageType) ;

代码修改后,图片正常显示!代码如下:

public static String createImg(byte[] bytes,String imgName,String path){
StringBuilder fullPath = new StringBuilder(imgFile(path)).append(File.separator).append(imgName).append("."+ImgType);
File img = null;
try {
img = new File(fullPath.toString());
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
BufferedImage bi =ImageIO.read(bais);      
saveJpgImage(bi,fullPath.toString());
bais.close();
} catch (Exception e) {
e.printStackTrace();
}
return filePath+File.separator+imgName+"."+ImgType;
}

public static void saveJpgImage(BufferedImage image,  
String filePath) {  
BufferedImage bufferedImage = new BufferedImage(image.getWidth(), image  
.getHeight(), BufferedImage.TYPE_3BYTE_BGR);  
bufferedImage.getGraphics().drawImage(image, 0, 0, null);  
saveImage(bufferedImage, ImgType, filePath);  
}

public static void saveImage(BufferedImage image, String format,  
String filePath) {  
try {  
ImageIO.write(image, format, new File(filePath));  
} catch (Exception e) {  
throw new RuntimeException(e);  
}  
}

-------------------------------------------------------------------------------

以下是网上找到别人生成各种类型的图片的最终效果对比!

package test;  
  
import java.awt.Color;  
import java.awt.Font;  
import java.awt.Graphics2D;  
  
import java.awt.RenderingHints;  
import java.awt.image.BufferedImage;  
import java.io.BufferedOutputStream;  
import java.io.ByteArrayOutputStream;  
import java.io.File;  
import java.io.FileOutputStream;  
  
import javax.imageio.ImageIO;  
  
import java.util.Iterator;  
import javax.imageio.*;  
import javax.imageio.stream.*;  
  
import org.junit.Before;  
import org.junit.Test;  
  
/** 
 * 加载png格式图片,使用不同方式转为png或者jpg格式的性能对比。 
 * */  
public class PngJpgImagePerTest {  
  
    private static String PNG = "png";  
    private static String JPG = "jpg";  
  
    private static String SimpleSavePNG = "__SimpleSavePNG.png";  
    private static String Convert2ArrayAndSavePNG = "__Convert2ArrayAndSavePNG.png";  
    private static String NewImageSavePNG = "__NewPNG.png";  
    private static String NewImageSaveJPG = "__NewJPG.jpg";  
    private static String SaveJPG = "__JPG_quality.jpg";  
  
    /** 
     * 保存文件。 
     * */  
    public static void save2File(String filePath, byte[] data) {  
  
        BufferedOutputStream bufferOutput = null;  
  
        try {  
            bufferOutput = new BufferedOutputStream(new FileOutputStream(  
                    new File(filePath)), 1024);  
  
            bufferOutput.write(data);  
            bufferOutput.flush();  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        } finally {  
            if (bufferOutput != null) {  
                try {  
                    bufferOutput.close();  
                } catch (Exception e) {  
                    throw new RuntimeException(e);  
                }  
            }  
        }  
    }  
  
    /** 
     * load image 
     * */  
    public static BufferedImage loadImage(String filePath) {  
        try {  
            return ImageIO.read(new File(filePath));  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    }  
  
    /** 
     * simple save use ImageIO.write 
     */  
    public static void saveImage(BufferedImage image, String format,  
            String filePath) {  
        try {  
            ImageIO.write(image, format, new File(filePath));  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    }  
  
    /** 
     * convert to byte array. 
     * */  
    public static byte[] convert2bytes(BufferedImage image, String format) {  
        try {  
            ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);  
            ImageIO.write(image, format, bout);  
            byte[] data = bout.toByteArray();  
            return data;  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    }  
  
    /** 
     * create new buffer image and save using png format. 
     * */  
    public static void savePngImage(BufferedImage image, String format,  
            String filePath) {  
        BufferedImage bufferedImage = new BufferedImage(image.getWidth(), image  
                .getHeight(), BufferedImage.TYPE_3BYTE_BGR);  
        bufferedImage.getGraphics().drawImage(image, 0, 0, null);  
        saveImage(bufferedImage, PNG, filePath);  
    }  
  
    /** 
     * create new buffer image and save using jpg format. 
     * */  
    public static void saveJpgImage(BufferedImage image, String format,  
            String filePath) {  
        BufferedImage bufferedImage = new BufferedImage(image.getWidth(), image  
                .getHeight(), BufferedImage.TYPE_3BYTE_BGR);  
        bufferedImage.getGraphics().drawImage(image, 0, 0, null);  
        saveImage(bufferedImage, JPG, filePath);  
    }  
  
    /** 
     * save jpg with specified quality. 为了图片质量,quality的值不能太低。 
     * */  
    public static void saveImageUsingJPGWithQuality(BufferedImage image,  
            String filePath, float quality) throws Exception {  
  
        BufferedImage newBufferedImage = new BufferedImage(image.getWidth(),  
                image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);  
        newBufferedImage.getGraphics().drawImage(image, 0, 0, null);  
  
        Iterator<ImageWriter> iter = ImageIO  
                .getImageWritersByFormatName("jpeg");  
  
        ImageWriter imageWriter = iter.next();  
        ImageWriteParam iwp = imageWriter.getDefaultWriteParam();  
  
        iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);  
        iwp.setCompressionQuality(quality);  
  
        File file = new File(filePath);  
        FileImageOutputStream fileImageOutput = new FileImageOutputStream(file);  
        imageWriter.setOutput(fileImageOutput);  
        IIOImage iio_image = new IIOImage(newBufferedImage, null, null);  
        imageWriter.write(null, iio_image, iwp);  
        imageWriter.dispose();  
    }  
  
    public static void drawString(Graphics2D g2, String value, int x, int y) {  
        Font font = new Font("Arial", Font.BOLD, 16);  
        g2.setColor(Color.BLACK);  
        g2.setFont(font);  
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,  
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);  
        g2.drawString(value, x, y);  
    }  
  
    private String sourceFilePath;  
    private BufferedImage sourceImage;  
    private int loop;  
    private float quality;  
  
    @Before  
    public void setup() {  
        sourceFilePath = "E:\\allencode\\ImgTest\\stat.png";  
        sourceImage = loadImage(sourceFilePath);  
        loop = 10;  
        quality = 0.8F;  
        Graphics2D g2 = sourceImage.createGraphics();  
        draw(g2);  
    }  
  
    private void draw(Graphics2D g2) {  
        drawString(g2, "Allen Hello world.", 500, 200);  
    }  
  
    /** 
     * ImageIO.write存储图片时主要的性能消耗在计算上。 
     * */  
    @Test  
    public void test_01() {  
        StringBuilder sb = new StringBuilder();  
        for (int i = 0; i < loop; i++) {  
            long start = System.currentTimeMillis();  
            saveImage(sourceImage, PNG, sourceFilePath + SimpleSavePNG);  
            long end = System.currentTimeMillis();  
            sb.append(" saveImage = " + (end - start));  
  
            long convertStart = System.currentTimeMillis();  
            byte[] pngData = convert2bytes(sourceImage, PNG);  
            long convertEnd = System.currentTimeMillis();  
            sb.append(" convert = " + (convertEnd - convertStart));  
  
            long saveStart = System.currentTimeMillis();  
            save2File(sourceFilePath + Convert2ArrayAndSavePNG, pngData);  
            long saveEnd = System.currentTimeMillis();  
            sb.append(" save = " + (saveEnd - saveStart));  
  
            sb.append("\n");  
        }  
  
        System.out.println(sb);  
    }  
  
    /** 
     * ImageIO.write和新建一个BufferedImage,采用jpg或png保存的比较。 
     * */  
    @Test  
    public void test_02() {  
        StringBuilder sb = new StringBuilder();  
        for (int i = 0; i < loop; i++) {  
            long start = System.currentTimeMillis();  
            saveImage(sourceImage, PNG, sourceFilePath + SimpleSavePNG);  
            long end = System.currentTimeMillis();  
            sb.append(" saveImage = " + (end - start));  
  
            start = System.currentTimeMillis();  
            savePngImage(sourceImage, "png", sourceFilePath + NewImageSavePNG);  
            end = System.currentTimeMillis();  
            sb.append(" savePngImage = " + (end - start));  
  
            start = System.currentTimeMillis();  
            saveJpgImage(sourceImage, "jpg", sourceFilePath + NewImageSaveJPG);  
            end = System.currentTimeMillis();  
            sb.append(" saveJpgImage = " + (end - start));  
  
            sb.append("\n");  
        }  
  
        System.out.println(sb);  
    }  
  
    /** 
     * ImageIO.write存储图片和保存jpg的时间对比。 
     * */  
    @Test  
    public void test_03() throws Exception {  
        StringBuilder sb = new StringBuilder();  
        for (int i = 0; i < loop; i++) {  
            long pngStart = System.currentTimeMillis();  
            saveImage(sourceImage, PNG, sourceFilePath + SimpleSavePNG);  
            long pngEnd = System.currentTimeMillis();  
            sb.append(" saveImage = " + (pngEnd - pngStart));  
  
            long jpgStart = System.currentTimeMillis();  
            saveImageUsingJPGWithQuality(sourceImage, sourceFilePath + SaveJPG,  
                    quality);  
            long jpgEnd = System.currentTimeMillis();  
            sb.append(" JPGWithQuality = " + (jpgEnd - jpgStart));  
  
            sb.append(" % = " + (pngEnd - pngStart) * 1D / (jpgEnd - jpgStart));  
            sb.append("\n");  
        }  
  
        System.out.println(sb);  
    }  
}

Java生成图片时使用BufferedImage的构造方法,让图片不失真相关推荐

  1. java生成图片乱码_Centos下JAVA生成图片时字体乱码

    最近项目使用了spring boot构建服务,项目跑在Centos6和Centos7的系统上,项目中有一个使用JAVA生成png图片时中文会造成乱码. 由于网上找了N多的资料,最终才把问题解决.很多说 ...

  2. Java继承时构造函数的关系

    Java继承时构造函数的关系,先来一道笔试题给大家看看: 在继承中,关于构造方法的说明,下列说法错误的是() A.子类无条件的继承父类的无参构造方法, B.子类可以引用父类中的有参构造方法,使用sup ...

  3. JVM从入门到精通(五): Java运行时数据区和常用指令

    JVM Runtime Data Area and JVM Instructions Java运行时数据区以及JVM指令 i=i++结果为8 i=++i结果为9 一个class的生命周期 以下面的规范 ...

  4. Java干货(一)----Java重写时应当遵守的10条规则

    Java重写时应当遵守的10条规则 1.1 只能重写继承过来的方法, 1.1.1 但不能重写父类中的静态方法.构造方法.private修饰的方法.final修饰的方法 1.2 重写的方法必须有相同的参 ...

  5. java中构造方法只能有一个_对Java中类的构造方法描述正确的是()A.如果在类中没有定义,Java就提供一个默认的构造方法B.只能...

    对Java中类的构造方法描述正确的是()A.如果在类中没有定义,Java就提供一个默认的构造方法B.只能 更多相关问题 猛虎噬人卣是_______时期的陶塑代表作品. 静态网页是指网页的内容是固定的, ...

  6. Java生成图片工具类

    Java生成图片工具类 最初版本(仅提供思路,生成时间长,根据自己的需要自己优化) package com.xhpc.charging.station.utils.img;import java.aw ...

  7. 用java如何做图片验证码,运用java生成图片验证码

    使用java生成图片验证码 本程序来源以下网址:http://www.linux521.com/2009/java/200909/8475.html 仅供学习和参考 import java.awt.B ...

  8. oracle java rmi 漏洞,Oracle Java SE Java运行时环境RMI子组件远程漏洞(CVE-2011-3556)

    发布日期:2011-10-20 更新日期:2011-10-20 受影响系统: Oracle Sun JRE 1.6.x Oracle Sun JDK 1.6.x 不受影响系统: Oracle Sun ...

  9. Adobe flash cs5 的Java运行时环境初始化错误 完美解决方法

    Adobe flash cs5 的Java运行时环境初始化错误 完美解决方法 下载网络上的Adobe flash cs5 精简版(绿色版),Java运行时环境初始化时出现错误,你可能需要重装Flash ...

最新文章

  1. java 中线程的状态
  2. VS NuGet使用
  3. 关于tcp和http
  4. 成功解决ModuleNotFoundError: No module named 'keras_retinanet.utils.compute_overlap'
  5. 【Win32汇编】字符串逆序
  6. Linux 字符设备驱动开发基础(六)—— VFS 虚拟文件系统解析
  7. 解决去除“请输入有效值。两个最接近的有效值分别为1和2“提示
  8. [转]Python3之max key参数学习记录
  9. 清除图片下默认的小间隙_PowerMILL软件应用策略(一):模型区域清除策略
  10. 制作pip源(按需,非镜像方式)
  11. Gliffy Diagrams 安装问题
  12. apm系统服务器,apm系统
  13. 免费Web托管公司000Webhost被黑 1350万明文密码泄露
  14. 携程2016校园招聘笔试题分析
  15. 搜索和推荐中的精度和召回(recall)分别是什么意思?
  16. “消费盲返”为什么可以在短短几天迅速爆火?
  17. payjs插件php,基于payjs的discuz支付插件制作
  18. php 启动php-fpm,linux启动多个php-fpm
  19. ros语音识别:pocketsphinx_continuous工作正常而gst-pocketsphinx不能识别相同语音的问题。
  20. JDK1.6“新“特性Instrumentation之JavaAgent

热门文章

  1. 简明教程 | 用 PPT 做卡通热图 - eFP Graph?!
  2. Cadence OrCAD/PSpice 元件库列表及各个库文件详细说明
  3. 那些年,我走过的场子!
  4. C++ 23种设计模式
  5. 蓝桥杯-平方和(java)
  6. 华为余承东称华为P30系列将重写规则
  7. echarts文字换行----淘干货找坏男人
  8. 怎样快速将pdf转换成txt格式
  9. 如何将一个网页文件设置为屏幕保护程序
  10. XShell命令查看进程