public static SafeTransformHandle CreateTransform(SafeProfileHandle sourceProfile, SafeProfileHandle destinationProfile, mscmsIntent dwIntent) { if (sourceProfile == null || sourceProfile.IsInvalid) { throw new ArgumentNullException("sourceProfile"); } if (destinationProfile == null || destinationProfile.IsInvalid) { throw new ArgumentNullException("destinationProfile"); } IntPtr[] handles = new IntPtr[2]; bool success = true; sourceProfile.DangerousAddRef(ref success); destinationProfile.DangerousAddRef(ref success); try { handles[0] = sourceProfile.DangerousGetHandle(); handles[1] = destinationProfile.DangerousGetHandle(); uint[] dwIntents = new uint[2] { (uint)dwIntent, (uint)dwIntent }; var htransform = CreateMultiProfileTransform( handles, (uint)handles.Length, dwIntents, (uint)dwIntents.Length, BEST_MODE | USE_RELATIVE_COLORIMETRIC, 0); if (htransform.IsInvalid) { throw new Win32Exception(); } return(htransform); } finally { sourceProfile.DangerousRelease(); destinationProfile.DangerousRelease(); } }
public static unsafe RGBQUAD[] TransformColorsTo_sRGB(SafeProfileHandle source, RGBQUAD[] color, mscmsIntent dwIntent) { var colorSize = Environment.Is64BitProcess ? 16 : 8; var size = colorSize * color.Length; // https://docs.microsoft.com/en-us/windows/win32/api/icm/nf-icm-translatecolors // https://docs.microsoft.com/en-us/windows/win32/api/icm/ns-icm-color IntPtr paInputColors = Marshal.AllocHGlobal(size); IntPtr paOutputColors = Marshal.AllocHGlobal(size); const double cmax = 255d; const double nmax = 0xFFFF; const ushort nmask = 0xFFFF; try { var inputPtr = (byte *)paInputColors; foreach (var c in color) { var nclr = (long)(c.rgbRed / cmax * nmax) | ((long)(c.rgbGreen / cmax * nmax) << 16) | ((long)(c.rgbBlue / cmax * nmax) << 32); *((long *)inputPtr) = nclr; inputPtr += colorSize; } using (var dest = OpenProfile_sRGB()) using (var transform = CreateTransform(source, dest, dwIntent)) { var success = TranslateColors(transform, paInputColors, (uint)color.Length, COLOR_TYPE.COLOR_3_CHANNEL, paOutputColors, COLOR_TYPE.COLOR_3_CHANNEL); if (!success) { throw new Win32Exception(); } var outputPtr = (byte *)paOutputColors; var output = new RGBQUAD[color.Length]; for (int i = 0; i < color.Length; i++) { long nclr = *((long *)outputPtr); output[i] = new RGBQUAD { rgbRed = (byte)((nclr & nmask) / nmax * cmax), rgbGreen = (byte)(((nclr >> 16) & nmask) / nmax * cmax), rgbBlue = (byte)(((nclr >> 32) & nmask) / nmax * cmax), }; outputPtr += colorSize; } return(output); } } finally { Marshal.FreeHGlobal(paInputColors); Marshal.FreeHGlobal(paOutputColors); } }
public static unsafe void TransformPixelsTo_sRGB(SafeProfileHandle source, mscmsPxFormat pxFormat, void *data, int width, int height, uint stride, mscmsIntent dwIntent) { using (var dest = OpenProfile_sRGB()) using (var transform = CreateTransform(source, dest, dwIntent)) { var success = TranslateBitmapBits(transform, data, pxFormat, (uint)width, (uint)height, stride, data, pxFormat, stride, IntPtr.Zero, IntPtr.Zero); if (!success) { throw new Win32Exception(); } } }