我有图像的原始字节。我使用以下代码来确定图像是否损坏]
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 =“在此处输入图像描述”>任何指导都受到高度赞赏。谢谢
检测部分损坏的图像很困难。
一种简单的方法是像这样检查开始和结束字节标记是否完整:
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)。