关于图片的一些知识

前言

首先安装MediaInfo Command line, 

MediaInfoLib - v19.04

Usage: "mediainfo [-Options...] FileName1 [Filename2...]"

这个工具对图片、视频的属性读取非常全面。对音视频图片等多媒体进行开发的时候是一个非常好的辅助工具。

示例:

这里可以知道图片的一些重要属性
格式:PNG
压缩算法:LZ77 (目前主流的无损数据压缩算法,https://zh.wikipedia.org/wiki/LZ77%E4%B8%8ELZ78)
宽度:825px
高度:525px
位深度:24bits (位深度为每个像素点可以支持显示的颜色数量,单位是bits,本图片可以显示2 ^ 24 = 16,777,216个颜色)
文件大小:419kb

图片在内存中的占用

图片显示在屏幕上时,其实是一种解码解压的过程,将图片放入内存中,然后再显示。

我们使用图片处理开源框架ImageMagick。采用C++编写,可以用来读、写和处理超过90种的图片文件,等有时间我发一个通过ImageMagick的离散傅里叶变换来实现磨皮降噪等效果的文章,当然openCV也可以,让技术变得简单了好多,傅里叶变换在多媒体处理上是很神奇的原理。

上面示例图片的大小是419kb,那么放入内存中占用的内存大小是多少呢?这个计算方式为:

imgWidth * imgHeight * (bit depth) / 8 = 825 * 525 * 24 / 8 = 1299375 字节

可以通过ImageMagick来验证一下是否正确,代码如下:

#include <iostream>
#include <fstream>
#include "Magick++.h"

using namespace Magick;
using namespace std;

int main(int argc, char** argv)
{
    Image image;
    try
    {
        InitializeMagick(*argv);
        image.read(argv[1]); //第一个参数是图片路径
        PixelData pxlsDat(image, argv[2], MagickCore::CharPixel); // 第二个参数是ColorSpace
        cout << " Bit depth is " << image.depth() << ", memory use is " << pxlsDat.size() << endl;
    }
    catch (Magick::Exception &error_)
    {
        cout << "Caught exception: " << error_.what() << endl; 
        return 1;
    }
    return 0;
}

关于第二个参数,其实可以通过identify -list format来查看支持的所有格式,如果查看图片的ColorSpace就使用
identify -verbose /path/to/image

我们可以查到上述图片Colorspace: sRGB

编译代码:

CXX = g++
CXXFLAGS = `Magick++-config --cxxflags --cppflags` -O2 -Wall
LIBS=`Magick++-config --ldflags --libs`
SRC = readImage.cpp
OBJFILES = readImage.o
TARGET = readImage

all: $(TARGET)
    @echo $(TARGET) build finished.
$(TARGET): $(OBJFILES)
    $(CXX) $(CXXFLAGS) -o $(TARGET) $(SRC) $(LIBS) 
clean:
    rm -f $(OBJFILES) $(TARGET) *~

运行./readImage /path/to/image "rgb"
Output:Bit depth is 8, memory use is 1299375

与我们之前计算的一样。419kb的图片内存占用1.2mb左右

引申:iOS对于大图片读取并显示的方法

iOS的framework对多媒体的API绝对要超级友好于Android,例如对视频的AVFoundation,CoreImage, vImage, CGImage, UIkit的图片处理转换等等,那是相当的丰富。

比如UIImage显示图片

- (void)showImageWithHardCore

{

    UIImage* tmpImage = [UIImage imageNamed:@"WX20180112-112352@2x.png"];

    _imgView.image = tmpImage;

}

图片使用一个170多MB的png,宽高都是1w多px的,结果Virtual Memory直接飙升至990多MB.

我们首先需要将图片的尺寸Downsampling到适合屏幕显示的图片,我们draw一下。

- (UIImage *)downsizeImage:(CGSize)size

{

    UIGraphicsBeginImageContextWithOptions(size, true, 1.0);

    [self drawInRect:CGRectMake(0, 0, size.width, size.height)];

    UIImage *downSizeImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return downSizeImage;

}

内存飙升后立即下降至40mb。

最后我们使用CGImage,这个方法也是苹果官方推荐的做法:

- (UIImage *)downsizeImage:(NSURL*)url toSize:(CGSize)size scale:(CGFloat)scale

{

    NSDictionary *imageSourceOptions = @{(id)kCGImageSourceShouldCache : @(NO)};

    CGImageSourceRef imageSourceRef = CGImageSourceCreateWithURL((__bridge CFURLRef)url, (__bridge CFDictionaryRef)imageSourceOptions);

    CGFloat maxDimensionInPixels = MAX(size.width, size.height) * scale;

    NSDictionary *downSizeOptions = @{(id)kCGImageSourceCreateThumbnailFromImageAlways : @(YES),

                                      (id)kCGImageSourceShouldCacheImmediately : @(YES),

                                      (id)kCGImageSourceCreateThumbnailWithTransform : @(YES),

                                      (id)kCGImageSourceThumbnailMaxPixelSize : @(maxDimensionInPixels)

                                      };

    CGImageRef downSizeImageRef = CGImageSourceCreateThumbnailAtIndex(imageSourceRef, 0, (__bridge CFDictionaryRef)downSizeOptions);

    UIImage *returnImage = [UIImage imageWithCGImage:downSizeImageRef];

    CGImageRelease(downSizeImageRef);

    CFRelease(imageSourceRef);

    return returnImage;

}

内存占用情况和drawrect的现象基本一致,但图片的显示速度要高于前者。

后记:图片的相似度对比,识别,盲水印等等都是图片的高级应用。我也在学习中。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值