常见图片宽高解析

于比较常用的图片格式Png、Jpg、Gif、Bmp,我们需要针对不同的图片格式使用不同的控件来显示,这里就有一个来解析图片格式的问题。我们不能单纯的用文件后缀名.png、.jpg、.jpeg、.gif、.bmp来区分图片格式,因为实际上我们可以直接修改图片后缀名,修改后缀名并不能修改图片的格式,图片还是保持它原来的格式。

图片文件的格式结果中,在头部信息(一般都会在图片文件最开始的几个字节)中都会包含图片的格式信息。下面就列车常用的这几种格式图片的头部信息标识(十六进制)。

1.Png图片文件包括8字节:89 50 4E 47 0D 0A 1A 0A。即为 .PNG....。

2.Jpg图片文件包括2字节:FF D8。

3.Gif图片文件包括6字节:47 49 46 38 39|37 61 。即为 GIF89(7)a。

4.Bmp图片文件包括2字节:42 4D。即为 BM。

根据图片问题头标识信息我们可以能很方便的判断出文件的格式,首先我们需要获取图片文件的字节流信息,代码如下。

Stream stream = ;                 StreamResourceInfo info = Application.GetResourceStream( Uri(path, UriKind.Relative));          (info != )         {             stream = info.Stream;         }                  (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())         {                         stream = myIsolatedStorage.OpenFile(path, FileMode.Open, FileAccess.Read);         }

从图片文件流stream中读取8个字节,然后再根据不同的图片格式做文件头匹配比较具能判断出文件的格式,代码如下。

ImageType         {             Null,             Png,             Jpg,             Gif,             Bmp         }                    ImageType getImageType(Stream stream)         {                         ImageType type = ImageType.Null;                         [] header =  [];             stream.Read(header, , );                          (header[] ==  &&                 header[] ==  &&                 header[] ==  &&                 header[] ==  &&                 header[] ==  &&                 header[] ==  &&                 header[] ==  &&                 header[] == )             {                                 type = ImageType.Png;             }               (header[] ==  &&                     header[] == )             {                                 type = ImageType.Jpg;             }               (header[] ==  &&                       header[] ==  &&                        header[] ==  &&                        header[] ==  &&                        (header[] ==  ||                       header[] == ) &&                       header[] == )                  {                                 type = ImageType.Gif;             }               (header[] ==  &&                       header[] == )                  {                                 type = ImageType.Bmp;             }                         stream.Close();              type;         }

解析到图片格式后,我们就可以根据图片格式选择对应的控件来显示图片了。

PNG:

要解析Png图片的宽度和高度信息,首先需要了解Png图片的数据块结构,Png图片的尺寸信息存放在文件头数据块中,所以我们需要了解文件头的数据块结构。

文件头数据块IHDR(header chunk):它包含有PNG文件中存储的图像数据的基本信息,并要作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。 文件头数据块由13字节组成,其中前8个字节即为图片的宽度和高度信息,各占4个字节。

文件头数据块是第一个数据块,但是在数据块前,也就是PNG图片文件的最开始位置首先存储的是PNG文件署名域,占8个字节,即:89 50 4e 47 0d 0a 1a 0a ( .PNG....),通过这个可以判断图片是否为PNG格式,接下来是文件头数据块的长度和标识,各占4个字节,文件头数据块的长度为13,所以文件头数据块的长度固定为 00 00 00 0D,而文件头数据块的标识为49 48 44 52,即“IHDR”。

通过上面的解析,我们可以分一下几步来解析PNG图片的宽度和高度。

1.首先读取起始位的8个字节,即PNG文件署名域,判断图片是否为PNG格式,如果不是,则退出。

[] header =  [];         stream.Read(header, , );                  (!(header[] ==  &&             header[] ==  &&             header[] ==  &&             header[] ==  &&             header[] ==  &&             header[] ==  &&             header[] ==  &&             header[] == ))         {                         ;         }

2.然后跳过8个字节,即文件头数据块的长度值 00 00 00 0D,以及文件头数据块标识 49 48 44 52(IHDR)。

stream.Seek(, SeekOrigin.Current);

3.接下来要读取就是图片的宽度和高度值,读取8个字节,由于是按照高低位调换存储,所以需要做高低位转换,转换后通过BitConverter类直接将字节类型转换为整数型即为图片的尺寸。

[] buffer =  [];         stream.Read(buffer, , buffer.Length);         Array.Reverse(buffer, , );         Array.Reverse(buffer, , );         width_ = BitConverter.ToInt32(buffer, );         height_ = BitConverter.ToInt32(buffer, );

GIF:

GIF图片的文件格式相对比较简单,其中宽度和高度信息存放在逻辑视屏描述块的前4个字节,而逻辑视屏描述块是GIF图片的第二块区域,第一个区域为6个字节的头部,头部包括标识符和版本。下表列出到高度信息为止的各个字节的描述。

名称

字节

说明

头部

标识符

3

GIF  47 49 46

版本

3

87a(89a) 38 39|37 61

逻辑视屏描述块

宽度

2

高度

2

根据上面的格式很容易获取图片的高度和宽度信息,具体代码如下。

[] header =  [];         stream.Read(header, , );          (!(header[] ==  &&                       header[] ==  &&                    header[] ==  &&                    header[] ==  &&                    (header[] ==  ||                   header[] == ) &&                   header[] == ))             {                         ;         }                 [] buffer =  [];         stream.Read(buffer, , buffer.Length);         width_ = BitConverter.ToInt16(buffer, );         height_ = BitConverter.ToInt16(buffer, );

BMP:

典型的位图文件格式通常包含下面几个数据块:

位图头:保存位图文件的总体信息。

位图信息:保存位图图像的详细信息。

调色板:保存所用颜色的定义。

位图数据:保存一个又一个像素的实际图像。

通过解析位图头我们可以判断图片是否为bmp格式,而我们所需要的图片尺寸信息存储在位图信息数据块里。所以我们需要详细了解位图头和位图信息两个数据块的存储结构。

位图头,这部分是识别信息,典型的应用程序会首先普通读取这部分数据以确保的确是位图文件并且没有损坏。

字节 #0-1 保存位图文件的标识符,这两个字节的典型数据是BM。

字节 #2-5 使用一个dword保存位图文件大小。

字节 #6-9 是保留部分,留做以后的扩展使用,对实际的解码格式没有影响。

字节 #10-13 保存位图数据位置的地址偏移,也就是起始地址。

位图信息,这部分告诉应用程序图像的详细信息,在屏幕上显示图像将会使用这些信息,它从文件的第15个字节开始。

字节 #14-17 定义以下用来描述影像的区块(BitmapInfoHeader)的大小。它的值是:40 - Windows 3.2、95、NT、12 - OS/2 1.x、240 - OS/2 2.x

字节 #18-21 保存位图宽度(以像素个数表示)。

字节 #22-25 保存位图高度(以像素个数表示)。

…………

以上关于bmp文件结构的内容参考维基百科http://zh.wikipedia.org/wiki/BMP。

通过上面对BMP图片格式的了解,可以用下面的代码来解析bmp图片的尺寸大小。

[] header =  [];         stream.Read(header, , );          ( !(header[] ==  && header[] == ))         {                         ;         }                 stream.Seek(, SeekOrigin.Current);                 [] buffer =  [];         stream.Read(buffer, , buffer.Length);         width_ = BitConverter.ToInt32(buffer, );         height_ = BitConverter.ToInt32(buffer, );

JPG:

由于jpg图片的格式相对于png要复杂很多,所以首先我们要先清楚的了解jpg图片的数据格式,jpg图片包括SOI和数据两个部分。

SOI,Start of Image,图像开始,标记代码 2字节 固定值0xFFD8。

数据部分分成很多数据段,数据段的一般结构如下。

段数据结构

名称

字节

说明

段标识

>= 1

多于一个的0xFF

段类型

1

类型编码(称作“标记码”)

段长度

2

包括段内容和段长度本身,不包括段标识和段类型

短内容

<= 65533

段类型有30种,但只有10种是必须被所有程序识别的,其它的类型都可以忽略。在这么多的段中,其中JPG图片的尺寸相关信息存储在SOF0(图像基本信息)段中。所以需要详细了解一下SOFO段的数据结构。

SOFO段结构

名称

字节

说明

段标识

1

0XFF

段类型

1

0XCO JFIF格式的为0XC2

段长度

2

其值=8+组件数量×3

样本精度

1

8 每个样本位数(大多数软件不支持12和16)

图片高的

2

采用Motorola格式,即:高位在前,低位在后

图片宽度

2

采用Motorola格式,即:高位在前,低位在后

由于我们是为了解析JPG图片的宽度和高度信息,所以上表SOFO段结构只列出了到宽度为止结构信息,接下来还有其他一些图片的相关信息,这里就不再列出。

根据上面对JPG图片格式的解析,我们可以分一下几步来解析JPG图片的尺寸信息。

1.读取2个字节的SOI,即0xFFD8,根据这两个字节判断图片是否为JPG图片,如果不是,则退出解析过程。

[] header =  [];         stream.Read(header, , );                  (!(header[] ==  &&             header[] == ))         {                         ;         }

2.接下来就需要解析图片的数据部分,由于数据部分是有很多不同的数据段构成,数据段拥有一些共同的特性,所以这里我们需要做一个循环来逐个遍历查找到SOFO数据段。

type = -;          ff = -;                  ps = ;                          {                          {                                 ff = stream.ReadByte();                  (ff < )                 {                     ;                 }             }  (ff != );                          {                                 type = stream.ReadByte();             }  (type == );                         ps = stream.Position;              (type)             {                  :                  :                  :                  :                  :                  :                  :                  :                  :                  :                     ;                  :                  :                     {                                                 getJpgSize(stream);                         ;                     }                 :                     ps = stream.ReadByte() * ;                     ps = stream.Position + ps + stream.ReadByte() - ;                     ;             }              (ps +  >= stream.Length)             {                 ;             }             stream.Position = ps;         }  (type != );

3.找到SOFO数据段后,就可以解析图片的宽度和高度信息。

getJpgSize(Stream stream)         {                         stream.Seek(, SeekOrigin.Current);                         height_ = stream.ReadByte() * ;             height_ += stream.ReadByte();                         width_ = stream.ReadByte() * ;             width_ += stream.ReadByte();         }

(0)

相关推荐

  • 原地过个幸福年:你知道图片有几种格式吗?

    前两期我们介绍了电脑当中主流的视频与音频格式,相信放假在家的小伙伴们也在或多或少的增强自己的设计技能,原地过个幸福年,有道是学好新技能,走遍天下都不怕,这一期我们给大家讲一讲电脑当中主流的图片格式,其 ...

  • PS格式全介绍 jpg/jpeg/jpeg2000有啥区别

    Photoshop简称PS,是我们日常办公中必备软件,虽然大部分用户不可能达到专业设计的程度,但日常的污点修复.尺寸修改和格式转换等技能几乎人人必备.不久前笔者在转换图片的时候本意要导出JPEG格式的 ...

  • 常见图片文件格式

    PSD(Photoshop document) Photoshop的默认文档格式,支持图层.通道.路径等Photoshop所有的特性.可以存储为RGB或CMYK模式,还能够自定义颜色数并加以存储,是目 ...

  • 美股常见的宽基指数:纳斯达克100指数、标普500指数

    我们熟悉的一般都是中国内陆的股市,中国香港股市,还有一个不容忽视的股票市场,那就是美国股市. 美国股市有两个最主要的指数:纳斯达克100指数.标普500指数.我们来分别了解一下. 纳斯达克100指数 ...

  • 非常见图片格式:tiff格式怎么转png格式?

    其实tiff和png是非常常见的一种图片格式,就是对于部分人来说,因为很少了解图片格式这些内容,所以对于tiff,png格式这二者之间的格式转换处理,不是很清楚tiff格式怎么转png格式的.所以小编 ...

  • [基金]宽基指数基金包括些什么?常见的宽基指数基金有哪些

    指数基金可以分为宽基指数基金与窄基指数基金,投资宽基指数基金实际上就是投资宏观经济.如果你不想仔细选择某一股票或者某一行业,那么宽基指数基金相对就比较适合你,那么宽基指数基金包括些什么呢? 宽基指数基 ...

  • 身边常见中草药图片大全

    身边常见中草药图片大全,中草药名称图片大全 身边常见中草药图片大全 ​ ​ 1. 曼陀罗 有毒,为镇静要药,可松弛肌肉,古代麻沸散和云南白药保险子主要成分,民间花.子.叶.根各有不同用法,分治不同疾病 ...

  • 超详细!14种小麦常见病害图片及防治技术

    超详细!14种小麦常见病害图片及防治技术

  • 你能分辨平板上生长霉菌吗?常见霉菌形态描述及典型菌落图片汇总!

    食品实验室服务 霉菌是微生物检测过程中常见的真菌种类,由于霉菌生理和繁殖的特殊性,很多霉菌都可以通过外观来基本判断种类.有经验的检验员看一眼平板上的霉菌的形态就差不多可以判断它的种类,很是令人佩服.你 ...

  • 常见乌龟的品种及图片大全!

    相信乌龟大家都不陌生吧,就算没亲眼瞧见过,但在网上是肯定有图片和视频供大家观赏的,而且现在很多人都喜欢养殖宠物乌龟,所以说是比较常见的.那么乌龟的种类你们都清楚吗?今天就为大家介绍乌龟的品种及图片大全 ...

  • 月季花常见的黄叶原因,搭配图片及相应处理方法,很直观

    文/廿六 月季花常见的9种黄叶原因,搭配图片及相应处理方法,很直观 月季花是我国的传统名花,时至今日不但热度依然不减,反而花色品种越来越多,喜欢它的花友也是越来越多.不过月季虽然娇艳无比,但却是有着& ...