【问题标题】:Is it possible to use switch to select ImageFormat? [duplicate]是否可以使用 switch 来选择 ImageFormat? [复制]
【发布时间】:2017-06-22 15:16:28
【问题描述】:

我将图像从一种格式转换为另一种格式,并希望使用开关来处理不同的格式。 System.Drawing.Imaging.ImageFormat 是公共密封类,开关不适用于它。 下面的代码正在运行,但我想在这里使用开关。你能帮我提些建议吗?

public static void ConvertImageFormat(Image image, string targetImageFilePath, int newWidth, int newHeight, ImageFormat imageFormatToConvert)
    {
        using (Bitmap bitmap = new Bitmap(image, newWidth, newHeight))
        {
            using (Graphics graphic = Graphics.FromImage(bitmap))
            {
                graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphic.SmoothingMode = SmoothingMode.HighQuality;
                graphic.CompositingQuality = CompositingQuality.HighQuality;
                graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;

                graphic.DrawImage(image, 0, 0, newWidth, newHeight);

                if (Equals(ImageFormat.Png, imageFormatToConvert))
                {
                    bitmap.Save(targetImageFilePath, ImageFormat.Png);
                }
                else if (Equals(ImageFormat.Gif, imageFormatToConvert))
                {
                    bitmap.Save(targetImageFilePath, ImageFormat.Gif);
                }
                else if (Equals(ImageFormat.Jpeg, imageFormatToConvert))
                {
                    ImageCodecInfo[] arrImageCodecInfo = ImageCodecInfo.GetImageEncoders();
                    using (EncoderParameters encoderParameters = new EncoderParameters(1))
                    {
                        encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
                        bitmap.Save(targetImageFilePath, arrImageCodecInfo[1], encoderParameters);
                    }
                }
                else
                {
                    throw new Exception($"Convert to <{imageFormatToConvert.ToString()}> from " +
                                        $"<{new ImageFormatConverter().ConvertToString(image.RawFormat)}>" +
                                        $" image format is not supported now.");
                }
            }
        }
    }

【问题讨论】:

    标签: c# switch-statement image-formats


    【解决方案1】:

    不,您不能将 Switch 与 ImageFormat 一起使用,因为它是类。

    在 C# 6 中,匹配表达式必须是返回 以下类型的值:

    a char.
    a string.
    a bool.
    an integral value, such as an int or a long.
    an enum value.
    

    从 C# 7 开始,匹配表达式可以是任何非 null 表达。

    因为 C# 6 只支持常量模式并且不允许 常量值的重复,案例标签定义互斥 值,并且只有一种模式可以匹配匹配表达式。作为一个 因此,case 语句出现的顺序并不重要。

    但是,在 C# 7 中,由于支持其他模式,因此案例标签 不需要定义互斥值,多个模式可以 匹配匹配表达式。因为只有switch中的语句 包含第一个匹配模式的部分被执行, case 语句出现的顺序现在很重要。如果 C# 检测到 一个 switch 部分,其 case 语句或语句等效于 或者是先前语句的子集,它会产生编译器错误, CS8120, "switch case 已被前一个 case 处理过。"

    switch (C# Reference) MSDN article

    我建议您将 if else 语句简化为以下内容,而不是尝试使用 Switch:

    if (Equals(ImageFormat.Png, imageFormatToConvert) || Equals(ImageFormat.Gif, imageFormatToConvert) || Equals(ImageFormat.Jpeg, imageFormatToConvert)
    {
        if (Equals(ImageFormat.Jpeg, imageFormatToConvert))
        {
            ImageCodecInfo[] arrImageCodecInfo = ImageCodecInfo.GetImageEncoders();
            using (EncoderParameters encoderParameters = new EncoderParameters(1))
            {
                encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
                bitmap.Save(targetImageFilePath, arrImageCodecInfo[1], encoderParameters);
            }
        }
        else{
            bitmap.Save(targetImageFilePath, imageFormatToConvert);
        }
    }
    else
    {
        throw new Exception($"Convert to <{imageFormatToConvert.ToString()}> from " +
                            $"<{new ImageFormatConverter().ConvertToString(image.RawFormat)}>" +
                            $" image format is not supported now.");
    }
    

    【讨论】:

    • 谢谢。我在提问之前阅读了这个文档,但可能我错过了一些东西。 UPD:在我看来,以这种方式简化并不好,因为如果您添加支持tiff format,则需要添加新的 else if。
    • @NikitaSychou 我已经写了这个代码,只看到你提供的代码,没有任何地方写到这种情况可能会改变。是的,如果您添加其他格式及其特殊代码部分,那么此代码不会简化任何内容。
    【解决方案2】:

    只需ToString() ImageFormat,然后打开 (string) 结果?

    ImageFormat 覆盖 ToString 以产生“人​​类可读”的结果。见MSDN

    var desiredImageFormatName = imageFormatToConvert.ToString();
    
    switch (desriredImageFormatName)
    {
        case "JPEG": // or whatever ImageFormat.Jpeg.ToString() returns
            ...
    }
    

    【讨论】:

    • 我认为这不是一个好的解决方案,好像有一天ImageFormat.Jpeg.ToString() 会被更改,而不是Jpeg 将返回JPEG 他的代码将停止工作
    • @S.Petrosov:实际上,我同意。最好首先使用ImageFomat作为参数类型,而简单地使用enumstring,这样更容易switch。我不明白为什么必须为此使用该类型。
    • 我认为OP没有意识到在这种情况下使用switch的危险性,正在考虑如何简化代码。但结果,即使使用开关,代码也将与他已有的非常相似。
    • @S.Petrosov:是的,我同意 switch 不会提供难以置信的简化代码。 Gary McGill, S.Petrosov 感谢两位!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    • 2021-12-27
    • 1970-01-01
    • 2017-03-26
    • 2016-04-09
    • 2015-12-16
    • 2011-07-22
    相关资源
    最近更新 更多