首先,请注意this问题中给出的答案不适用于所有灰度图像,并且还注意到this other问题中接受的答案根本没有解释如何确定图像是否为灰度图像,但无论如何它不适合我的需求,因为它似乎只涵盖JPEG和TIFF图像,并假设它们将具有EXIF元数据及其中的必需字段。 (我无法理解为什么人们确定我所链接的第一个问题是我所链接的第二个问题的“重复”......)
最后,this last接受了缺乏一个工作和示范代码示例的答案,但无论如何这都无济于事,因为作者提到了使用Bitmap.GetPixel()
函数的缓慢和弃用的方法,但我们应该使用Bitmap.LockBits()
函数来代替更高的性能优势。
我有一些GIF,JPG,BMP和PNG图像,我需要确定它们是灰度图像还是不是灰度图像。对于GIF文件,我只关心分析第一帧。
我对图像的数据结构,像素颜色位和那些东西没有多少经验/意识,我只知道非常基础。所以,如果我错过了重要的信息,我应该提供我将要测试的图像的任何信息,那么只要问我,但无论如何要考虑到我想为“所有”类型的图像创建一个通用的解决方案,好吧,不是全部,但至少这些格式:BMP,JPG,GIF和PNG。
在我提到的那些图像格式中,我的最高优先级是GIF图像,这意味着如果能够确定GIF图像是否为灰度的方法不能用于分析其他类型图像的方法,那么我将接受仅涵盖GIF图像像素处理的答案。
我认为我的需求很明确:如何确定图像是否为灰度?
如果它根本不清楚,为了避免我可以做到你可以浪费你的时间:
Bitmap.GetPixel()
函数,它必须使用Bitmap.LockBits()
代替。这就是我到目前为止所做的。我试图理解确定图像是否为灰度的点,我也不确定我的bytesPerPixel
变量的条件是否正确以及我的RGB值分配是否正确,因为我从一开始就说我不是图像处理专家所以我可能错过了重要的事情......
VB.net
Public Shared Function IsImageGrayScale(ByVal img As Image) As Boolean
Select Case img.PixelFormat
Case PixelFormat.Format16bppGrayScale
Return True
Case Else
Dim pixelCount As Integer = (img.Width * img.Height)
Dim bytesPerPixel As Integer = (Image.GetPixelFormatSize(img.PixelFormat) \ 8)
If (bytesPerPixel <> 3) AndAlso (bytesPerPixel <> 4) Then
Throw New NotImplementedException(message:="Only pixel formats that has 3 or 4 bytes-per-pixel are supported.")
Else
Dim result As Boolean
' Lock the bitmap's bits.
Dim bmp As Bitmap = DirectCast(img, Bitmap)
Dim rect As New Rectangle(Point.Empty, bmp.Size)
Dim data As BitmapData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat)
' Get the address of the first line.
Dim ptr As IntPtr = data.Scan0
' Declare an array to hold the bytes of the bitmap.
Dim numBytes As Integer = (data.Stride * bmp.Height)
Dim rgbValues As Byte() = New Byte(numBytes - 1) {}
' Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, numBytes)
' Unlock the bitmap's bits.
bmp.UnlockBits(data)
' Iterate the pixels.
For i As Integer = 0 To (rgbValues.Length - bytesPerPixel) Step bytesPerPixel
Dim c As Color =
Color.FromArgb(red:=rgbValues(i + 2),
green:=rgbValues(i + 1),
blue:=rgbValues(i))
' I don't know what kind of comparison I need to do with the pixels,
' so I don't know how to proceed here to determine whether the image is or is not grayscale.
' ...
Next i
Return result
End If
End Select
End Function
C#(代码转换,未经测试)
public static bool IsImageGrayScale(Image img) {
switch (img.PixelFormat) {
case PixelFormat.Format16bppGrayScale:
return true;
default:
int pixelCount = (img.Width * img.Height);
int bytesPerPixel = (Image.GetPixelFormatSize(img.PixelFormat) / 8);
if ((bytesPerPixel != 3) && (bytesPerPixel != 4)) {
throw new NotImplementedException(message: "Only pixel formats that has 3 or 4 bytes-per-pixel are supported.");
} else {
bool result = false;
// Lock the bitmap's bits.
Bitmap bmp = (Bitmap)img;
Rectangle rect = new Rectangle(Point.Empty, bmp.Size);
BitmapData data = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
// Get the address of the first line.
IntPtr ptr = data.Scan0;
// Declare an array to hold the bytes of the bitmap.
int numBytes = (data.Stride * bmp.Height);
byte[] rgbValues = new byte[numBytes];
// Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, numBytes);
// Unlock the bitmap's bits.
bmp.UnlockBits(data);
// Iterate the pixels.
for (int i = 0; i <= rgbValues.Length - bytesPerPixel; i += bytesPerPixel) {
Color c = Color.FromArgb(red: rgbValues[i + 2],
green: rgbValues[i + 1],
blue: rgbValues[i]);
// I don't know what kind of comparison I need to do with the pixels,
// so I don't know how to proceed here to determine whether the image is or is not grayscale.
// ...
}
return result;
}
}
}
我建议使用Presentation Core的System.Windows.Media.Imaging,它公开了一个抽象的BitmapDecoder class,它是Windows Imaging直接支持的所有解码器的基础:
System.Windows.Media.Imaging.BmpBitmapDecoder System.Windows.Media.Imaging.GifBitmapDecoder System.Windows.Media.Imaging.IconBitmapDecoder System.Windows.Media.Imaging.JpegBitmapDecoder System.Windows.Media.Imaging.LateBoundBitmapDecoder System.Windows.Media.Imaging.PngBitmapDecoder System.Windows.Media.Imaging.TiffBitmapDecoder System.Windows.Media.Imaging.WmpBitmapDecoder
解码图像文件流时,正确的解码器从抽象类转换为特定类。
解码的图像帧被转换为BitmapFrame Class,其成员转换为BitmapSource class,其引用关于图像流的所有解码信息。
有趣的是,在这种情况下,是BitmapSource.Format属性,它暴露了System.Windows.Media.PixelFormat Structure及其识别格式的枚举。
这些格式包括:
PixelFormats.Gray32Float PixelFormats.Gray16 PixelFormats.Gray8 PixelFormats.Gray4 PixelFormats.Gray2
这些标志可以照常测试。
IsGrayscale
, which returns the result of the test of the Image PixelFormat, using the PixelFormats previously listed.图像格式由BitmapInfo.Format
BitmapInfo.Metadata.Format
属性引用(不同来源,用于比较。
其他属性非常明显。
实现此类的项目必须引用:
PresentationCore
System.Xaml
WindowsBase
属性:
ImageSize (Size) => Size of the Image
Dpi (Size) => DpiX and DpiY of the Image
PixelSize (Size) => Size in Pixels ot the Image
Masks (List) => List of Byte Masks
BitsPerPixel (int) => Bits per Pixel
PixelFormat (PixelFormat) => Pixel format as reported by the Decoder
ImageType (string) => Textual expression of the image format (GIF, JPG etc.)
HasPalette (bool) => The Image has a Palette
Palette (BitmapPalette) => Palette representation of the Image Colors
HasThumbnail (bool) => The Image includes a Thumbnail image
Thumbnail (BitmapImage) => The Image Thumbnail, in BitmapImage format
Frames (int) => Number of frames. Animated Images are represented by a sequence of frames
FramesContent (FramesInfo) => Informations about all frame included in this Image
IsMetadataSuppported (bool) => The Image has Metadata informations
Metadata (MetadataInfo) => Class referencing all the Metadata informations a Image contains
AnimationSupported (bool) => This Format supports frame Animations
Animated (bool) => The Image is a timed sequence of frames
方法:
public enum DeepScanOptions : int {
Default = 0,
Skip,
Force
}
public bool IsGrayScale(DeepScanOptions DeepScan)
在给定图像内部调色板的情况下,检查Image PixelFormat
是否被视为GrayScale。 DeepScanOptions
枚举器用于确定扫描的执行方式。
样本使用部分中的更多详细信息。
public enum GrayScaleInfo : int {
None = 0,
Partial,
GrayScale,
Undefined
}
public ImagingBitmapInfo.GrayScaleInfo IsGrayScaleFrames()
报告框架选项板的状态。它可能会返回:
None
:图像没有灰度帧
Partial
:有些帧是GrayScale
GrayScale
:所有帧都有一个GrayScale Palette
Undefined
:图像可能没有调色板信息。图像像素格式由PixelFormat
属性报告
public ImagingBitmapInfo.GrayScaleStats GrayScaleSimilarity();
此方法执行统计评估(平均值,(总和(最小)<=>总和(最大值)),考虑图像的所有内部调色板的颜色,以验证内部颜色表示可以与灰度模式同化多少。
它返回一个ImagingBitmapInfo.GrayScaleStats
,它暴露了这些属性:
int Palettes
:评估的调色板数量
float AverageMaxDistance
:RGB分量之间的平均距离(Max)
float AverageMinDistance
:RGB分量之间的平均距离(Min)
float AverageLogDistance
:RGB组件之间的平均逻辑距离
float GrayScalePercent
:相似度的百分比
float GrayScaleAveragePercent
:逻辑相似度的百分比
List<FrameStat> PerFrameValues
:报告每个Palette条目的计算结果的类。它公开了这些属性:
qazxsw poi:当前调色板中的颜色数
qazxsw poi:RGB组件之间的距离(最大值)
int ColorEntries
:RGB分量之间的距离(最小值)
float DistanceMax
:RGB分量之间的平均距离
float DistanceMin
在float DistanceAverage
类中插入所有图像帧信息。
它在内部使用,但可以在创建主类public void FrameSourceAddRange(BitmapFrame[] bitmapFrames)
的实例时手动填充。公开这些属性:
qazxsw poi:图像中包含的帧总数
qazxsw poi:具有调色板的帧数
FramesInfo
:GrayScale帧的数量
ImagingBitmapInfo
:B&W帧数
FramesTotalNumber
:所有帧的类列表。 FramesColorNumber
类对象公开这些属性:
FramesGrayscaleNumber
:框架的大小
FramesBlackWhiteNumber
:Frame List<Frames>
的DpiX和DpiY:帧的PixelFormat
FramesInfo
:框架有一个调色板
FrameSize
:框架有一个GrayScale调色板
FrameDpi
:框架有一个B&W调色板
PixelFormat
转换IsColorFrame
IsGrayScaleFrame
以IsBlackWhiteFrame
public System.Drawing.Bitmap ThumbnailToBitmap()
格式转换,可用于System.Windows.Media.Imaging
控件/类。 (此时未经过适当测试)。
BitmapImage
, is initialized passing to the System.Drawing
method a File Path or a File Stream.Bitmap
要验证Image是否具有GrayScale WinForms
,请调用ImagingBitmapInfo
方法,指定必须检索此信息。
BitmapFormatInfo()
该类根据图像像素格式决定是否对图像调色板执行深度扫描(如果存在调色板)。如果像素格式已经报告了GrayScale图像(例如ImagingBitmapInfo BitmapInfo = BitmapFormatInfo(@"[ImagePath]");
//or
ImagingBitmapInfo BitmapInfo = BitmapFormatInfo([FileStream]);
,PixelFormat
等),则不执行深度扫描。如果像素格式是索引格式,则执行扫描;如果PixelFormat是彩色格式,则不执行扫描。
请注意,某些图像(大多数是Gif)可能会报告Color
IsGrayScale(ImagingBitmapInfo.DeepScanOptions)
,而内部格式(Palette)可能是GrayScale。
ImagingBitmapInfo.DeepScanOptions.Default
指示执行所有帧的调色板的深度扫描,无论图像解码器报告什么PixelFormats.Gray32Float
。
用于发现报告的彩色图像是否具有一个或多个灰度帧。
PixelFormats.Gray16
指示不使用调色板像素格式执行调色板的深度扫描,即使它将正常执行。
PixelFormat
如果结果与预期的结果不同,可以执行完整的图像帧ImagingBitmapInfo.DeepScanOptions.Force
检查,调用:
PixelFormat
此方法执行所有帧的完整检查,并报告任何内部帧是否具有GrayScale ImagingBitmapInfo.DeepScanOptions.Skip
。结果可以是System.Windows.Media.PixelFormat pixelFormat = BitmapInfo.PixelFormat;
bool BitmapIsGrayscale = BitmapInfo.IsGrayScale(ImagingBitmapInfo.DeepScanOptions.Force);
枚举器值之一:
PixelFormat
,ImagingBitmapInfo.GrayScaleInfo GrayScaleFrames = BitmapInfo.IsGrayScaleFrames();
,PixelFormat
,GrayScaleInfo
。
如果结果是None
,则所有内部帧都具有GrayScale Partial
。
GrayScale
表示图像没有调色板信息。
要创建“图像调色板”颜色条目的灰度相似度的统计表示,请调用Undefined
方法:
GrayScale
PixelFormat
更新:
这或多或少是相同的设置,但Undefined
导向。
意味着只使用GrayScaleSimilarity()
组件。
ImagingBitmapInfo.GrayScaleStats Stats = BitmapInfo.GrayScaleSimilarity();
float GrayScalePercent = Stats.GrayScalePercent
float RGBAverageDistancePercent = Stats.GrayScaleAveragePercent
float RGBPatternMaxDistance = Stats.AverageMaxDistance
有较少的选择(在GDI +中也有一个令人讨厌的错误,与using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
public class ImagingBitmapInfo
{
FramesInfo framesInfo;
public ImagingBitmapInfo()
{
this.framesInfo = new FramesInfo();
this.Metadata = new MetadataInfo();
this.Metadata.ApplicationName = string.Empty;
this.Metadata.Author = new List<string>() { };
this.Metadata.CameraManufacturer = string.Empty;
this.Metadata.CameraModel = string.Empty;
this.Metadata.Comment = string.Empty;
this.Metadata.Copyright = string.Empty;
this.Metadata.DateTaken = string.Empty;
this.Metadata.Subject = string.Empty;
this.Metadata.Title = string.Empty;
}
public Size ImageSize { get; set; }
public Size Dpi { get; set; }
public Size PixelSize { get; set; }
public List<PixelFormatChannelMask> Masks { get; set; }
public int BitsPerPixel { get; set; }
public PixelFormat PixelFormat { get; set; }
public string ImageType { get; set; }
public bool HasPalette { get; set; }
public BitmapPalette Palette { get; set; }
public bool HasThumbnail { get; set; }
public BitmapImage Thumbnail { get; set; }
public int Frames { get; set; }
public FramesInfo FramesContent
{ get { return this.framesInfo; } }
public bool IsMetadataSuppported { get; set; }
public MetadataInfo Metadata { get; set; }
public bool AnimationSupported { get; set; }
public bool Animated { get; set; }
public enum DeepScanOptions : int
{
Default = 0,
Skip,
Force
}
public enum GrayScaleInfo : int
{
None = 0,
Partial,
GrayScale,
Undefined
}
public System.Drawing.Bitmap ThumbnailToBitmap()
{
if (this.Thumbnail == null)
return null;
using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(
this.Thumbnail.DecodePixelWidth,
this.Thumbnail.DecodePixelHeight))
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(this.Thumbnail));
encoder.Save(outStream);
return (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(outStream);
}
}
public void FrameSourceAddRange(BitmapFrame[] bitmapFrames)
{
if (bitmapFrames == null) return;
this.framesInfo.Frames.AddRange(bitmapFrames.Select(bf => new FramesInfo.Frame()
{
Palette = bf.Palette,
FrameSize = new Size(bf.PixelWidth, bf.PixelHeight),
FrameDpi = new Size(bf.DpiX, bf.DpiY),
PixelFormat = bf.Format,
IsGrayScaleFrame = CheckIfGrayScale(bf.Format, bf.Palette, DeepScanOptions.Force),
IsBlackWhiteFrame = (bf.Format == PixelFormats.BlackWhite)
}));
this.framesInfo.Frames.Where(f => (!f.IsGrayScaleFrame & !f.IsBlackWhiteFrame))
.All(f => f.IsColorFrame = true);
}
public GrayScaleInfo IsGrayScaleFrames()
{
if (this.framesInfo.Frames.Count == 0)
return GrayScaleInfo.Undefined;
if (this.framesInfo.FramesGrayscaleNumber > 0)
return (this.framesInfo.FramesGrayscaleNumber == this.framesInfo.FramesTotalNumber)
? GrayScaleInfo.GrayScale : GrayScaleInfo.Partial;
return GrayScaleInfo.None;
}
public bool IsGrayScale(DeepScanOptions DeepScan)
{
return CheckIfGrayScale(this.PixelFormat, this.Palette, DeepScan);
}
private bool CheckIfGrayScale(PixelFormat pixelFormat, BitmapPalette palette, DeepScanOptions DeepScan)
{
if (pixelFormat == PixelFormats.Gray32Float ||
pixelFormat == PixelFormats.Gray16 ||
pixelFormat == PixelFormats.Gray8 ||
pixelFormat == PixelFormats.Gray4 ||
pixelFormat == PixelFormats.Gray2)
{
if (palette == null || (DeepScan != DeepScanOptions.Force)) { return true; }
}
if (pixelFormat == PixelFormats.Indexed8 ||
pixelFormat == PixelFormats.Indexed4 ||
pixelFormat == PixelFormats.Indexed2)
{
DeepScan = (DeepScan != DeepScanOptions.Skip) ? DeepScanOptions.Force : DeepScan;
}
if ((DeepScan != DeepScanOptions.Skip) & palette != null)
{
List<Color> IndexedColors = palette.Colors.ToList();
return IndexedColors.All(rgb => (rgb.R == rgb.G && rgb.G == rgb.B && rgb.B == rgb.R));
}
return false;
}
public GrayScaleStats GrayScaleSimilarity()
{
if (!this.HasPalette) return null;
GrayScaleStats stats = new GrayScaleStats();
float AccumulatorMax = 0F;
float AccumulatorMin = 0F;
float AccumulatorAvg = 0F;
float[] Distance = new float[3];
stats.Palettes = this.Frames;
foreach (FramesInfo.Frame frame in this.framesInfo.Frames)
{
GrayScaleStats.FrameStat framestat = new GrayScaleStats.FrameStat()
{ ColorEntries = frame.Palette.Colors.Count };
foreach (Color pEntry in frame.Palette.Colors)
{
if (!(pEntry.R == pEntry.G && pEntry.G == pEntry.B && pEntry.B == pEntry.R))
{
Distance[0] = Math.Abs(pEntry.R - pEntry.G);
Distance[1] = Math.Abs(pEntry.G - pEntry.B);
Distance[2] = Math.Abs(pEntry.B - pEntry.R);
AccumulatorMax += (float)(Distance.Max());
AccumulatorMin += (float)(Distance.Min());
AccumulatorAvg += (float)(Distance.Average());
}
}
framestat.DistanceMax = (float)((AccumulatorMax / 2.56) / framestat.ColorEntries);
framestat.DistanceMin = (float)((AccumulatorMin / 2.56) / framestat.ColorEntries);
framestat.DistanceAverage = (float)((AccumulatorAvg / 2.56) / framestat.ColorEntries);
stats.PerFrameValues.Add(framestat);
AccumulatorMax = 0F;
AccumulatorMin = 0F;
AccumulatorAvg = 0F;
}
stats.AverageMaxDistance = stats.PerFrameValues.Max(mx => mx.DistanceMax);
stats.AverageMinDistance = stats.PerFrameValues.Min(mn => mn.DistanceMin);
stats.AverageLogDistance = stats.PerFrameValues.Average(avg => avg.DistanceAverage);
stats.GrayScaleAveragePercent = 100F - stats.AverageLogDistance;
stats.GrayScalePercent = 100F - ((stats.AverageMaxDistance - stats.AverageMinDistance) / 2);
return stats;
}
public class GrayScaleStats
{
public GrayScaleStats()
{
this.PerFrameValues = new List<FrameStat>();
}
public List<FrameStat> PerFrameValues { get; set; }
public int Palettes { get; set; }
public float AverageMaxDistance { get; set; }
public float AverageMinDistance { get; set; }
public float AverageLogDistance { get; set; }
public float GrayScalePercent { get; set; }
public float GrayScaleAveragePercent { get; set; }
public class FrameStat
{
public int ColorEntries { get; set; }
public float DistanceMax { get; set; }
public float DistanceMin { get; set; }
public float DistanceAverage { get; set; }
}
}
public class FramesInfo
{
public FramesInfo()
{
this.Frames = new List<Frame>();
}
public int FramesTotalNumber
{
get { return (this.Frames != null) ? this.Frames.Count() : 0; }
private set { }
}
public int FramesColorNumber
{
get { return (this.Frames != null) ? this.Frames
.Where(f => f.IsColorFrame == true)
.Count() : 0; }
private set { }
}
public int FramesGrayscaleNumber
{
get {return (this.Frames != null) ? this.Frames
.Where(f => f.IsGrayScaleFrame == true)
.Count() : 0; }
private set { }
}
public int FramesBlackWhiteNumber
{
get { return (this.Frames != null) ? this.Frames
.Where(f => f.IsBlackWhiteFrame == true)
.Count() : 0; }
private set { }
}
public List<Frame> Frames { get; private set; }
internal class Frame
{
public BitmapPalette Palette { get; set; }
public Size FrameSize { get; set; }
public Size FrameDpi { get; set; }
public PixelFormat PixelFormat { get; set; }
public bool IsColorFrame { get; set; }
public bool IsGrayScaleFrame { get; set; }
public bool IsBlackWhiteFrame { get; set; }
}
}
public class MetadataInfo
{
public string ApplicationName { get; set; }
public List<string> Author { get; set; }
public string Copyright { get; set; }
public string CameraManufacturer { get; set; }
public string CameraModel { get; set; }
public string Comment { get; set; }
public string Format { get; set; }
public string Subject { get; set; }
public string Title { get; set; }
public string DateTaken { get; set; }
public int Rating { get; set; }
}
}
public static ImagingBitmapInfo BitmapPixelFormat(string FileName)
{
using (FileStream stream = File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
return BitmapPixelFormat(stream);
}
}
public static ImagingBitmapInfo BitmapPixelFormat(FileStream stream)
{
ImagingBitmapInfo imageInfo = new ImagingBitmapInfo();
var bitmapDecoder = BitmapDecoder.Create(stream,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
BitmapSource bitmapSource = bitmapDecoder.Frames[0];
ImageMetadata imageMetadata = bitmapSource.Metadata;
BitmapMetadata bitmapMetadata = (BitmapMetadata)bitmapSource.Metadata;
try
{
imageInfo.Frames = bitmapDecoder.Frames.Count();
if (imageInfo.Frames > 0)
imageInfo.FrameSourceAddRange(bitmapDecoder.Frames.ToArray());
imageInfo.ImageType = bitmapMetadata.Format.ToUpperInvariant();
imageInfo.PixelFormat = bitmapSource.Format;
imageInfo.HasPalette = ((bitmapSource.Palette != null) && (bitmapSource.Palette.Colors.Count > 0)) ? true : false;
imageInfo.Palette = bitmapSource.Palette;
imageInfo.ImageSize = new Size((float)bitmapSource.Height, (float)bitmapSource.Width);
imageInfo.Dpi = new Size((float)bitmapSource.DpiX, (float)bitmapSource.DpiY);
imageInfo.PixelSize = new Size(bitmapSource.PixelHeight, bitmapSource.PixelWidth);
imageInfo.Masks = bitmapSource.Format.Masks.ToList();
imageInfo.BitsPerPixel = bitmapSource.Format.BitsPerPixel;
imageInfo.AnimationSupported = bitmapDecoder.CodecInfo.SupportsAnimation;
imageInfo.Animated = (imageInfo.AnimationSupported && (imageInfo.Frames > 1)) ? true : false;
imageInfo.HasThumbnail = bitmapDecoder.Thumbnail != null;
if (imageInfo.HasThumbnail)
imageInfo.Thumbnail = (BitmapImage)bitmapDecoder.Thumbnail.CloneCurrentValue();
imageInfo.Metadata.Format = bitmapMetadata.Format;
//If not supported, Catch and set imageInfo.SetMetadataNonSupported()
imageInfo.Metadata.ApplicationName = bitmapMetadata.ApplicationName;
imageInfo.Metadata.Author = (bitmapMetadata.Author != null)
? bitmapMetadata.Author.ToList<string>()
: null;
imageInfo.Metadata.CameraModel = bitmapMetadata.CameraModel;
imageInfo.Metadata.CameraManufacturer = bitmapMetadata.CameraManufacturer;
imageInfo.Metadata.CameraModel = bitmapMetadata.Comment;
imageInfo.Metadata.Copyright = bitmapMetadata.Copyright;
imageInfo.Metadata.Subject = bitmapMetadata.Subject;
imageInfo.Metadata.Title = bitmapMetadata.Title;
imageInfo.Metadata.Rating = bitmapMetadata.Rating;
imageInfo.Metadata.Format = bitmapMetadata.Format;
imageInfo.Metadata.DateTaken = bitmapMetadata.DateTaken;
}
catch (System.NotSupportedException)
{ imageInfo.IsMetadataSuppported = false; }
catch (System.Exception ex) { /* Log ex */ throw ex; }
return imageInfo;
}
相关,从未纠正过)并且一些信息不能直接获得。
无论如何,相关部分都在那里。
就我测试而言,可以正确检测灰度图像。
要注意的是,如果Image具有索引的Palette(例如Gif格式),则报告的
WinForms
FlagSystem.Drawing
永远不会正确。也不是System.Drawing.Imaging
。 在这种情况下,验证图像是否为灰度图像的唯一可能方式(我发现)是解析调色板。它只需要几个Bitmap Encoders即可完成,但仍然很烦人。 它适用于其他格式。
与之前列出的程序相同。 可以这样使用:
ImageFlags
要么
ColorSpaceGRAY
PixelFormat.Format16bppGrayScale
因为这个邮政机构缺乏空间。