C # converte o valor RGB em CMYK usando um perfil ICC?

esta pergunta parece postada em muitos lugares sobre as interwebs e SO, mas eu não consegui encontrar uma resposta satisfatória 🙁

Como posso converter um valor RGB em um valor CMYK usando um perfil ICC?

A resposta mais próxima que eu tenho está lá, onde explica como converter de CMYK para RGB, mas não o contrário, que é o que eu preciso. (http://stackoverflow.com/questions/4920482/cmyk-to-rgb-formula-of-photoshop/5076731#5076731)

float[] colorValues = new float[4]; colorValues[0] = c / 255f; colorValues[1] = m / 255f; colorValues[2] = y / 255f; colorValues[3] = k / 255f; System.Windows.Media.Color color = Color.FromValues(colorValues, new Uri(@"C:\Users\me\Documents\ISOcoated_v2_300_eci.icc")); System.Drawing.Color rgbColor = System.Drawing.Color.FromArgb(color.R, color.G, color.B); 

Eu acho que eu deveria estar usando algumas classs / estruturas / methods do namespace System.Windows.Media.

A estrutura System.Windows.Media.Color contém um método FromRgb, mas não consigo obter valores CMYK depois, fora desse System.Windows.Media.Color!

Muito Obrigado

Eu não sei de qualquer API C # ou biblioteca que pode conseguir isso. No entanto, se você tiver conhecimento C / C ++ suficiente para criar um wrapper para c #, vejo duas opções:

  • Sistema de colors do Windows (WCS) (parte do Windows)
  • LittleCMS

O namespace System.Windows.Media é muito limitado. Há provavelmente um mecanismo poderoso (WCS?) Por trás dele, mas apenas uma pequena parte é disponibilizada.

Atualizar:

Aqui está um código C # para fazer a conversão usando o WCS. Certamente poderia usar um wrapper que facilitaria o uso:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace ICM { public class WindowsColorSystem { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public class ProfileFilename { public uint type; [MarshalAs(UnmanagedType.LPTStr)] public string profileData; public uint dataSize; public ProfileFilename(string filename) { type = ProfileFilenameType; profileData = filename; dataSize = (uint)filename.Length * 2 + 2; } }; public const uint ProfileFilenameType = 1; public const uint ProfileMembufferType = 2; public const uint ProfileRead = 1; public const uint ProfileReadWrite = 2; public enum FileShare : uint { Read = 1, Write = 2, Delete = 4 }; public enum CreateDisposition : uint { CreateNew = 1, CreateAlways = 2, OpenExisting = 3, OpenAlways = 4, TruncateExisting = 5 }; public enum LogicalColorSpace : uint { CalibratedRGB = 0x00000000, sRGB = 0x73524742, WindowsColorSpace = 0x57696E20 }; public enum ColorTransformMode : uint { ProofMode = 0x00000001, NormalMode = 0x00000002, BestMode = 0x00000003, EnableGamutChecking = 0x00010000, UseRelativeColorimetric = 0x00020000, FastTranslate = 0x00040000, PreserveBlack = 0x00100000, WCSAlways = 0x00200000 }; enum ColorType : int { Gray = 1, RGB = 2, XYZ = 3, Yxy = 4, Lab = 5, _3_Channel = 6, CMYK = 7, _5_Channel = 8, _6_Channel = 9, _7_Channel = 10, _8_Channel = 11, Named = 12 }; public const uint IntentPerceptual = 0; public const uint IntentRelativeColorimetric = 1; public const uint IntentSaturation = 2; public const uint IntentAbsoluteColorimetric = 3; public const uint IndexDontCare = 0; [StructLayout(LayoutKind.Sequential)] public struct RGBColor { public ushort red; public ushort green; public ushort blue; public ushort pad; }; [StructLayout(LayoutKind.Sequential)] public struct CMYKColor { public ushort cyan; public ushort magenta; public ushort yellow; public ushort black; }; [DllImport("mscms.dll", SetLastError = true, EntryPoint = "OpenColorProfileW", CallingConvention = CallingConvention.Winapi)] static extern IntPtr OpenColorProfile( [MarshalAs(UnmanagedType.LPStruct)] ProfileFilename profile, uint desiredAccess, FileShare shareMode, CreateDisposition creationMode); [DllImport("mscms.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] static extern bool CloseColorProfile(IntPtr hProfile); [DllImport("mscms.dll", SetLastError = true, EntryPoint = "GetStandardColorSpaceProfileW", CallingConvention = CallingConvention.Winapi)] static extern bool GetStandardColorSpaceProfile( uint machineName, LogicalColorSpace profileID, [MarshalAs(UnmanagedType.LPTStr), In, Out] StringBuilder profileName, ref uint size); [DllImport("mscms.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] static extern IntPtr CreateMultiProfileTransform( [In] IntPtr[] profiles, uint nProfiles, [In] uint[] intents, uint nIntents, ColorTransformMode flags, uint indexPreferredCMM); [DllImport("mscms.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] static extern bool DeleteColorTransform(IntPtr hTransform); [DllImport("mscms.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] static extern bool TranslateColors( IntPtr hColorTransform, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), In] RGBColor[] inputColors, uint nColors, ColorType ctInput, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Out] CMYKColor[] outputColors, ColorType ctOutput); public static void Test() { bool success; StringBuilder profileName = new StringBuilder(256); uint size = (uint)profileName.Capacity * 2; success = GetStandardColorSpaceProfile(0, LogicalColorSpace.sRGB, profileName, ref size); ProfileFilename sRGBFilename = new ProfileFilename(profileName.ToString()); IntPtr hSRGBProfile = OpenColorProfile(sRGBFilename, ProfileRead, FileShare.Read, CreateDisposition.OpenExisting); ProfileFilename isoCoatedFilename = new ProfileFilename(@"C:\Users\me\Documents\ISOcoated_v2_300_eci.icc"); IntPtr hIsoCoatedProfile = OpenColorProfile(isoCoatedFilename, ProfileRead, FileShare.Read, CreateDisposition.OpenExisting); IntPtr[] profiles = new IntPtr[] { hSRGBProfile, hIsoCoatedProfile }; uint[] intents = new uint[] { IntentPerceptual }; IntPtr transform = CreateMultiProfileTransform(profiles, 2, intents, 1, ColorTransformMode.BestMode, IndexDontCare); RGBColor[] rgbColors = new RGBColor[1]; rgbColors[0] = new RGBColor(); CMYKColor[] cmykColors = new CMYKColor[1]; cmykColors[0] = new CMYKColor(); rgbColors[0].red = 30204; rgbColors[0].green = 4420; rgbColors[0].blue = 60300; success = TranslateColors(transform, rgbColors, 1, ColorType.RGB, cmykColors, ColorType.CMYK); success = DeleteColorTransform(transform); success = CloseColorProfile(hSRGBProfile); success = CloseColorProfile(hIsoCoatedProfile); } } } 

Nenhuma das respostas aqui parece abordar satisfatoriamente a necessidade de usar um perfil ICC.

Eu encontrei uma página de problema do MS Connect que tem algum código de amostra usando o Windows Imaging Components para converter um JPEG RBG em CMYK usando um perfil ICC.

Se você tiver seu arquivo ICC e um arquivo JPEG de amostra, poderá configurar um aplicativo de console para usar esse código muito rapidamente.

Salvei o perfil ICC em uma pasta chamada “Profiles” e defini o valor “Copy to Output Directory” para “Always”.

O JPEG é salvo em uma pasta chamada “Imagens” e eu configurei seu valor “Build Action” para “Recurso Incorporado”.

O projeto do aplicativo de console precisa de referências aos seguintes módulos:

  • ApresentaçãoCor
  • System.Xaml
  • WindowsBase

O aplicativo de console na íntegra (chamado CMYKConversion):

Program.cs:

 using System; namespace CMYKConversion { class Program { static void Main(string[] args) { Converter c = new Converter(); c.Convert(); Console.ReadKey(); } } } 

Converter.cs:

 using System; using System.IO; using System.Reflection; using System.Windows.Media; using System.Windows.Media.Imaging; namespace CMYKConversion { public class Converter { public void Convert() { var rgbJpeg = BitmapFrame.Create(GetStreamFromResource("CMYKConversion.Images.Desert.jpg")); var iccCmykJpeg = new ColorConvertedBitmap( rgbJpeg, new ColorContext(PixelFormats.Default), new ColorContext(GetProfilePath("Profiles/1010_ISO_Coated_39L.icc")), PixelFormats.Cmyk32 ); var jpegBitmapEncoder = new JpegBitmapEncoder(); jpegBitmapEncoder.Frames.Add(BitmapFrame.Create(iccCmykJpeg)); var iccCmykJpegStream = new MemoryStream(); jpegBitmapEncoder.Save(iccCmykJpegStream); iccCmykJpegStream.Flush(); SaveMemoryStream(iccCmykJpegStream, "C:\\desertCMYK.jpg"); iccCmykJpegStream.Close(); } private Stream GetStreamFromResource(string name) { return typeof(Program).Assembly.GetManifestResourceStream(name); } private Uri GetProfilePath(string name) { string folder = Path.GetDirectoryName(Assembly.GetAssembly(typeof(Program)).CodeBase); return new Uri(Path.Combine(folder, name)); } private void SaveMemoryStream(MemoryStream ms, string fileName) { FileStream outStream = File.OpenWrite(fileName); ms.WriteTo(outStream); outStream.Flush(); outStream.Close(); } } } 

De acordo com um MVP, o GDI + pode ler CMYK, mas não pode codificá-lo (fonte: http://www.pcreview.co.uk/forums/convert-rgb-image-cmyk-t1419911.html ). Eles dizem que usar o TIF como um formato de intermediação pode ser o caminho a percorrer.

Além disso, você pode experimentar o SDK de geração de charts da Graphics Mill para .NET em http://imaging.aurigma.com/ (não sou afiliado a essa empresa).

Eu sei que isso não é muito de uma resposta, mas esperançosamente ele lança alguma luz e aponta você na direção certa.

Você poderia dar uma olhada nisso: Converter colors RGB em CMYK?

Embora esta conversão seja bastante subjetiva, daí a necessidade do perfil ICC, pode ser que você possa extrair esse “fator” do ICC e ajustar a fórmula?

Qual é o contexto em que você precisa converter os valores RGB em CMYK?