图片 订阅
图片是指由图形、图像等构成的平面媒体。图片的格式很多,但总体上可以分为点阵图和矢量图两大类,我们常用BMP、JPG等格式都是点阵图形,而SWF、CDR、AI等格式的图形属于矢量图形。有形式的事物,我们看到的,是图画、照片、拓片等的统称。图是技术制图中的基础术语,指用点、线、符号、文字和数字等描绘事物几何特征、形态、位置及大小的一种形式。随着数字采集技术和信号处理理论的发展,越来越多的图片以数字形式存储。 展开全文
图片是指由图形、图像等构成的平面媒体。图片的格式很多,但总体上可以分为点阵图和矢量图两大类,我们常用BMP、JPG等格式都是点阵图形,而SWF、CDR、AI等格式的图形属于矢量图形。有形式的事物,我们看到的,是图画、照片、拓片等的统称。图是技术制图中的基础术语,指用点、线、符号、文字和数字等描绘事物几何特征、形态、位置及大小的一种形式。随着数字采集技术和信号处理理论的发展,越来越多的图片以数字形式存储。
信息
类    属
平面媒体
类    型
点阵图和矢量图
中文名
图片
外文名
Picture
图片词语概念
词典解释图:技术制图中的基础术语, 图片(80张) 指用点、线、符号、文字和数字等描绘事物几何特征、形态、位置及大小的一种形式(注意,是一种形式)。片:名词,又如:唱片、画片、相片、影片、片石(片状石料)、木片、玉兰片、虾片、名片、瓦片……(简述的是有形的一种事物)。
收起全文
精华内容
参与话题
问答
  • js 特效 图片滚动 渐变 多张图片滚动js 特效 图片滚动 渐变 多张图片滚动js 特效 图片滚动 渐变 多张图片滚动js 特效 图片滚动 渐变 多张图片滚动js 特效 图片滚动 渐变 多张图片滚动js 特效 图片滚动 渐变 多张图片...
  • 背景图片

    2020-05-15 14:44:13
  • 各种图片编码格式详解(bmp,jpg,png)

    万次阅读 2019-04-11 19:44:19
    做了几年有关图形、图像的工作,对图片格式算是小有经验,在此写成一文章总结下。虽然一开始并不想讲很理论的东西,但写完后发现几乎全是理论,细想一下关于图片格式的知识本身就是理论的东西,囧~~ 那就力求用最...

    图像基本数据结构

     要讲图片格式还先得从图像的基本数据结构说起。在计算机中, 图像是由一个个像素点组成,像素点就是颜色点,而颜色最简单的方式就是用RGB或RGBA表示, 如图所示

     

    (图1)

    (图2)

    如果有A通道就表明这个图像可以有透明效果。

    R,G,B每个分量一般是用一个字节(8位)来表示,所以图(1)中每个像素大小就是3*8=24位图, 而图(2)中每个像素大小是4*8=32位。

    这里有三点需要说明:

    一、图像y方向正立或倒立

    图像是二维数据,数据在内存中只能一维存储,二维转一维有不同的对应方式。比较常见的只有两种方式: 按像素“行排列”从上往下或者从下往上。

    如图所示的图像有9个像素点,如果从上往下排列成一维数据是(123456789), 如果是从下往上排列则为(789456123)。
    只所以会有这种区别是因为,前一种是以计算机图形学的屏幕坐标系为参考(右上为原点,y轴向下 ),而另后一种是以标准的数学坐标系为参考(右下为原点,y轴向上)。这两个坐标系只是y值不一样,互相转换的公式为:

    y2 = height-1-y1

    y1,y2分别为像素在两个坐标系中的y坐标,height为图像的高度。

    不过好像只有bmp图片格式以及windows下的GDI,GDI+是从下往上排列,其它比如DirectX,OpenGL,Cocoa(NSImage, UIImage),OpenCV等都是从上往下排列。

    二、RGB排列顺序

    不同图形库中每个像素点中RGBA的排序顺序可能不一样。上面说过像素一般会有RGB,或RGBA四个分量,那么在内存中RGB的排列就有6种情况,如下:

    • RGB
    • RBG
    • GRB
    • GBR
    • BGR
    • BRG

    RGBA的排列有24种情况,这里就不全部列出来了。
    不过一般只会有RGB,BGR, RGBA, RGBA, BGRA这几种排列据。 绝大多数图形库或环境是BGR/BGRA排列,cocoa中的NSImage或UIImage是RGBA排列。

    三、像素32位对齐

    如果是RGB24位图,会存在一个32位对齐的问题——
    在x86体系下,cpu一次处理32整数倍的数据会更快,图像处理中经常会按行为单位来处理像素。24位图,宽度不是4的倍数时,其行字节数将不是32整数倍。这时可以采取在行尾添加冗余数据的方式,使其行字节数为32的倍数。
    比如,如果图像宽为5像素,不做32位对齐的话,其行位数为24*5=120,120不是32的倍数。是32整数倍并且刚好比120大的数是128,也就只需要在其行尾添加1字节(8位)的冗余数据即可。(一个以空间换时间的例子)
    有个公式可以轻松计算出32位对齐后每行应该占的字节数

    byteNum = ((width * 24 + 31) & ~31)>>3;

    注意结果是字节数,如果想知道位数,还得x8

    图片格式的必要性

    如果将图像原始格式直接存储到文件中将会非常大,比如一个5000*5000 24位图,所占文件大小为5000*5000*3字节=71.5MB, 其大小非常可观。
    如果用zip或rar之类的通用算法来压缩像素数据,得到的压缩比例通常不会太高,因为这些压缩算法没有针对图像数据结构进行特殊处理。
    于是就有了jpeg,png等格式,同样是图像压缩算法jpeg和png也有不同的适用场景,具体在下文再阐述。

    所以可以总结如下: jpeg,png文件之于图像,就相当于zip,rar格式之于普通文件(用zip,rar格式对普通文件进行压缩)

    BMP格式

    bmp格式没有压缩像素格式,存储在文件中时先有文件头、再图像头、后面就都是像素数据了,上下颠倒存储。
    用windows自带的mspaint工具保存bmp格式时,可以发现有四种bmp可供选择:
    单色: 一个像素只占一位,要么是0,要么是1,所以只能存储黑白信息
    16色位图: 一个像素4位,有16种颜色可选
    256色位图: 一个像素8位,有256种颜色可选
    24位位图: 就是图(1)所示的位图,颜色可有2^24种可选,对于人眼来说完全足够了。

    这里为了简单起见,只详细讨论最常见的24位图的bmp格式。

    现在来看其文件头和图片格式头的结构:

                           

    文件头信息
    字段 大小(字节) 描述 bfType  2 一定为19778,其转化为十六进制为0x4d42,对应的字符串为BM bfSize  4 文件大小  bfReserved1 2  一般为0   bfReserved2 2  一般为0   bfOffBits  4  从文件开始处到像素数据的偏移,也就是这两个结构体大小之和

     

    bmp图片结构头
     字段 大小(字节)  描述   biSize  4 此结构体的大小   biWidth  4  图像的宽 biHeight   4 图像的高  biPlanes   2 图像的帧数,一般为1  biBitCount   2 一像素所占的位数,一般是24 biCompression   4 一般为0  biSizeImage   4 像素数据所占大小,即上面结构体中文件大小减去偏移(bfSize-bfOffBits)  biXPelsPerMeter   4  一般为0 biXPelsPerMeter   4   一般为0 biClrUsed   4   一般为0 biClrImportant   4   一般为0

     

    本来在windows平台下wingdi.h文件中已经有这些结构的定义,不过为了不依赖与windows,实现为跨平台,本人将wingdi.h中的这两个结构“偷用”出来了。代码如下:

     1 //bmp文件头
     2 #pragma pack(push)
     3 #pragma pack(2)
     4     typedef struct tagBITMAPFILEHEADER {
     5         unsigned short bfType;      // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778
     6         unsigned int bfSize;        // 文件大小
     7         unsigned short bfReserved1; // 0
     8         unsigned short bfReserved2; // 0
     9         unsigned int bfOffBits;     // 从文件头到像素数据的偏移,也就是这两个结构体的大小之和
    10     } BITMAPFILEHEADER;
    11 #pragma pack(pop)
    12 
    13 //bmp图像头
    14 typedef struct tagBITMAPINFOHEADER {
    15     unsigned int biSize;        // 此结构体的大小
    16     int biWidth;                // 图像的宽
    17     int biHeight;               // 图像的高
    18     unsigned short biPlanes;    // 1
    19     unsigned short biBitCount;  // 24
    20     unsigned int biCompression; // 0
    21     unsigned int biSizeImage;   // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits
    22     int biXPelsPerMeter;        // 0
    23     int biYPelsPerMeter;        // 0
    24     unsigned int biClrUsed;     // 0 
    25     unsigned int biClrImportant;// 0
    26 } BITMAPINFOHEADER;
    Bmp结构体

    由于bmp格式比较简单,本人已实现了一份简单的c++代码,具有读取、保存bmp图片的功能,只支持24位的bmp格式。

    代码在 http://git.oschina.net/xiangism/blogData 的“常见图片格式详解/ImageDemo/BmpDemo”文件夹中。

    虽然这里只建立了vs2008项目,但代码在linux, mac平台下都可以编译通过。

    需要说明的是为了统一处理,将bmp读取到LBitmap::m_pixel中时就将其转化为32位从上往下排列的图像格式了。并且会有y坐标的转化。
    所以在读取的时候会有一个temp_line先存储文件中的24位数据,再转化为32位数据。在保存时也是先将32位数据转化到temp_line的24位数据上,然后再写入文件。(如果仅仅是处理bmp,那么这么多的一个A通道是冗余数据,但后面处理png图片时就会用到这个A通道)

    如果用上面的代码来读取如图所示的图片(放大8倍后的显示图):

     


    右上角像素为RGB(255, 128, 0)

    1 ln::LBitmap bmp;
    2 bmp.ReadBmp(L"one.bmp");
    3 unsigned char *p = bmp.Pixel(0, 0);
    4 printf("%d, %d, %d\n", p[0], p[1], p[2]); //显示左上角的像素值
    5 bmp.WriteBmp(L"out.bmp");                 //保存到文件,可以测试是否能正确读取和保存bmp

    运行的结果为: 0,128,255
    可以看出像素分布为BGR

    ps:

    • bmp格式也是可以压缩.
    • bmp格式也可以有颜色板。颜色板就是一个颜色的索引,上面说过bmp格式一个像素可以只有2个,16个或256个取值。就拿单色位图来说明,默认为0对应RGB(0,0,0) 1,对应RGB(255, 255, 255)
      如果颜色板这样定义: 
      0对应 RGB(255,0, 0)红
      1对应 RGB(0, 255, 0)绿
      这样黑白图就成了红绿图

    JPEG格式

    1. jpeg是有损压缩格式, 将像素信息用jpeg保存成文件再读取出来,其中某些像素值会有少许变化。在保存时有个质量参数可在[0,100]之间选择,参数越大图片就越保真,但图片的体积也就越大。一般情况下选择70或80就足够了。
    2. jpeg没有透明信息。
    3. jpeg比较适合用来存储相机拍出来的照片,这类图像用jpeg压缩后的体积比较小。其使用的具体算法核心是离散余弦变换、Huffman编码、算术编码等技术,有兴趣的同学可以在网上找一大堆资料,本文就不详细介绍了。

    接下来要介绍一个有关jpeg非常实用的技术——
    jpeg格式支持不完全读取整张图片,即可以选择读取原图、1/2、1/4、1/8大小的图片
    比如5000*5000的一张大图,可以只读取将其缩小成1/8后即625*625大小的图片。 这样比先完全读取5000*5000的图像,再用算法缩小成625*625大小不知快多少倍。
    如果应用需求只需要一张小图时,这种读取方式就可以大显身手了。

    在c代码中读取jpeg一般是使用libjpeg, 这个库提供了不完全读取图片的功能。

    给ln::LBitmap添加有关jpeg的接口,如下ReadJpeg()第三个参数fraction可取值为1,2,4,8,分别对应1/1,1/2,1/4,1/8

    ```
    在上面LBitmap的基本上加入下面5个函数:
    // 不读取像素数据,只读取jpeg文件的大小, 用指针*width, *height做为传出参数, 返回值bool返回文件是否为jpeg格式
    static bool ReadJpegSize(const wchar_t *path, int *width, int *height);
    

    // 判断文件是否为jpeg格式
    static bool IsJpegFile(const wchar_t *fileame);

    // 读取jpeg,fraction可取值为1, 2, 4, 8
    bool ReadJpeg(const wchar_t *filename, int fraction = 1);

    // 按照width, height的大小读取合适的jpeg大小, 所得的图像大小不会超过width*height
    bool ReadFitJpeg(const wchar_t *filename, int width, int height);

    // 保存jpeg,quality范围是[0, 100]
    bool WriteJpeg(const wchar_t *filename, int quality = 80

    JpegAPI

    具体的实现在JpegDemo
    用上面的函数进行jpeg的读取和保存的测试

    复制代码
    ```
    ln::LBitmap bmp;
    bmp.ReadBmp(L"one.bmp");
    unsigned char *p = bmp.Pixel(0, 0);
    printf("%d, %d, %d\n", p[0], p[1], p[2]);
    bmp.WriteJpeg(L"one.jpg", 90);
    ```
    复制代码

    读取one.bmp图片,然后保存成jpeg格式,one.jpg放大后显示如下

    发现左上角的颜色发生了变化,并且也影响到周围的像素,就算将上面WriteJpeg()第二个参数换成100,也还是这种效果,这是Jpeg格式无法避免的问题
    但如果读取一张风景照,再保存成Jpeg,就几乎看不出有什么差别了。

    android平台下实现jpeg预读

    复制代码
    BitmapFactory.Options opt = new BitmapFactory.Options();
    opt.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(info.fullPath, opt); //这里仅仅只读取jpeg的大小
    opt.inJustDecodeBounds = false;
    if (opt.outWidth > opt.outHeight) {
        opt.inSampleSize = opt.outWidth / phSize;//hpSize是允许的图片宽高的最大值
    } else {
        opt.inSampleSize = opt.outHeight / phSize;
    }
    Bitmap b = BitmapFactory.decodeFile(info.fullPath, opt); 
    复制代码

     将BitmapFactory.Options的inJustDecodeBounds 设置为true后,就只会读取Jpeg的大小,而不会去解析像素数据。然后再设置inSampleSize后,就可以根据这个值来读取适当大小的图片,研究android的源码后可以发现底层也是调用的libjpeg库来实现。

    ios,mac

    本人还没有在ios/mac中发现如何预读jpeg的官方API。Apple对图形、图像、多媒体领域提供了丰富接口,如果这个功能真没实现就太令我惊讶了! 不过ObjectC完全兼容C,可以调用libjpeg库来实现这个功能。

    .NET下仅读取jpeg的大小

    下面是用c#仅仅读取jpeg宽高(没有解析像素数据), 直接用C#读取1/2,1/4,1/8还不知道如何实现

    FileStream stream = new FileStream(path, FileMode.Open);
    Image img = Image.FromStream(stream, false, false);  //关键是将第三个参数设置为false
    Console.WriteLine("size: {0},{1}", img.Width, img.Height);

     

    jpeg批量转化工具

    用相机拍出来的原始jpeg图片是高保真质量, 所占文件体积非常大,本人写了一个批量转化的工具,可以将jpeg的质量都转化成80, 图像的宽高不变, 这时人眼几乎看不出有什么差别, 但其体积只有原来的1/3. 如果有大量的照片需要保存时, 节约的空间就很客观了。实现原理很简单, 就是读取jpeg文件, 然后再保存.
    用c#实现的,代码量非常少,在此贴出全部源码

      1     class Program
      2     {
      3         static string src_path;
      4         static long small_size = 0;
      5 
      6         private static ImageCodecInfo GetCodecInfo(string mimeType)
      7         {
      8             ImageCodecInfo[] CodecInfo = ImageCodecInfo.GetImageEncoders();
      9 
     10             foreach (ImageCodecInfo ici in CodecInfo) {
     11                 if (ici.MimeType == mimeType)
     12                     return ici;
     13             }
     14             return null;
     15         }
     16 
     17         static void SaveImage(string path)
     18         {
     19             FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
     20 
     21             if (stream.Length == 0) {
     22                 stream.Close();
     23                 return;
     24             }
     25 
     26             byte[] file_data = new byte[stream.Length];
     27             stream.Read(file_data, 0, (int)stream.Length);
     28             Stream mem = new MemoryStream(file_data);
     29 
     30             long old_size = stream.Length;
     31 
     32             try {
     33                 Image img = new Bitmap(mem);
     34                 stream.Close();
     35 
     36                 EncoderParameter p = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 80L);
     37                 EncoderParameters ps = new EncoderParameters(1);
     38 
     39                 ps.Param[0] = p;
     40 
     41                 img.Save(path, GetCodecInfo("image/jpeg"), ps);
     42 
     43                 FileStream f = new FileStream(path, FileMode.Open, FileAccess.Read);
     44                 long new_size = f.Length;
     45                 f.Close();
     46 
     47                 small_size += old_size - new_size;
     48 
     49             } catch (System.Exception ex) {
     50 
     51             } finally {
     52                 stream.Close();
     53             }
     54       
     55         }
     56 
     57         static void ConvertOneImage(string path, bool is_save)
     58         {
     59             if (is_save) {
     60                 string new_name = src_path + path.Substring(path.LastIndexOf('\\'));
     61                 File.Copy(path, new_name, true);
     62             }
     63 
     64             SaveImage(path);            
     65         }
     66 
     67         static void ShowSize(string path)
     68         {
     69             FileStream stream = new FileStream(path, FileMode.Open);
     70             Image img = Image.FromStream(stream, false, false);
     71             stream.Close();
     72             //Console.WriteLine("{0} {1}", img.Width, img.Height);
     73             if (img.Width == 0) {
     74                 Console.WriteLine("Error");
     75             }
     76         }
     77 
     78         static void BatchJpeg()
     79         {
     80             string path = Application.ExecutablePath;
     81             path = path.Substring(0, path.LastIndexOf('\\'));
     82 
     83             src_path = path + "\\" + "src";
     84             //Console.WriteLine(src_path);
     85 
     86             Console.WriteLine("批量转化jpeg图片,保证其图片质量的前提下减少其存储大小");
     87             Console.WriteLine("若想保存原图片,其按y(原图将放在src文件夹下), 否则按任意键开始处理");
     88 
     89             ConsoleKeyInfo key = Console.ReadKey();
     90             bool is_save = false;
     91 
     92             if (key.KeyChar == 'y' || key.KeyChar == 'Y') {
     93                 is_save = true;
     94 
     95                 Directory.CreateDirectory("src");
     96             }
     97 
     98             string[] files = Directory.GetFiles(path, "*.jpg");
     99 
    100             Stopwatch sw = new Stopwatch();
    101             sw.Start();
    102 
    103             for (int i = 0; i < files.Length; ++i) {
    104                 ConvertOneImage(files[i], is_save);
    105                 //string s = files[i].Substring(files[i].LastIndexOf('\\') + 1);
    106                 //Console.WriteLine((i + 1).ToString() + "/" + files.Length.ToString() + " \t " + s);
    107                 
    108                 //ShowSize(files[i]);
    109             }
    110 
    111             sw.Stop();
    112 
    113             Console.WriteLine("*********已结束,按任意键结束********");
    114             double v = (small_size * 1.0 / (1024 * 1024));
    115 
    116             Console.WriteLine("共减少 " + v.ToString("0.00##") + "M 的存储空间");
    117             Console.WriteLine("耗时:" + sw.Elapsed.TotalSeconds.ToString("0.00##") + "");
    118             Console.ReadKey();
    119         }
    120 
    121         static void Main(string[] args)
    122         {
    123             BatchJpeg();
    124             //SaveImage("E:\\img - 副本.JPG");
    125             //string path = "E:\\cpp_app\\LiteTools\\JpegBatch\\bin\\Release\\img - 副本.JPG";
    126             //File.Delete(path);
    127         }
    128     }
    JpegBatchConvert

     

    Exif信息

    另外jpeg文件一般有一个附属的exif信息,这个信息中有图像大小,拍摄时间,拍摄的相关参数,照片方向,图像缩略图等信息。

    用相机拍出来的jpeg都会有这个信息。如果照片方向不是正立的话,在读取到像素取后,还得按exif所指明的方向将图像旋转下。mspaint程序就没有做这个处理,有些图片用picasa查看和用mspaint查看方向就不一样。当然为了简单起见,上面的LBitmap中也自动忽略了exif信息及其图像拍摄时的方向。

    如果不用读取1/2,1/4,1/8的方法,也可以从exif中来读取缩略图,但这个缩略图一般很小。

    说到exif,不得不说一款用perl实现的命令行工具:exiftool。几乎所有的多媒体文件(图像、音乐、视频)都可以用这个工具来查看其有关信息,当然如果不是jpeg文件就是指广义上的"exif"。在git中有已经编译好可执行文件exiftool.exe。使用方法是将这个文件放到系统路径下,然后在想查看的文件路径下执行 exiftool filename

    在实现BatchJpeg工具时如果仅仅用上面实现的LBitmap来读取,保存, 将会失去exif信息, 而相片的拍摄时间等信息又很重要, 所以还得用另一个库exiv2来读取写入exif。如果用c#, 用上面的代码exif信息会自动保留下来。默默地向c#致敬。

    intelJpeg库

    如果在win32环境下对jpeg IO速度有很高的要求,可以使用interlJpeg库,不开源,但提供有*.h,*.lib文件。这个库可以大大提高jpg读取、保存速度。

    当时分别用c#和c实现了jpeg批量转化工具, 在处理大量图片时发现c#用时居然只有c的一半。太奇怪了,按理说,c的速度比c#应该快才对啊, 而实事是c慢了这么多。 最后发现问题就在libjpeg上,用了intetJpeg后速度就和c#差不多了(猜想.NET内部也是用intelJpeg来处理jpeg)。

    PNG格式

    1. png是一种无损压缩格式, 压缩大概是用行程编码算法。
    2. png可以有透明效果。
    3. png比较适合适量图,几何图。 比如本文中出现的这些图都是用png保存,比用joeg保存体积要小。

    再强调一下: jpeg比较适合存储色彩“杂乱”的拍摄图片,png比较适合存储几何特征强的图形类图片

    png可能有24位图和32位图之分。32位图就是带有alpha通道的图片。
    将图片a绘制到另一幅图片b上,如果图片a没有alpha通道,那么就会完全将b图片的像素给替换掉。而如果有alpha通道,那么最后覆盖的结果值将是c = a*alpha + b*(1-alpha)
    再对LBitmap添加png的支持。
    添加接口如下:

    static bool ReadPngSize(const wchar_t *path, int *width, int *height);
    static bool IsPngFile(const wchar_t *filename);
    bool ReadPng(const wchar_t *filename);
    bool WritePng(const wchar_t *filename);

    具体实现在PngDemo中。有调用libpng库,并且libpng库依赖zlib库(由此可以看出png算法有用到常规的压缩算法)。

    GIF格式

    上面提到的bmp,jpeg,png图片都只有一帧,而gif可以保存多帧图像,如图所示

    libgif库可以用来读取gif图片。gif中有个参数可以控制图片变化的快慢。在程序中可以使用这个参数,也可以自己定义一个参数,这就是为什么gif图片,在不同程序中查看时其变化速度不一样。

    webp

    google开发的一种有损、透明图片格式,相当于jpeg和png的合体,google声称其可以把图片大小减少40%。

     

    一个强大的格式库,CxImage

    CxImage几乎可以读取任何图片格式

    下面是其头文件中的宏定义:

    #define CXIMAGE_SUPPORT_WINDOWS 1
    #define CXIMAGE_SUPPORT_EXIF    1
    #define CXIMAGE_SUPPORT_BMP 1
    #define CXIMAGE_SUPPORT_GIF 1
    #define CXIMAGE_SUPPORT_JPG 1
    #define CXIMAGE_SUPPORT_PNG 1
    #define CXIMAGE_SUPPORT_ICO 1
    #define CXIMAGE_SUPPORT_TIF 1
    #define CXIMAGE_SUPPORT_TGA 1
    #define CXIMAGE_SUPPORT_PCX 1
    #define CXIMAGE_SUPPORT_WBMP 1
    #define CXIMAGE_SUPPORT_WMF 1
    #define CXIMAGE_SUPPORT_JP2 1
    #define CXIMAGE_SUPPORT_JPC 1
    #define CXIMAGE_SUPPORT_PGX 1
    #define CXIMAGE_SUPPORT_PNM 1
    #define CXIMAGE_SUPPORT_RAS 1
    
    #define CXIMAGE_SUPPORT_MNG 1
    #define CXIMAGE_SUPPORT_SKA 1
    #define CXIMAGE_SUPPORT_RAW 1
    #define CXIMAGE_SUPPORT_PSD 1
    

    CxImage在针对特定格式时,也是调用了其它图片库(比如libjpeg, libpng, libtiff)。由于CxImage太过庞大,如果不想使用其全部代码,可以自己从中“偷取”特定图片格式的读取、保存代码。

     

     

    原文出处 http://www.cnblogs.com/xiangism

    展开全文
  • 图片

    2020-03-22 10:29:52
    一些用到的图片 1.雪花1 2020.03.22

    一些用到的图片

    1.雪花1 2020.03.22
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    https://img-blog.csdnimg.cn/20200322104141545.png
    在这里插入图片描述
    https://img-blog.csdnimg.cn/20200322104145683.png
    在这里插入图片描述
    https://img-blog.csdnimg.cn/20200322110742872.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2NjI0MjUy,size_16,color_FFFFFF,t_70
    在这里插入图片描述
    https://img-blog.csdnimg.cn/20200322110818831.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2NjI0MjUy,size_16,color_FFFFFF,t_70

    2.樱花
    在这里插入图片描述
    https://img-blog.csdnimg.cn/2020032211123813.png

    展开全文
  • 图片的压缩其实是俩概念, 1、是 “压” 文件体积变小,但是像素数不变,长宽尺寸不变,那么质量可能下降, 2、是 “缩” 文件的尺寸变小,也就是像素数减少。长宽尺寸变小,文件体积同样会减小。 这个 ...

    前言

    图片压缩其实就是俩概念:

    • 文件体积变小,但是像素数不变,长宽尺寸不变,那么质量可能下降
    //1、JPEG
              UIImageJPEGRepresentation(image, 0.0)//是1的功能
    //推荐使用png`   
         NSData * imageData = UIImagePNGRepresentation(image);
    `
    
    //因为`PNG:0x89 image/png ,压缩比没有 JPG 高,但是无损压缩,解压缩性能高,苹果推荐的图像格式!`
    
    
    • 文件的尺寸变小,也就是像素数减少。长宽尺寸变小,文件体积同样会减小。
    
              [sourceImage drawInRect:CGRectMake(0,0,targetWidth, targetHeight)] //是2的功能。
    
    

    I、 解决压缩之后图片模糊的问题

    模糊的问题,大部分原因是使用第三方框架,(比如QMUIKit),在选择相册预览的时候,就把图片压缩了很模糊了。(尤其是针对协议类型这种大图)

    1.1如果是拍照,可以压缩一下分辨率,否则上传很慢

    • 1.1.1不用使用预览图进行上传
    //    [self imgUpLoad:imageAsset.previewImage Max:1 Index:1];
        
        [self imgUpLoad:imageAsset.originImage Max:1 Index:1];
    
    
    • 1.1.2 如果是拍照,可以压缩一下分辨率,否则上传很慢
        return  [self imageCompressForSize:image targetSize:size];
    
    
    • 1.1.3: 拍照压缩分辨率的例子
    - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
    {
        NSString *type = [info objectForKey:UIImagePickerControllerMediaType];
        //当选择的类型是图片
        if ([type isEqualToString:@"public.image"])
        {
            UIImage *image1 = [info objectForKey:UIImagePickerControllerOriginalImage];
            image1 = [ControlManager image:image1 scaleToSize:CGSizeMake(1000, 1200)];// 压缩分辨率 便于上传
            
            [picker dismissViewControllerAnimated:YES completion:nil];
            
            [SVProgressHUD showWithStatus:@"上传中.." maskType:SVProgressHUDMaskTypeGradient];
            [self imgUpLoad:image1 Max:1 Index:1];
        }
    }
    
    

    1. 2、 质量压缩(0.5) 结合比例压缩(1028)

    • 1.2.1用法
            NSData * imageData = UIImageJPEGRepresentation( [image compressWithTargetPixel:1028], k_UIImageJPEGRepresentationcompressionQuality);
    
    
    • 1.2.2:质量压缩的比例(质量压缩使用系统APIUIImageJPEGRepresentation
    #define k_UIImageJPEGRepresentationcompressionQuality 0.5
    
    
    • 1.2.3 比例压缩 compressWithTargetPixel的代码
    
    
    - (UIImage *)compressWithTargetPixel:(NSUInteger)targetPx {
        
        UIImage *newImage = nil;
        
        CGSize imageSize = self.size;
        CGFloat width = imageSize.width * self.scale;
        CGFloat height = imageSize.height * self.scale;
        
        // 是否重绘
        BOOL drawImge = NO;
        
        // 压缩后的尺寸
        CGFloat scaleFactor = 0.0;
        CGFloat scaledWidth = targetPx;
        CGFloat scaledHeight = targetPx;
        
        // 1. 图片宽高均 ≤ 参照像素,图片尺寸保持不变
        if (width <= targetPx && height <= targetPx) {
            newImage = self;
        }
        
        // 2. 宽或高均 > 参照像素
        else if (width > targetPx && height > targetPx) {
            
            drawImge = YES;
            CGFloat factor = width / height;
            
            if (factor <= 2) {
                // 2.1 图片宽高比 ≤ 2,则将图片宽或者高取大的等比压缩至1280px
                if (width > height) {
                    scaleFactor  = targetPx / width;
                } else {
                    scaleFactor = targetPx / height;
                }
            } else {
                // 2.2 图片宽高比 > 2时,则宽或者高取小的等比压缩至1280px
                if (width > height) {
                    scaleFactor  = targetPx / height;
                } else {
                    scaleFactor = targetPx / width;
                }
            }
        }
        
        // 3. 宽高一个 >= 1280px,另一个 < 1280px; 宽 >= 1280
        else if (width >= targetPx && height < targetPx ) {
            if (width / height > 2) {
                newImage = self;
            } else {
                drawImge = YES;
                scaleFactor = targetPx / width;
            }
        }
        // 4. 宽高一个 >= 1280px,另一个 < 1280px 高 >= 1280
        else if (width < targetPx &&  height >= targetPx) {
            if (height / width > 2) {
                newImage = self;
            } else {
                drawImge = YES;
                scaleFactor = targetPx / height;
            }
        }
        
        if (drawImge == YES) {
            scaledWidth = width * scaleFactor;
            scaledHeight = height * scaleFactor;
            
            UIGraphicsBeginImageContextWithOptions(CGSizeMake(scaledWidth/self.scale, scaledHeight/self.scale), YES, [UIScreen mainScreen].scale);
            [self drawInRect:CGRectMake(0, 0, scaledWidth/self.scale, scaledHeight/self.scale)];
            newImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
        }
        
        if (newImage == nil) {
            newImage = self;
        }
        
        newImage = [UIImage imageWithData:UIImageJPEGRepresentation(newImage, 0.7) scale:newImage.scale];
        
        return newImage;
    }
    
    

    II 针对业务场景选择图片格式

    2.1 如何区分不同格式的图像的

    • 根据图像数据第一个字节来判断的!
    	// NSData+ImageContentType.m    + (NSString *)sd_contentTypeForImageData:
    
    	PNG:0x89 image/png ,压缩比没有 JPG 高,但是无损压缩,解压缩性能高,苹果推荐的图像格式!
    	JPG:0xFF image/jpeg,压缩比最高的一种图片格式,有损压缩!最多使用的场景,照相机!解压缩的性能不好!
    	GIF:0x47 image/gif ,序列桢动图,特点:只支持 256 种颜色!最流行的时候在 19981999,有专利的!
    
    

    2.2 使用场景分析

    2.2.1 JPEG/JPG

    • 特点:有损压缩、体积小、不支持透明
    • 使用场景:颜色丰富的照片,JPG是通用的选择,如大的背景图、轮播图或Banner图。

    2.2.2 PNG

    • 特点:无损压缩、质量高、体积大、支持透明。
    • 使用场景:透明图片的业务场景,如小的Logo、颜色简单且对比强烈的图片或背景。

    2.2.3 SVG

    • 特点:文本文件、体积小、不失真、兼容性好、无需多端、多分辨率适配、较强的交互特性、渲染成本比较高。
    • 使用场景:图片色彩相对简单的业务场景。

    2.2.4 Base64

    • 特点:文本文件、依赖编码,Base64编码后,图片大小会膨胀为原文件的4/3。
    • 使用场景:小图标(<8KB)解决方案。

    2.2.5 WebP

    • 特点:WebP图片是一种新的图像格式,由Google开发。与png、jpg相比,相同的视觉体验下,WebP图像的尺寸缩小了大约30%。另外,WebP图像格式还支持有损压缩、无损压缩、透明和动画,但有兼容性问题。
    • 使用场景:图片占较大的商场类网站,目前Google、Facebook、ebay、淘宝、腾讯、美团等已经在用。

    “打开淘宝网,假如你是chrome浏览器,你会发现,所有图片都是webp结尾的,淘宝网图片运用了webp。假如你是safari浏览器,看到图片就是jpg或者png了,淘宝网自动判断浏览器支持不支持webp,假如支持,则输出相应的图片格式!

    在这里插入图片描述

    https://img.alicdn.com/imgextra/i4/1725301/O1CN01aXKpab1p1uBGClTeF_!!1725301-0-lubanu.jpg_290x290q90.jpg_.webp

    III 、 see also

    3.1: NSData与UIImage之间的转换

    
    //NSData转换为UIImage
    NSData *imageData = [NSData dataWithContentsOfFile: imagePath];
    UIImage *image = [UIImage imageWithData: imageData];
    
    //UIImage转换为NSData
    NSData *imageData = UIImagePNGRepresentation(aimae);
    

    3.2 其他压缩参考

    #  UIImage (Compress)
    
    
    
    - h
    
    ```objectivec
    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface UIImage (Compress)
    
    // 压缩图片质量 二分算法
    - (NSData *)compressQualityWithMaxLength:(NSInteger)maxLength;
    
    /*
     *  压缩图片方法(先压缩质量再压缩尺寸)
     */
    -(NSData *)compressWithLengthLimit:(NSUInteger)maxLength;
    /*
     *  压缩图片方法(压缩质量)
     */
    -(NSData *)compressQualityWithLengthLimit:(NSInteger)maxLength;
    /*
     *  压缩图片方法(压缩质量二分法)
     */
    -(NSData *)compressMidQualityWithLengthLimit:(NSInteger)maxLength;
    /*
     *  压缩图片方法(压缩尺寸)
     */
    -(NSData *)compressBySizeWithLengthLimit:(NSUInteger)maxLength;
    
    @end
    
    
    • m
    #import "UIImage+Compress.h"
    
    @implementation UIImage (Compress)
    
    // 二分法计算
    - (NSData *)compressQualityWithMaxLength:(NSInteger)maxLength {
        CGFloat compression = 1;
        NSData *data = UIImageJPEGRepresentation(self, compression);
        if (data.length < maxLength) return data;
        CGFloat max = 1;
        CGFloat min = 0;
        for (int i = 0; i < 6; ++i) {
            compression = (max + min) / 2;
            data = UIImageJPEGRepresentation(self, compression);
            if (data.length < maxLength * 0.9) {
                min = compression;
            } else if (data.length > maxLength) {
                max = compression;
            } else {
                break;
            }
        }
        return data;
    }
    
    -(NSData *)compressWithLengthLimit:(NSUInteger)maxLength{
        // Compress by quality
        CGFloat compression = 1;
        NSData *data = UIImageJPEGRepresentation(self, compression);
        //NSLog(@"Before compressing quality, image size = %ld KB",data.length/1024);
        if (data.length < maxLength) return data;
        
        CGFloat max = 1;
        CGFloat min = 0;
        for (int i = 0; i < 6; ++i) {
            compression = (max + min) / 2;
            data = UIImageJPEGRepresentation(self, compression);
            //NSLog(@"Compression = %.1f", compression);
            //NSLog(@"In compressing quality loop, image size = %ld KB", data.length / 1024);
            if (data.length < maxLength * 0.9) {
                min = compression;
            } else if (data.length > maxLength) {
                max = compression;
            } else {
                break;
            }
        }
        //NSLog(@"After compressing quality, image size = %ld KB", data.length / 1024);
        if (data.length < maxLength) return data;
        UIImage *resultImage = [UIImage imageWithData:data];
        // Compress by size
        NSUInteger lastDataLength = 0;
        while (data.length > maxLength && data.length != lastDataLength) {
            lastDataLength = data.length;
            CGFloat ratio = (CGFloat)maxLength / data.length;
            //NSLog(@"Ratio = %.1f", ratio);
            CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),
                                     (NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blank
            UIGraphicsBeginImageContext(size);
            [resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
            resultImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            data = UIImageJPEGRepresentation(resultImage, compression);
            //NSLog(@"In compressing size loop, image size = %ld KB", data.length / 1024);
        }
        //NSLog(@"After compressing size loop, image size = %ld KB", data.length / 1024);
        return data;
    }
    
    - (NSData *)compressQualityWithLengthLimit:(NSInteger)maxLength {
        CGFloat compression = 1;
        NSData *data = UIImageJPEGRepresentation(self, compression);
        while (data.length > maxLength && compression > 0) {
            compression -= 0.02;
            data = UIImageJPEGRepresentation(self, compression); // When compression less than a value, this code dose not work
        }
        return data;
    }
    
    
    -(NSData *)compressMidQualityWithLengthLimit:(NSInteger)maxLength{
        CGFloat compression = 1;
        NSData *data = UIImageJPEGRepresentation(self, compression);
        if (data.length < maxLength) return data;
        CGFloat max = 1;
        CGFloat min = 0;
        for (int i = 0; i < 6; ++i) {
            compression = (max + min) / 2;
            data = UIImageJPEGRepresentation(self, compression);
            if (data.length < maxLength * 0.9) {
                min = compression;
            } else if (data.length > maxLength) {
                max = compression;
            } else {
                break;
            }
        }
        return data;
    }
    
    -(NSData *)compressBySizeWithLengthLimit:(NSUInteger)maxLength{
        UIImage *resultImage = self;
        NSData *data = UIImageJPEGRepresentation(resultImage, 1);
        NSUInteger lastDataLength = 0;
        while (data.length > maxLength && data.length != lastDataLength) {
            lastDataLength = data.length;
            CGFloat ratio = (CGFloat)maxLength / data.length;
            CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),
                                     (NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blank
            UIGraphicsBeginImageContext(size);
            // Use image to draw (drawInRect:), image is larger but more compression time
            // Use result image to draw, image is smaller but less compression time
            [resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
            resultImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
            data = UIImageJPEGRepresentation(resultImage, 1);
        }
        return data;
    }
    @end
    
    
    • tabbaritem 图片太大解决方案
      将图片名称修改为@2x. 即可
    展开全文
  • 图片

    2020-04-20 00:47:00
  • 图片,相册

    千次阅读 2013-05-03 05:09:06
    iphone中图像通常存储在4个地方【相册、应用程序包、沙盒、Internet】,通过这4个源,我们就可以存取应用图片。  相册  iphone的相册包含摄像头胶卷+用户计算机同步的部分照片。用户可以通过...
  • 基础知识 java 图片与string相互转换

    千次阅读 2017-10-03 18:15:16
    import java.awt.*; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.io.*; import java.nio.charset.StandardCharsets; import java.util.Base64;...import javax.imageio.I
  • 代码很粗糙,娱乐玩玩就好 import time import os from lxml import etree import requests import os import random import multiprocessing ...def download(a, b, url1, headers, n,items2_list): ...
  • 微信拒绝老好人

    2019-01-25 17:28:00
    作者 |曾响铃本文经授权转自科技向令说(ID: xiangling0815)1 月 22 日晚 19 时开始,抖音新用户发现自己开始无法以微信授权的方式登录、使用抖音。...
  • 使用 ShapeDrawable 实现小动画之图片放大镜常用函数代码实现注意Activity 向自定义 View 传递参数
  • 本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,...现在Android上的图片加载框架非常成熟,从最早的老牌图片加载框架UniversalImageLoader,到后来Google推出的Volley,再到后
  • 在多数情况下,我们想要在界面上加载并展示一张图片只需要一行代码就能实现。虽说只有这简简单单的一行代码,但大家可能不知道的是,Glide在背后帮我们默默执行了成吨的工作。这个形容词我想了很久,因为我觉得用...
  • Glide的缓存设计可以说是非常先进的,考虑的场景也很周全。在缓存这一功能上,Glide又将它分成了两个模块,一个是内存缓存,一个是硬盘缓存。 这两个缓存模块的作用各不相同,内存缓存的主要作用是防止应用重复将...
  • 在前面四篇文章的当中,我们已经学习了Glide的基本用法、Glide的工作原理和执行流程、Glide的缓存机制、以及Glide的回调机制等内容。如果你能将前面的四篇文章都掌握好了,那么恭喜你,现在你已经是一名Glide好手了...
  • 大家好,今天我们继续学习Glide。在上一篇文章当中,我带着大家一起深入探究了Glide的缓存机制,我们不光掌握了Glide缓存的使用方法,还通过源码分析对缓存的工作原理进行了了解。今天是这个Glide系列的第四篇文章,...
  • 本篇将是我们这个Glide系列的最后一篇文章。 其实在写这个系列第一篇文章的时候,Glide就推出4.0.0的RC版了。那个时候因为我一直研究的都是Glide 3.7.0版本,再加上RC版本还不太稳定,因此整个系列也都是基于3.7.0...
  • Google推荐的图片加载库Glide介绍

    万次阅读 多人点赞 2015-03-30 10:56:16
    英文原文 Introduction to Glide, Image Loader Library for Android, recommended by Google 首发地址 http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0327/2650.html 在泰国举行的谷歌开发者论坛...
  • Android图片处理之Glide使用大全

    万次阅读 2016-01-27 20:10:02
    Android Glide是一个开源的图片加载和缓存处理的第三方框架。和Android的Picasso库类似,个人感觉比Android Picasso好用。Android Glide使自身内部已经实现了缓存策略,使得开发者摆脱Android图片加载的琐碎事务,...
  • 在前面的六篇文章中,我们对Glide的方方面面都进行了学习,包括基本用法、源码解析、缓存机制、回调与监听、图片变换以及自定义模块。而今天,我们就要综合利用之前所学到的知识,来对Glide进行一个比较大的功能扩展...
  • 不知不觉中,我们的Glide系列教程已经到了第六篇了,距离第一篇Glide的基本用法发布已经过去了半年的时间。在这半年中,我们通过用法讲解和源码分析配合学习的方式,将Glide的方方面面都研究了个遍,相信一直能看到...
  • Glide是一个功能强大的图片加载库,下面是平常开发中使用到的一些功能,基于Glide-4.X版本的用法 Glide-github地址 Glide jar包下载地址 加载圆形图片: RequestOptions mRequestOptions = RequestOptions....
  • 在项目中总结的Glide用法(工具类)。public class Glides { public static Glides instance = new Glides(); public Glides() { } public static Glides getInstance() { return instance; } // 加载网络图片
  • Glide,该功能非常强大 Android 图片加载开源框架 相信大家并不陌生 正由于他的功能强大,所以它的源码非常复杂,这导致很多人望而却步 本人尝试将 Glide 的功能进行分解,并单独针对每个功能进行源码分析,从而...
  • Glide加载图片

    2016-07-25 17:41:28
    为什么图片加载我首先推荐Glide? 图片加载框架用了不少,从afinal框架的afinalBitmap,Xutils的BitmapUtils,老牌框架universalImageLoader,著名开源组织square的picasso,google推荐的glide到FaceBoo
  • 图片加载之Glide使用

    万次阅读 2017-03-31 16:52:40
    Glide的基本用法
  • 使用Glide加载https网址图片

    万次阅读 2017-09-08 16:31:15
    最近有网友问我怎么加载https图片,说是从网上找了很多办法都没成功,然后我就问他用的是什么图片加载工具,回答是glide,然后我自己也去网上找了一下,千篇一律的都说是结合okhttp来使用,修改okhttp的三个类,忽略...
  • Glide3.0加载https图片

    千次阅读 2017-07-06 11:22:44
    相关文章:okhttp3.0忽略https证书 在上一节说到的是用okhttp如何忽略证书来访问https请求,但是访问是可以访问了,但是图片却加载不出来,这是什么原因
  •  获取GIF动画图片Glide.with(this).load(R.drawable.image02).into(iv);image02.gif是个动画图片具体功能如下:GIF 动画的解码 :通过调用Glide.with(context).load(“图片路径“)方法,GIF动画图片可以自动显示...
  • 图片加载之Glide使用总结

    万次阅读 2016-04-25 07:39:03
    相关方法 with():指定了声明周期 load():加载资源,String/Uri/File/Integer/URL/byte[]/T,或者 loadFromMediaStore(Uri uri) placeholder(resourceId/drawable): 设置资源加载过程中的占位Drawable。...

空空如也

1 2 3 4 5 ... 20
收藏数 3,001,207
精华内容 1,200,482
关键字:

图片