zoukankan      html  css  js  c++  java
  • 用Delphi从内存流中判断图片格式[转]

    http://blog.163.com/tfn2008%40yeah/blog/static/110321319201222243214337/

    用Delphi从内存流中判断图片格式[转]  

    2012-03-22 16:32:14|  分类: Delphi|举报|字号 订阅

     
     
     

    图片的格式很多,一个图片文件的后缀名并不能说明这个图片的真正格式什么,那么如何获取图片的格式呢?我想到了几个简单但有效的方法,那就是读取图片文件的文件头标识。我们知道各种格式的图片的文件头标识识不同的,因此我们可以通过判断文件头的标识来识别图片格式。
         我对各种格式的图片文件头标识进行了分析,不仅查找资料,也用十六进制编辑器察看过图片的文件头,以下是我收集、分析的结果,供大家参考。

    1.JPEG
    - 文件头标识 (2 bytes): $ff, $d8 (SOI) (JPEG 文件标识) 
    - 文件结束标识 (2 bytes): $ff, $d9 (EOI) 

    2.TGA
    - 未压缩的前5字节   00 00 02 00 00
    - RLE压缩的前5字节   00 00 10 00 00

    3.PNG
    - 文件头标识 (8 bytes)   89 50 4E 47 0D 0A 1A 0A

    4.GIF
    - 文件头标识 (6 bytes)   47 49 46 38 39(37) 61
                                         G   I   F     8   9 (7)     a

    5.BMP
    - 文件头标识 (2 bytes)   42 4D
                                         B   M

    6.PCX
    - 文件头标识 (1 bytes)   0A

    7.TIFF
    - 文件头标识 (2 bytes)   4D 4D 或 49 49

    8.ICO
    - 文件头标识 (8 bytes)   00 00 01 00 01 00 20 20 

    9.CUR
    - 文件头标识 (8 bytes)   00 00 02 00 01 00 20 20

    10.IFF
    - 文件头标识 (4 bytes)   46 4F 52 4D
                                         F   O   R   M

    11.ANI
    - 文件头标识 (4 bytes)   52 49 46 46
                                       R     I     F   F


         根据这些文件头标识的收集,我可以写一个识别图像格式的模块了。但是在写这个模块之前可以对收集到的文件头标识进行优化,使得程序中字符串比对次数尽量的少。
    1.JPEG我们知需要比对文件头的$ff, $d8这两个字符,而不用读取最后的两个结束标识了。
    2.TGA,ICO,CUR只需比对第三个与第五个字符即可。
    3.PNG比对[89][50]这两个字符。
    4.GIF比对[47][49][46]与第五个字符。

    废话不多说了,利用内存流来判断文件的格式,其实判断文件的前几个字节就可以简单的判断这个文件是什么类型的文件,例如

    jpg文件 是 FFD8 (从低位到高位就要反过来 D8FF 下面都是一样)

    BMP文件 是 424D ---4D42

    其他的我就不一一列举了,想知道跟多文件类型分别是用什么字符作为文件的开头的话,下载个C32asm或者UE等这类16进制编辑器就可以看到了。

    procedure TForm1.Button1Click(Sender: TObject); //Button1的单击事件
    var   
    //声明变量
       MyImage:TMemoryStream;   //内存流对象
       Buffer:Word;
       i:integer;
    begin
       if OpenDialog1.Execute then  
     //OpenDialog1是一个文件打开对话框,在Delphi组件面版的Dialog页中可以找到。
       
    begin
         MyImage:=TMemoryStream.Create; //建立内存流对象

    try
         MyImage.LoadFromFile(OpenDialog1.FileName); 
    //把刚刚用户选择的文件载入到内存流中
         MyImage.Position := 0;   
    //移动指针到最开头的位置
         if MyImage.Size = 0 then  
     //如果文件大小等于0,那么
         
    begin
           
    //错误
           ShowMessage('错误');
           Exit;
         
    end;
         MyImage.ReadBuffer(Buffer,2); 
    //读取文件的前2个字节,放到Buffer里面

         if Buffer=$4D42 then 
    //如果前两个字节是以4D42[低位到高位]
         begin
           ShowMessage('BMP'); 
    //那么这个是BMP格式的文件
         end
         else if Buffer=$D8FF 
    then //如果前两个字节是以D8FF[低位到高位]
        begin
             //JPEG
           ShowMessage('JPEG'); //........一样 下面不注释了
         end
         else if Buffer=$4947
     then
         begin
             
    //GIF
           ShowMessage('GIF');
         
    end
         else if
     Buffer=$050A 
    then
         begin
             //PCX
           ShowMessage('PCX');
         
    end
         else if
     Buffer=$5089
     then
         begin
             //PNG
           ShowMessage('PNG');
         
    end
         else if
     Buffer=$4238
     then
         begin
            //PSD
           ShowMessage('PSD');
         
    end
         else if
     Buffer=$A659 
    then
         begin
            //RAS
           ShowMessage('RAS');
         
    end
         else if
     Buffer=$DA01
     then
         begin
             
    //SGI
           ShowMessage('SGI');
         
    end
         else if
     Buffer=$4949
     then
         begin
             
    //TIFF
           ShowMessage('TIFF');
         
    end
         else   
    //如是其他类型的文件的话,直接显示错误
         begin
             //ERR
           ShowMessage('ERR');
         end;
     //if 
       end; //if

    finally

    MyImage.Free;   //释放内存流对象

    end;
    end;

    上面的过程只是简单的判断文件的前2个字节,如果想更加精确一点的话,可以把文件最后2个字节也判断上。
    delphi lazarus opengl 网页操作自动化, 图像分析破解,游戏开发
  • 相关阅读:
    Codeforces Round #415 (Div. 2) C. Do you want a date?
    Lifting the Stone 计算几何 多边形求重心
    计算几何 多边形面积 和 重心 的求法
    POJ 3304 segments 线段和直线相交
    LibreOJ #114. k 大异或和
    LibreOJ #113. 最大异或和
    对于各种各样平衡树的比较
    数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
    替罪羊树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
    红黑树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
  • 原文地址:https://www.cnblogs.com/delphi-xe5/p/6354476.html
Copyright © 2011-2022 走看看