关于在ios中使用png与jpg图片的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于在ios中使用png与jpg图片的区别相关的知识,希望对你有一定的参考价值。

参考技术A 关于png图片:

1.png有透明通道, jpg没有.png有手机硬解码加速 无损显示效果好

2.png加载速度快, 显示效果好

3.xcode也会对png图片进行优化,而不会对jpg图片进行优化.

4.png 在大图片的时候占用空间会比jpg大.

关于jpg图片:

1.高压缩率

2.适合扫描使用

JPG&PNG图片压缩java实现

最近项目中有一个需求是关于图片处理的,其实关于图片处理java的BufferedImage类基本上已经可以处理绝大多数需求,但是关于png图片的压缩遇到一点小的阻碍,我们知道png图片与JPG图片最大的区别就是可以保存为透明背景的图片,JPEG就不可以,jpeg是一种有损压缩的图片格式。png是可以转换成JPEG的,但是透明像素会变成白色的,而且图像信息会丢失一部分。png图片压缩起来比较困难。下面给出已经在项目中使用的静态方法实现这些需求。

1、图片文件生成BufferedImage对象:

    /**
     * @param file 图片
     * @return boolean true:符合要求
     * @description 图片文件转化为BufferedImage
     */
    public static BufferedImage fileToBufferedImage(File file) throws IOException 
        if (!file.exists()) 
            return null;
        
        BufferedImage bufferedImage = ImageIO.read(file);
        return bufferedImage;
    


    /**
     * @param fileByteArray
     * @return BufferedImage
     * @throws IOException
     * @description 图片文件字节数组转化为BufferedImage
     */
    public static BufferedImage fileToBufferedImage(byte[] fileByteArray) throws IOException 
        if (fileByteArray == null || fileByteArray.length == 0) 
            return null;
        
        ByteArrayInputStream stream = new ByteArrayInputStream(fileByteArray);
        BufferedImage bufferedImage = ImageIO.read(stream);
        return bufferedImage;
    

2、BufferedImage对象生成图片文件:有两个写法方式:1-简单方式,2-支持高质量压缩的方式

    /**
     * bufferedImage 转化为文件-简单方式
     * @param bufferedImage
     * @param destFile      获取目标路径
     * @param ext           图片的格式:jpg/png
     * @throws IOException
     */
    public static void bufferedImageToFile1(BufferedImage bufferedImage, String destFile, String ext) throws IOException 
        //使用ImageIO的方法进行输出,记得关闭资源
        OutputStream out = new FileOutputStream(destFile);
        ImageIO.write(bufferedImage, ext, out);
        out.close();
    

    /**
     * bufferedImage 转化为文件-高质量支持压缩的方式
     * @param bufferedImage
     * @param destFile      获取目标路径
     * @param ext           图片的格式:jpg/png
     * @throws IOException
     */
    public static void bufferedImageToFile2(BufferedImage bufferedImage, String destFile, String ext, float quality) throws IOException 
        Iterator<ImageWriter> imageWriterIter = ImageIO.getImageWritersByFormatName(ext);
        if (imageWriterIter.hasNext()) 
            ImageWriter writer = imageWriterIter.next();
            ImageWriteParam param = writer.getDefaultWriteParam();
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(quality);    //质量0-1.0
            File file = new File(destFile);
            FileImageOutputStream out = new FileImageOutputStream(file);
            writer.setOutput(out);
            writer.write(null, new IIOImage(bufferedImage, null, null), param);
            out.close();
            writer.dispose();
        

    

3、上面的压缩对于jpg和png图片,因为使用高质量的像素,会导致图片精度很高,图片比较大,现在提供对于jpg和png的图片的压缩代码

      对于jpg图片,我们不断降低压缩质量会较大幅度的降低图片大小,因为jpg图片是有损压缩,质量会降低的比较大,参考代码如下:

    /**
     * bufferedImage 目标将图片压缩到500KB以下,最多压缩5次
     * @param bufferedImage
     * @param ext       图片的格式
     * @param quality   默认1.0            
     * @throws IOException
     */
    public static byte[] bufferedImageToFileByte2Less500K(String tempFilePath, BufferedImage bufferedImage, String ext, float quality) throws IOException 
        Iterator<ImageWriter> imageWriterIter = ImageIO.getImageWritersByFormatName(ext);
        if (imageWriterIter.hasNext()) 
            ImageWriter writer = imageWriterIter.next();
            ImageWriteParam param = writer.getDefaultWriteParam();
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            System.out.println(quality);
            param.setCompressionQuality(quality);    //最高质量
            File file = new File(tempFilePath+ "/" + new Random().nextInt(10)  + "_temp_heap_image_" + quality + "."+ext);
            FileImageOutputStream out = new FileImageOutputStream(file);
            writer.setOutput(out);
            writer.write(null, new IIOImage(bufferedImage, null, null), param);
            ByteArrayOutputStream swapStream = getByteArrayOutputStream(file);
            out.close();
            writer.dispose();
            if(quality <=0.5f || swapStream.toByteArray().length/1024 <=500)
                return swapStream.toByteArray();
            else
                quality = quality - 0.1f;
                return bufferedImageToFileByte2Less500K(tempFilePath,bufferedImage,ext,quality);
            
        
        return null;
    

         上面的代码对于png图片,压缩的很有限,因为png是高质量图片,因此,我们要重新想办法,后来找到一个支持png压缩的工具包:OpenViewerFX,可以将png图片压缩的比较小,而且不怎么失真,代码如下:

        需要引入依赖:

    <dependency>
      <groupId>org.jpedal</groupId>
      <artifactId>OpenViewerFX</artifactId>
      <version>6.6.14</version>
    </dependency>
   /**
     * bufferedImage 转化为文件
     * @param bufferedImage
     * @param ext 图片的格式:png
     * @throws IOException
     */
    public static byte[] bufferedImageToFileByte(String tempFilePath, BufferedImage bufferedImage, String ext) throws IOException 
        //使用ImageIO的方法进行输出,记得关闭资源
        File file = new File(tempFilePath+ "/" + new Random().nextInt(10) + "_temp_heap_image."+ext);
        OutputStream out = new FileOutputStream(file);
        ImageIO.write(bufferedImage, ext, out);
        out.close();
        ByteArrayOutputStream swapStream = getByteArrayOutputStream(file);
        //对于图片是jpg或者小于500KB,就直接输出
        if(ext.equalsIgnoreCase("jpg") || swapStream.toByteArray().length/1024 <=500)
            return swapStream.toByteArray();
        
        File compressOutFile=new File(tempFilePath+ "/" + new Random().nextInt(10) + "_temp_heap_image_cp."+ext);
        //如果图片是png,且大于500KB,则进行压缩
        PngCompressor.compress(file,compressOutFile);
        swapStream = getByteArrayOutputStream(compressOutFile);
        return swapStream.toByteArray();
    

下面再提供一些工具类:

    /**
     * @param file        图片
     * @param imageWidth  宽
     * @param imageHeight 高
     * @return boolean true:符合要求
     * @description 校验图片比例
     */
    public static boolean checkImageScale(File file, int imageWidth, int imageHeight) throws IOException 

        Boolean result = false;
        if (!file.exists()) 
            return false;
        
        BufferedImage bufferedImage = ImageIO.read(file);
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();
        if (imageHeight != 0 && height != 0) 
            int scale1 = imageHeight / imageWidth;
            int scale2 = height / width;
            if (scale1 == scale2) 
                result = true;
            
        
        return result;
    


    /**
     * @param path 图片路径
     * @return java.lang.String base64字符串
     * @description 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
     */
    public static String imgToBase64Str(String path) throws IOException 
        byte[] data = null;
        // 读取图片字节数组
        InputStream in = null;
        try 
            in = new FileInputStream(path);
            data = new byte[in.available()];
            in.read(data);
         finally 
            if (in != null) 
                try 
                    in.close();
                 catch (IOException e) 
                    e.printStackTrace();
                
            
        
        //返回Base64编码过的字节数组字符串
        return Base64.encodeBase64String(data);
    


    /**
     * 按比例对图片进行缩放
     * @param scale 图片根据比例缩放
     * @throws IOException
     */
    public static BufferedImage zoomByScale(BufferedImage bufferedImage, double scale) throws IOException 

        //获取图片的长和宽
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();

        //获取缩放后的长和宽
        int _width = (int) (scale * width);
        int _height = (int) (scale * height);

        //获取缩放后的Image对象
        Image _img = bufferedImage.getScaledInstance(_width, _height, Image.SCALE_DEFAULT);

        //新建一个和Image对象相同大小的画布:BufferedImage.TYPE_INT_ARGB
        BufferedImage image = new BufferedImage(_width, _height, BufferedImage.TYPE_INT_ARGB);
        //获取画笔
        Graphics2D graphics = image.createGraphics();
        //将Image对象画在画布上,最后一个参数,ImageObserver:接收有关 Image 信息通知的异步更新接口,没用到直接传空
        graphics.drawImage(_img, 0, 0, null);
        //释放资源
        graphics.dispose();

        return image;

    

    /**
     * png -支持图片背景透明
     * 图片指定长和宽对图片进行缩放
     * @param width  长
     * @param height 宽
     * @throws IOException
     */
    public static BufferedImage zoomBySize(BufferedImage bufferedImage, int width, int height) 
        //与按比例缩放的不同只在于,不需要获取新的长和宽,其余相同.
        Image _img = bufferedImage.getScaledInstance(width, height, Image.SCALE_DEFAULT);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics = image.createGraphics();
        graphics.drawImage(_img, 0, 0, null);
        graphics.dispose();
        return image;
    

    /**
     * @param background 背景
     * @param foreground 前景
     * @param x 前景x坐标
     * @param y 前景y坐标
     * @return
     * @description 将前景图片合成到背景图上
     */
    public static BufferedImage compose(BufferedImage background, BufferedImage foreground, int x, int y) 
        try 
            Graphics2D g = background.createGraphics();
            g.drawImage(foreground, x, y, foreground.getWidth(), foreground.getHeight(), null);
            g.dispose();
         catch (Exception e) 
            System.out.println(e.getMessage());
        
        return background;

    


    /**
     * 裁剪png图片的非透明区域,使用最大x和y的边框
     * @param bufferedImage
     * @return
     * @throws IOException
     */
    public static BufferedImage getNotTransparentArea(BufferedImage bufferedImage) throws IOException 

        int w = bufferedImage.getWidth();
        int h = bufferedImage.getHeight();
        int x = 0, y = 0, width = 0, height = 0;
        for (int j = 0; j < h; j++) 
            for (int i = 0; i < w; i++) 
                int dip = bufferedImage.getRGB(i, j);
                if ((dip & 0xff000000) != 0) 
                    if (x == 0 || i < x) 
                        x = i;
                    
                    if (y == 0 || j < y) 
                        y = j;
                    
                    if (width == 0 || i > width) 
                        width = i;
                    
                    if (height == 0 || j > height) 
                        height = j;
                    
                
            
        
        bufferedImage = bufferedImage.getSubimage(x - 1, y - 1, width - x + 1, height - y + 1);
        return bufferedImage;
    

以上是关于关于在ios中使用png与jpg图片的区别的主要内容,如果未能解决你的问题,请参考以下文章

JPG&PNG图片压缩java实现

JPG&PNG图片压缩java实现

gif/jpg/png 图片格式 简单对比

转jpg png区别和使用

IOS开发之Bug--关于UIImageView的使用

IOS图片压缩(PNG压缩 JPEG压缩 非UIImageJPEGRepresentation)