如何使用C在ASP.NET中识别CMYK图像#
有人知道如何使用C#正确识别ASP.NET中的CMYK图像吗?当我检查如何使用C在ASP.NET中识别CMYK图像#,asp.net,image-processing,bitmap,cmyk,Asp.net,Image Processing,Bitmap,Cmyk,有人知道如何使用C#正确识别ASP.NET中的CMYK图像吗?当我检查位图实例的标志属性时,得到的结果不正确 我创建了三个图像来测试这一点:cmyk.jpg、rgb.jpg和gray.jpg。这些分别是CMYK、RGB和灰度图像 这是我的测试代码: static void Main(string[] args) { Bitmap bmpCMYK = new Bitmap("cmyk.jpg"); Bitmap bmpRGB = new Bitmap("rgb.jpg");
位图
实例的标志
属性时,得到的结果不正确
我创建了三个图像来测试这一点:cmyk.jpg、rgb.jpg和gray.jpg。这些分别是CMYK、RGB和灰度图像
这是我的测试代码:
static void Main(string[] args)
{
Bitmap bmpCMYK = new Bitmap("cmyk.jpg");
Bitmap bmpRGB = new Bitmap("rgb.jpg");
Bitmap bmpGray = new Bitmap("gray.jpg");
Console.WriteLine("\t\tRgb\tCmyk\tGray\tYcbcr\tYcck\tPixelFormat");
Console.WriteLine("cmyk.jpg\t{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
IsSet(bmpCMYK, System.Drawing.Imaging.ImageFlags.ColorSpaceRgb),
IsSet(bmpCMYK, System.Drawing.Imaging.ImageFlags.ColorSpaceCmyk),
IsSet(bmpCMYK, System.Drawing.Imaging.ImageFlags.ColorSpaceGray),
IsSet(bmpCMYK, System.Drawing.Imaging.ImageFlags.ColorSpaceYcbcr),
IsSet(bmpCMYK, System.Drawing.Imaging.ImageFlags.ColorSpaceYcck),
bmpCMYK.PixelFormat);
Console.WriteLine("rgb.jpg\t\t{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
IsSet(bmpRGB, System.Drawing.Imaging.ImageFlags.ColorSpaceRgb),
IsSet(bmpRGB, System.Drawing.Imaging.ImageFlags.ColorSpaceCmyk),
IsSet(bmpRGB, System.Drawing.Imaging.ImageFlags.ColorSpaceGray),
IsSet(bmpRGB, System.Drawing.Imaging.ImageFlags.ColorSpaceYcbcr),
IsSet(bmpRGB, System.Drawing.Imaging.ImageFlags.ColorSpaceYcck),
bmpRGB.PixelFormat);
Console.WriteLine("gray.jpg\t{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
IsSet(bmpGray, System.Drawing.Imaging.ImageFlags.ColorSpaceRgb),
IsSet(bmpGray, System.Drawing.Imaging.ImageFlags.ColorSpaceCmyk),
IsSet(bmpGray, System.Drawing.Imaging.ImageFlags.ColorSpaceGray),
IsSet(bmpGray, System.Drawing.Imaging.ImageFlags.ColorSpaceYcbcr),
IsSet(bmpGray, System.Drawing.Imaging.ImageFlags.ColorSpaceYcck),
bmpGray.PixelFormat);
bmpCMYK.Dispose();
bmpRGB.Dispose();
bmpGray.Dispose();
Console.ReadLine();
}
private static bool IsSet(Bitmap bitmap, System.Drawing.Imaging.ImageFlags flag)
{
return (bitmap.Flags & (int)flag) == (int)flag;
}
这将产生以下输出:
我已经检查了实际图像,cmyk.jpg实际上是一个cmyk图像
显然,这是一个“已知问题”。Alex Gil在WPF中也遇到了同样的问题(请看这个问题:),他通过使用BitmapDecoder
类来加载图像,成功地解决了这个问题。我对在ASP.NET中使用该解决方案感到有点不舒服,因为它需要我添加对WindowsBase.dll和PresentationCore.dll的引用,而且我不确定是否希望在web项目中使用这些引用
是否有人知道其他纯.NET解决方案可以检查图像是否为CMYK格式,我可以在ASP.NET中安全使用?一个想法:如果您不想在web项目中引用这些dll,您可以在web项目之外的服务中进行处理,哪一种可能更好?我假设.NET中的所有内容都基于
RGB
、aRGB
和灰度(因为灰度是RGB(128,128,128))
如果我的假设是正确的,那么您将不得不选择第三方路径。您可能会检查哪个是win32 DLL,但有一个.NET包装器,我正在生产环境中使用它,这很好
如果它不能提供这些信息,我会感到惊讶
(编辑)在您要求纯.NET解决方案之前,我没有注意到—所以这可能行不通—但我发现它是对.NET framework图像处理局限性的有用补充
如果只需要识别格式,另一个想法是直接从文件中提取格式。我不知道JPEG格式的规范可能有多复杂,但是,嘿,这只是最可靠的方法,最可靠的方法是解析文件头以检索数据。因此,我是如何解决您遇到的问题的,这与我遇到的问题相同。当您知道它是100%a cymk图像时,csharp中的所有内容都会返回rgb信息。那么要做什么呢,我们转到根目录并读取文件。以下是我所做的工作和测试,工作良好,应该涵盖所有操作系统,50对50的IMG测试正确。这也是2.0,以防万一
public bool isByteACMYK(Stream image)
{
using (StreamReader sr = new StreamReader(image))
{
string contents = sr.ReadToEnd();
if (contents.ToLower().Contains("cmyk"))
{
return true;
}
}
return false;
}
public bool isFileACMYKJpeg(System.Drawing.Image image)
{
System.Drawing.Imaging.ImageFlags flagValues = (System.Drawing.Imaging.ImageFlags)Enum.Parse(typeof(System.Drawing.Imaging.ImageFlags), image.Flags.ToString());
if (flagValues.ToString().ToLower().IndexOf("ycck") == -1)
{
// based on http://www.maxostudio.com/Tut_CS_CMYK.cfm
bool ret = false;
try{
int cmyk = (image.Flags & (int)ImageFlags.ColorSpaceCmyk);
int ycck = (image.Flags & (int)ImageFlags.ColorSpaceYcck);
ret = ((cmyk > 0) || (ycck > 0));
} catch (Exception ex){
}
return ret;
}
return true;
}
// my upload test .. but you could turn a file to stream and do the same
public void UpdatePool(HttpPostedFile newimage)
{
if (newimage.ContentLength != 0)
{
Stream stream = newimage.InputStream;
MemoryStream memoryStream = new MemoryStream();
CopyStream(stream,memoryStream);
memoryStream.Position = 0;
stream = memoryStream;
System.Drawing.Image processed_image = null;
processed_image = System.Drawing.Image.FromStream(newimage.InputStream);
if (imageService.isFileACMYKJpeg(processed_image) || imageService.isByteACMYK(stream))
{
Flash["error"] = "You have uploaded a CMYK image. Please conver to RGB first.";
RedirectToReferrer();
return;
}
}
}
干杯-Jeremy我使用ImageFlags和PixelFormat值的组合。请注意,.NET中缺少PixelFormat.Forma32bppCMYK-我从Windows SDK中的GdiPlusPixelFormats.h中获取了它 诀窍在于Windows7和Server2008R2返回正确的像素格式,但缺少图像标志。Vista和Server 2008返回的像素格式无效,但图像标志正确。疯狂
public ImageColorFormat GetColorFormat(this Bitmap bitmap)
{
const int pixelFormatIndexed = 0x00010000;
const int pixelFormat32bppCMYK = 0x200F;
const int pixelFormat16bppGrayScale = (4 | (16 << 8);
// Check image flags
var flags = (ImageFlags)bitmap.Flags;
if (flags.HasFlag(ImageFlags.ColorSpaceCmyk) || flags.HasFlag(ImageFlags.ColorSpaceYcck))
{
return ImageColorFormat.Cmyk;
}
else if (flags.HasFlag(ImageFlags.ColorSpaceGray))
{
return ImageColorFormat.Grayscale;
}
// Check pixel format
var pixelFormat = (int)bitmap.PixelFormat;
if (pixelFormat == pixelFormat32bppCMYK)
{
return ImageColorFormat.Cmyk;
}
else if ((pixelFormat & pixelFormatIndexed) != 0)
{
return ImageColorFormat.Indexed;
}
else if (pixelFormat == pixelFormat16bppGrayScale)
{
return ImageColorFormat.Grayscale;
}
// Default to RGB
return ImageColorFormat.Rgb;
}
public enum ImageColorFormat
{
Rgb,
Cmyk,
Indexed,
Grayscale
}
publicmagecolorformat GetColorFormat(此位图)
{
const int pixelformatindex=0x00010000;
const int pixelFormat32bppCMYK=0x200F;
常量int像素格式16bppgrayscale=(4 |(16)这确实可能是一个解决方案,但我正在尝试创建一个小型的、可重用的库,用于在web应用程序中保存和调整图像大小。我认为在这种情况下,让它依赖于服务不是一个好主意坦白地说,一旦你开始调整真正大的图像大小(不需要大到磁盘才能大到内存),它很快就会变得混乱,内存和/或cpu和/或磁盘方面的。现在,所有图像操作都由一个简单的服务处理,它使用图形魔术:我放了一个作业文件(src-image,resize-options,dst-image)在一个文件夹中,服务会将其拾取并调整图像的大小。web服务永远不会以这种方式占用。