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

问题描述 投票:5回答:1

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

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

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9sUHpPNS5qcGcifQ==” alt =“在此处输入图像描述”>

如何确定图像已部分损坏?

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

<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9BMVM4ZC5qcGcifQ==” alt =“在此处输入图像描述”>任何指导都受到高度赞赏。谢谢

image partial corrupt
1个回答
0
投票

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

一种简单的方法是像这样检查开始和结束字节标记是否完整:

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("https://i.stack.imgur.com/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
    }
}

这至少对某些(更多)图像有效,但是它无法检测出在开始和结束部分之间数据损坏的图像。

参考:

您可以尝试某些操作,但是要使用某些文件格式(例如:BMP,JPEG(某种程度上),只有人类才能最终决定文件是否确定或已损坏。

为此目的,有开放的软件,建议看看Bad Peggy(Java)。

© www.soinside.com 2019 - 2024. All rights reserved.