我有一个图像的原始字节。我使用以下代码来确定图像是否已损坏
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
如何确定图像部分损坏?
原始图像下方是一个简单的 300x300 像素图像,中心有一条对角线。
任何指导都受到高度赞赏。
谢谢
最佳答案
检测部分损坏的图像很困难。
一个简单的方法是检查开始和结束字节标记是否完整,如下所示:
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
}
}
这至少适用于一些(更多)图像,但它无法检测开始和结束部分之间数据损坏的图像。
引用:
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/