/// <summary> /// Performs color correction on the specified 8-bit gray scale image data and converts it to RGB. /// </summary> /// <param name="srcPtr">The pointer to the start of the gray scale image data.</param> /// <param name="srcStride">The stride of the gray scale image data.</param> /// <param name="origin">The starting row and column offset in the image data buffer.</param> /// <param name="destSurface">The destination surface.</param> /// <returns><c>true</c> if the image data was successfully converted; otherwise, <c>false</c>.</returns> /// <exception cref="ArgumentNullException"><paramref name="destSurface"/> is null.</exception> public unsafe bool ColorCorrectGrayScale(IntPtr srcPtr, int srcStride, Point origin, IDisplayPixelsSurface destSurface) { if (destSurface == null) { throw new ArgumentNullException(nameof(destSurface)); } if (transform == null) { return(false); } byte *srcDataStart = (byte *)srcPtr + (origin.Y * srcStride) + origin.X; return(UnsafeNativeMethods.Mscms.TranslateBitmapBits( transform, (IntPtr)srcDataStart, NativeEnums.Mscms.BMFORMAT.BM_GRAY, (uint)destSurface.Width, (uint)destSurface.Height, (uint)srcStride, destSurface.Scan0.Pointer, destSurface.MscmsFormat, (uint)destSurface.Stride, IntPtr.Zero, IntPtr.Zero )); }
/// <summary> /// Performs color correction on the RGB image data. /// </summary> /// <param name="srcPtr">The pointer to the start of the image data..</param> /// <param name="srcRowBytes">The source row bytes.</param> /// <param name="srcColBytes">The source column bytes.</param> /// <param name="srcPlaneBytes">The source plane bytes.</param> /// <param name="origin">The origin.</param> /// <param name="destinationSurface">The destination surface.</param> /// <returns><c>true</c> if the image data was successfully converted; otherwise, <c>false</c>.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="destinationSurface"/> is null. /// </exception> public unsafe bool ColorCorrectRGB( IntPtr srcPtr, int srcRowBytes, int srcColBytes, int srcPlaneBytes, Point origin, IDisplayPixelsSurface destinationSurface) { if (destinationSurface == null) { throw new ArgumentNullException(nameof(destinationSurface)); } if (transform == null) { return(false); } if (srcColBytes == 1) { // As the Windows Color System APIs do not support planar order image data we have to convert the // image data to interleaved and then use a second surface for the final color correction. if (interleavedRGBSurface == null || interleavedRGBSurface.Width != destinationSurface.Width || interleavedRGBSurface.Height != destinationSurface.Height) { interleavedRGBSurface?.Dispose(); interleavedRGBSurface = new SurfaceBGR24(destinationSurface.Width, destinationSurface.Height); } int top = origin.Y; int left = origin.X; int bottom = top + interleavedRGBSurface.Height; int right = left + interleavedRGBSurface.Width; byte *baseAddr = (byte *)srcPtr; int greenPlaneOffset = srcPlaneBytes; int bluePlaneOffset = srcPlaneBytes * 2; for (int y = top; y < bottom; y++) { byte *redPlane = baseAddr + (y * srcRowBytes) + left; byte *greenPlane = redPlane + greenPlaneOffset; byte *bluePlane = redPlane + bluePlaneOffset; byte *dst = interleavedRGBSurface.GetRowAddressUnchecked(y - top); for (int x = left; x < right; x++) { dst[2] = *redPlane; dst[1] = *greenPlane; dst[0] = *bluePlane; redPlane++; greenPlane++; bluePlane++; dst += 3; } } return(UnsafeNativeMethods.Mscms.TranslateBitmapBits( transform, interleavedRGBSurface.Scan0.Pointer, interleavedRGBSurface.MscmsFormat, (uint)destinationSurface.Width, (uint)destinationSurface.Height, (uint)interleavedRGBSurface.Stride, destinationSurface.Scan0.Pointer, destinationSurface.MscmsFormat, (uint)destinationSurface.Stride, IntPtr.Zero, IntPtr.Zero )); } else { NativeEnums.Mscms.BMFORMAT srcFormat; switch (srcColBytes) { case 3: srcFormat = NativeEnums.Mscms.BMFORMAT.BM_BGRTRIPLETS; break; case 4: srcFormat = NativeEnums.Mscms.BMFORMAT.BM_xBGRQUADS; break; default: throw new InvalidOperationException("Unsupported column bytes value."); } byte *srcDataStart = (byte *)srcPtr + (origin.Y * srcRowBytes) + (origin.X * srcColBytes); return(UnsafeNativeMethods.Mscms.TranslateBitmapBits( transform, (IntPtr)srcDataStart, srcFormat, (uint)destinationSurface.Width, (uint)destinationSurface.Height, (uint)srcRowBytes, destinationSurface.Scan0.Pointer, destinationSurface.MscmsFormat, (uint)destinationSurface.Stride, IntPtr.Zero, IntPtr.Zero )); } }
/// <summary> /// Performs color correction on the specified 8-bit CMYK image data and converts it to RGB.. /// </summary> /// <param name="srcPtr">The pointer to the start of the image data..</param> /// <param name="srcRowBytes">The source row bytes.</param> /// <param name="srcColBytes">The source column bytes.</param> /// <param name="srcPlaneBytes">The source plane bytes.</param> /// <param name="origin">The origin.</param> /// <param name="destinationSurface">The destination surface.</param> /// <returns><c>true</c> if the image data was successfully converted; otherwise, <c>false</c>.</returns> public unsafe bool ColorCorrectCMYK( IntPtr srcPtr, int srcRowBytes, int srcColBytes, int srcPlaneBytes, Point origin, IDisplayPixelsSurface destinationSurface) { if (destinationSurface == null) { throw new ArgumentNullException(nameof(destinationSurface)); } if (transform == null) { return(false); } if (srcColBytes == 1) { // As the Windows Color System APIs do not support planar order image data we have to convert the // image data to interleaved and then use a second surface for the final color correction. if (interleavedCMYKSurface == null || interleavedCMYKSurface.Width != destinationSurface.Width || interleavedCMYKSurface.Height != destinationSurface.Height) { interleavedCMYKSurface?.Dispose(); interleavedCMYKSurface = new SurfaceCMYK32(destinationSurface.Width, destinationSurface.Height); } int top = origin.Y; int left = origin.X; int bottom = top + interleavedCMYKSurface.Height; int right = left + interleavedCMYKSurface.Width; byte *baseAddr = (byte *)srcPtr; int magentaPlaneOffset = srcPlaneBytes; int yellowPlaneOffset = magentaPlaneOffset + srcPlaneBytes; int blackPlaneOffset = yellowPlaneOffset + srcPlaneBytes; for (int y = top; y < bottom; y++) { byte *cyanPlane = baseAddr + (y * srcRowBytes) + left; byte *magentaPlane = cyanPlane + magentaPlaneOffset; byte *yellowPlane = cyanPlane + yellowPlaneOffset; byte *blackPlane = cyanPlane + blackPlaneOffset; byte *dst = interleavedCMYKSurface.GetRowAddressUnchecked(y - top); for (int x = left; x < right; x++) { dst[0] = *cyanPlane; dst[1] = *magentaPlane; dst[2] = *yellowPlane; dst[3] = *blackPlane; cyanPlane++; magentaPlane++; yellowPlane++; blackPlane++; dst += 4; } } return(UnsafeNativeMethods.Mscms.TranslateBitmapBits( transform, interleavedCMYKSurface.Scan0.Pointer, interleavedCMYKSurface.MscmsFormat, (uint)destinationSurface.Width, (uint)destinationSurface.Height, (uint)interleavedCMYKSurface.Stride, destinationSurface.Scan0.Pointer, destinationSurface.MscmsFormat, (uint)destinationSurface.Stride, IntPtr.Zero, IntPtr.Zero )); } else { byte *srcDataStart = (byte *)srcPtr + (origin.Y * srcRowBytes) + (origin.X * srcColBytes); return(UnsafeNativeMethods.Mscms.TranslateBitmapBits( transform, (IntPtr)srcDataStart, NativeEnums.Mscms.BMFORMAT.BM_KYMCQUADS, (uint)destinationSurface.Width, (uint)destinationSurface.Height, (uint)srcRowBytes, destinationSurface.Scan0.Pointer, destinationSurface.MscmsFormat, (uint)destinationSurface.Stride, IntPtr.Zero, IntPtr.Zero )); } }