当前位置 : 主页 > 编程语言 > c语言 >

如何确定C#或VB.NET中的图像是否为灰度?

来源:互联网 收集:自由互联 发布时间:2021-06-25
首先 首先,请注意,this问题中给出的答案对于所有灰度图像都不起作用,并且还注意到this other问题中接受的答案根本没有解释如何确定图像是否是灰度图像,但无论如何它确实不适合我的需
首先

首先,请注意,this问题中给出的答案对于所有灰度图像都不起作用,并且还注意到this other问题中接受的答案根本没有解释如何确定图像是否是灰度图像,但无论如何它确实不适合我的需求,因为它似乎只涵盖JPEG和TIFF图像,并假设它们将具有EXIF元数据及其中的必需字段. (我无法理解为什么人们确定我所链接的第一个问题是我所链接的第二个问题的“重复”……)

最后,this last接受的答案缺乏一个工作和演示代码示例,但无论如何都无济于事,因为作者使用Bitmap.GetPixel()函数引用了缓慢且不赞成的方法,但我们应该使用Bitmap.LockBits()函数代替为了更高的性能效益.

情景

我有一些GIF,JPG,BMP和PNG图像,我需要确定它们是灰度图像还是不是灰度图像.对于GIF文件,我只关心分析第一帧.

我对图像的数据结构,像素颜色位和那些东西没有多少经验/意识,我只知道非常基础.所以,如果我错过了重要的信息,我应该提供我将要测试的图像的任何信息,那么请问我,但无论如何要考虑到我想为“所有”类型的图像创建一个通用的解决方案,好吧,不是全部,但至少这些格式:BMP,JPG,GIF和PNG.

在我提到的那些图像格式中,我的最高优先级是GIF图像,这意味着如果能够确定GIF图像是否为灰度的方法不能用于分析其他类型图像的方法,那么我将接受仅涵盖GIF图像像素处理的答案.

我认为我的需求很明确:如何确定图像是否为灰度?

如果它根本不清楚,为了避免我可以做到你可以浪费你的时间:

>解决方案必须至少适用于GIF图像. (记住,我只关心GIF中的第一帧),但如果提供的解决方案对BMP,JPG和PNG也有效,那么它当然总是更好.
>该解决方案必须关注PixelFormat.Format32bppRgb灰度图像.
>解决方案一定不能使用Bitmap.GetPixel()函数,它必须使用Bitmap.LockBits().
>我不是要求解释,伪代码也没有外部链接到关于图像结构/格式/像素等的文档,我要求一个工作代码示例(当然,如果作者涵盖图像结构/像素技术,总是更好提供除代码之外的基本解释).
>在C#或VB.NET中,选择并不重要.

研究

这就是我到目前为止所做的.我试图理解确定图像是否为灰度的点,我也不确定我的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,它公开了Windows Imaging直接支持的所有解码器的抽象 BitmapDecoder class:

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 Properties

这些格式包括:

PixelFormats.Gray32Float
PixelFormats.Gray16
PixelFormats.Gray8
PixelFormats.Gray4
PixelFormats.Gray2

这些标志可以像往常一样进行测试.

此类可用于收集有关Bitmap格式的信息.
我已经包含了一个属性IsGrayscale,它使用之前列出的PixelFormats返回Image PixelFormat的测试结果.

图像格式由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()

报告框架选项板的状态.它可能会返回:

无:图像没有灰度帧
部分:某些帧是GrayScale
GrayScale:所有帧都有一个GrayScale Palette
未定义:图像可能没有调色板信息.图像像素格式由PixelFormat属性报告

public ImagingBitmapInfo.GrayScaleStats GrayScaleSimilarity();

该方法执行统计评估(平均值,(Sum(Min)< => Sum(Max)),考虑图像的所有内部调色板的颜色,以验证内部颜色表示可以被同化到多少灰度模式.
它返回一个ImagingBitmapInfo.GrayScaleStats,它公开这些属性:

int Palettes:评估的Palette数量
float AverageMaxDistance:RGB组件之间的平均距离(Max)
float AverageMinDistance:RGB组件之间的平均距离(Min)
float AverageLogDistance:RGB组件之间的平均逻辑距离
float GrayScalePercent:相似度的百分比
float GrayScaleAveragePercent:逻辑相似度的百分比

列表与LT; FrameStat> PerFrameValues:报告每个Palette条目的计算结果的类.它公开了这些属性:

int ColorEntries:当前选用板中的颜色数
float DistanceMax:RGB组件之间的距离(Max)
float DistanceMin:RGB组件之间的距离(最小值)
float DistanceAverage:RGB组件之间的平均距离

public void FrameSourceAddRange(BitmapFrame[] bitmapFrames)

在FramesInfo类中插入所有图像帧信息.
它在内部使用,但可以在创建主类的实例(ImagingBitmapInfo)时手动填充.公开这些属性:

FramesTotalNumber:图像中包含的od帧数
FramesColorNumber:具有调色板的帧数
FramesGrayscaleNumber:GrayScale帧的数量
FramesBlackWhiteNumber:B& W帧的数量

List< Frames>:所有帧的类列表. FramesInfo类对象公开这些属性:

FrameSize:帧的大小
FrameDpi:帧的DpiX和DpiY
PixelFormat:Frame的PixelFormat
IsColorFrame:框架有一个调色板
IsGrayScaleFrame:框架有一个GrayScale Palette
IsBlackWhiteFrame:框架有一个B& W调色板

public System.Drawing.Bitmap ThumbnailToBitmap()

以System.Drawing位图格式转换System.Windows.Media.Imaging BitmapImage,可以在WinForms控件/类中使用. (此时未经过适当测试).

样品用法:
主类,ImagingBitmapInfo,初始化传递给BitmapFormatInfo()方法文件路径或文件流.

ImagingBitmapInfo BitmapInfo = BitmapFormatInfo(@"[ImagePath]");
//or 
ImagingBitmapInfo BitmapInfo = BitmapFormatInfo([FileStream]);

要验证Image是否具有GrayScale PixelFormat,请调用IsGrayScale(ImagingBitmapInfo.DeepScanOptions)方法,指定必须检索此信息.

ImagingBitmapInfo.DeepScanOptions.Default
该类根据图像像素格式决定是否对图像调色板执行深度扫描(如果存在调色板).如果像素格式已经报告了GrayScale图像(例如PixelFormats.Gray32Float,PixelFormats.Gray16等),则不执行深度扫描.如果像素格式是索引格式,则执行扫描;如果PixelFormat是彩色格式,则不执行扫描.

Note that some Images (Gifs, mostly) may report a Color PixelFormat,
while the inner format (Palette) might be GrayScale.

ImagingBitmapInfo.DeepScanOptions.Force
无论图像解码器报告PixelFormat是什么,都指示对所有帧的调色板执行深度扫描.
用于发现报告的彩色图像是否具有一个或多个灰度帧.

ImagingBitmapInfo.DeepScanOptions.Skip
指示不使用调色板像素格式执行调色板的深度扫描,即使它将正常执行.

System.Windows.Media.PixelFormat pixelFormat = BitmapInfo.PixelFormat;
bool BitmapIsGrayscale = BitmapInfo.IsGrayScale(ImagingBitmapInfo.DeepScanOptions.Force);

如果结果与预期的结果不同,可以执行完整的图像帧PixelFormat检查,调用:

ImagingBitmapInfo.GrayScaleInfo GrayScaleFrames = BitmapInfo.IsGrayScaleFrames();

此方法执行所有帧的完整检查,并报告任何内部帧是否具有GrayScale PixelFormat.结果可以是GrayScaleInfo枚举器值之一:
无,部分,GrayScale,未定义.
如果结果是GrayScale,则所有内部帧都具有GrayScale PixelFormat.
未定义表示图像没有调色板信息.

要创建图像调色板的颜色条目的灰度相似性的统计表示,请调用GrayScaleSimilarity()方法:

ImagingBitmapInfo.GrayScaleStats Stats = BitmapInfo.GrayScaleSimilarity();

float GrayScalePercent = Stats.GrayScalePercent
float RGBAverageDistancePercent = Stats.GrayScaleAveragePercent
float RGBPatternMaxDistance = Stats.AverageMaxDistance
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;
}

更新:

这或多或少是相同的设置,但面向WinForms.
这意味着只使用System.Drawing程序集.

System.Drawing.Imaging有较少的选项(在GDI中也有一个令人讨厌的错误,与Bitmap Encoders相关,从未纠正过)并且一些信息无法直接获得.无论如何,相关部分都在那里.

就我测试而言,可以正确检测灰度图像.

To note that, if an Image has an indexed Palette (e.g. Gif format), the reported 070021 Flag ColorSpaceGRAY is never
correct. Nor is the 070022.
The only
possible way (that I found) to verify whether the image is a Grayscale
one in this case, is to parse the color Palette. It takes only a few Ticks to complete, annoying nonetheless.
It’s working correctly for other formats.

与之前列出的程序相同.
可以这样使用:

ImagingBitmapInfo BitmapInfo = BitmapPixelFormat(@"[ImagePath]");
bool BitmapIsGrayscale = BitmapInfo.IsGrayScale();

要么

ImagingBitmapInfo BitmapInfo = BitmapPixelFormat([ImageStream]);
bool BitmapIsGrayscale = BitmapInfo.IsGrayScale();

Code moved to PasteBin因为这个邮政遗体缺乏空间.

网友评论