image - 如何确定图像是否部分损坏? C#

标签 image partial corrupt

我有一个图像的原始字节。我使用以下代码来确定图像是否已损坏

public bool IsValidGDIPlusImage(byte[] imageData)
{
    try
    {
        using (var ms = new MemoryStream(imageData))
        {
            using (var bmp = new Bitmap(ms))
            {
            }
        }
        return true;
    }
    catch (Exception ex)
    {
        return false;
    }
}

如果图像完全损坏,上面的代码可以正常工作,但是如果我的图像部分损坏怎么办?像下面的JPEG

enter image description here

如何确定图像部分损坏?

原始图像下方是一个简单的 300x300 像素图像,中心有一条对角线。

enter image description here
任何指导都受到高度赞赏。
谢谢

最佳答案

检测部分损坏的图像很困难。

一个简单的方法是检查开始和结束字节标记是否完整,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using System.Drawing;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            try {

                var imgBytes = Helper.DownloadImageAsBytes("/image/KQI1j.jpg");
                //valid GDI+? Example true!
                Console.WriteLine(IsValidGDIPlusImage(imgBytes));
                //Complete? Example false
                ImageFile imgFile = new ImageFile(imgBytes);
                Console.WriteLine(imgFile.Complete);

            }
            catch(Exception ex)
            {
                Console.Write(ex.Message);
            }
        }

        public static bool IsValidGDIPlusImage(byte[] imageData)
        {
            try
            {
                using (var ms = new MemoryStream(imageData))
                {
                    using (var bmp = new Bitmap(ms))
                    {
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
    }
}

public class Helper {
    public static byte[] DownloadImageAsBytes(String url) {
        using (var webClient = new WebClient()) { 
            return webClient.DownloadData(url);
        }
    }
}

public class ImageFile {

    private Types  _eFileType   = Types.FileNotFound;
    private bool   _blComplete  = false             ;
    public bool Complete
    {
        get { return _blComplete; }
    }
    private int    _iEndingNull = 0                 ;

    private readonly byte[] _abTagPNG  = { 137, 80, 78, 71, 13, 10, 26, 10  };
    private readonly byte[] _abTagJPG  = { 255, 216, 255                    };
    private readonly byte[] _abTagGIFa = { 71, 73, 70, 56, 55, 97           };
    private readonly byte[] _abTagGIFb = { 71, 73, 70, 56, 57, 97           };
    private readonly byte[] _abEndPNG  = { 73, 69, 78, 68, 174, 66, 96, 130 };
    private readonly byte[] _abEndJPGa = { 255, 217, 255, 255               };
    private readonly byte[] _abEndJPGb = { 255, 217                         };
    private readonly byte[] _abEndGIF  = { 0, 59                            };

    public enum Types { FileNotFound, FileEmpty, FileNull, FileTooLarge, FileUnrecognized, PNG, JPG, GIFa, GIFb }

    public ImageFile(byte[] abtTmp) {

        _eFileType = Types.FileUnrecognized; // default if found

        //byte[] abtTmp = File.ReadAllBytes(_sFilename);
        // check the length of actual data
        int iLength = abtTmp.Length;
        if(abtTmp[abtTmp.Length - 1] == 0) {
            for(int i = (abtTmp.Length - 1); i > -1; i--) {
                if(abtTmp[i] != 0) {
                    iLength = i;
                    break;
                }
            }
        }
        // check that there is actual data
        if(iLength == 0) {
            _eFileType = Types.FileNull;
        } else {
            _iEndingNull = (abtTmp.Length - iLength);
            // resize the data so we can work with it
            Array.Resize<byte>(ref abtTmp, iLength);
            // get the file type
            if(_StartsWith(abtTmp, _abTagPNG)) {
                _eFileType = Types.PNG;
            } else if(_StartsWith(abtTmp, _abTagJPG)) {
                _eFileType = Types.JPG;
            } else if(_StartsWith(abtTmp, _abTagGIFa)) {
                _eFileType = Types.GIFa;
            } else if(_StartsWith(abtTmp, _abTagGIFb)) {
                _eFileType = Types.GIFb;
            }
            // check the file is complete
            switch(_eFileType) {
                case Types.PNG:
                    _blComplete = _EndsWidth(abtTmp, _abEndPNG);
                    break;
                case Types.JPG:
                    _blComplete = (_EndsWidth(abtTmp, _abEndJPGa) || _EndsWidth(abtTmp, _abEndJPGb));
                    break;
                case Types.GIFa:
                case Types.GIFb:
                    _blComplete = _EndsWidth(abtTmp, _abEndGIF);
                    break;
            }
            // get rid of ending null bytes at caller's option
            //if(_blComplete && cullEndingNullBytes) File.WriteAllBytes(_sFilename, abtTmp);
        }

    }


    public Types  FileType        { get { return _eFileType  ; } }
    public bool   IsComplete      { get { return _blComplete ; } }
    public int    EndingNullBytes { get { return _iEndingNull; } }

    private bool _StartsWith(byte[] data, byte[] search) {
        bool blRet = false;
        if(search.Length <= data.Length) {
            blRet = true;
            for(int i = 0; i < search.Length; i++) {
                if(data[i] != search[i]) {
                    blRet = false;
                    break;
                }
            }
        }
        return blRet; // RETURN
    }

    private bool _EndsWidth(byte[] data, byte[] search) {
        bool blRet = false;
        if(search.Length <= data.Length) {
            int iStart = (data.Length - search.Length);
            blRet = true;
            for(int i = 0; i < search.Length; i++) {
                if(data[iStart + i] != search[i]) {
                    blRet = false;
                    break;
                }
            }
        }
        return blRet; // RETURN
    }
}

这至少适用于一些(更多)图像,但它无法检测开始和结束部分之间数据损坏的图像。

引用:
  • https://www.dreamincode.net/forums/topic/286802-detect-partially-corrupted-image/
  • https://stackoverflow.com/a/5139214/8291949报价:

  • You can try some things, but with certain file formats (example: BMP, JPEG to some extent) only a human can ultimately decide if the file is OK or corrupted.



    有为此目的开放的软件,推荐看一看Bad Peggy ( java )。
    如果您愿意使用更大的库,OpenCV 可能会很有用。

    关于image - 如何确定图像是否部分损坏? C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8876397/

    相关文章:

    css - 图像随窗口宽度调整大小,但保持比例

    html - Box-Shadow 在我的网站上不起作用

    c# - Powerpoint 中形状的部分下划线检查不起作用?

    PrimeFaces:CommandButton 或 CommandLink 上的 process 属性的默认值是多少?

    c# - 偶尔接收到的TCP数据顺序错误,不完整

    image - svg 剪辑图像并显示描边

    html - 如何使用带有图像的伪类 ":visited"设置元素样式?

    c# - BindingSource 似乎不包含在部分类中创建的属性

    安卓果冻 bean : Database corrupted on upgrade

    linux - 如何解决 Linux 中损坏的文本文件?