/// <summary> /// Function to expand a 16BPP scan line in an image to a 32BPP RGBA line. /// </summary> /// <param name="src">The pointer to the source data.</param> /// <param name="srcPitch">The pitch of the source data.</param> /// <param name="srcFormat">Format to convert from.</param> /// <param name="dest">The pointer to the destination data.</param> /// <param name="destPitch">The pitch of the destination data.</param> /// <param name="bitFlags">Image bit conversion control flags.</param> /// <exception cref="ArgumentException">Thrown when the <paramref name="srcFormat" /> is not a 16 BPP format.</exception> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="src"/> or the <paramref name="dest"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when the <paramref name="srcPitch"/> or the <paramref name="destPitch"/> parameter is less than 0.</exception> /// <remarks> /// <para> /// Use this to expand a 16 BPP (B5G6R5 or B5G5R5A1 format) into a 32 BPP R8G8B8A8 (normalized unsigned integer) format. /// </para> /// </remarks> public static unsafe void Expand16BPPScanline(void *src, int srcPitch, BufferFormat srcFormat, void *dest, int destPitch, ImageBitFlags bitFlags) { ushort *srcPtr = (ushort *)src; uint * destPtr = (uint *)dest; if ((srcFormat != BufferFormat.B5G5R5A1_UNorm) && (srcFormat != BufferFormat.B5G6R5_UNorm) && (srcFormat != BufferFormat.B4G4R4A4_UNorm)) { throw new ArgumentException(string.Format(Resources.GORIMG_ERR_FORMAT_IS_NOT_16BPP, srcFormat), nameof(srcFormat)); } if (src == null) { throw new ArgumentNullException(nameof(src)); } if (dest == null) { throw new ArgumentNullException(nameof(dest)); } for (int srcCount = 0, destCount = 0; ((srcCount < srcPitch) && (destCount < destPitch)); srcCount += 2, destCount += 4) { ushort srcPixel = *(srcPtr++); uint R = 0, G = 0, B = 0, A = 0; switch (srcFormat) { case BufferFormat.B5G6R5_UNorm: R = (uint)((srcPixel & 0xF800) >> 11); G = (uint)((srcPixel & 0x07E0) >> 5); B = (uint)(srcPixel & 0x001F); R = ((R << 3) | (R >> 2)); G = ((G << 2) | (G >> 4)) << 8; B = ((B << 3) | (B >> 2)) << 16; A = 0xFF000000; break; case BufferFormat.B5G5R5A1_UNorm: R = (uint)((srcPixel & 0x7C00) >> 10); G = (uint)((srcPixel & 0x03E0) >> 5); B = (uint)(srcPixel & 0x001F); R = ((R << 3) | (R >> 2)); G = ((G << 3) | (G >> 2)) << 8; B = ((B << 3) | (B >> 2)) << 16; A = ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) ? 0xFF000000 : (((srcPixel & 0x8000) != 0) ? 0xFF000000 : 0); break; case BufferFormat.B4G4R4A4_UNorm: A = (uint)((srcPixel & 0xF000) >> 12); R = (uint)((srcPixel & 0xF00) >> 8); G = (uint)((srcPixel & 0xF0) >> 4); B = (uint)(srcPixel & 0xF); R = ((R << 4) | R); G = ((G << 4) | G) << 8; B = ((B << 4) | B) << 16; A = ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) ? 0xFF000000 : ((A << 4) | A) << 24; break; } *(destPtr++) = R | G | B | A; } }
/// <summary> /// Function to copy (or update in-place) with bits swizzled to match another format. /// </summary> /// <param name="src">The pointer to the source data.</param> /// <param name="srcPitch">The pitch of the source data.</param> /// <param name="dest">The pointer to the destination data.</param> /// <param name="destPitch">The pitch of the destination data.</param> /// <param name="format">Format of the destination buffer.</param> /// <param name="bitFlags">Image bit conversion control flags.</param> /// <exception cref="ArgumentException">Thrown when the <paramref name="format"/> parameter is Unknown.</exception> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="src"/> or the <paramref name="dest"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when the <paramref name="srcPitch"/> or the <paramref name="destPitch"/> parameter is less than 0.</exception> /// <remarks> /// <para> /// Use this method to copy a single scanline and swizzle the bits of an image and (optionally) set an opaque constant alpha value. /// </para> /// </remarks> public static unsafe void SwizzleScanline(void *src, int srcPitch, void *dest, int destPitch, BufferFormat format, ImageBitFlags bitFlags) { int size = srcPitch.Min(destPitch); uint r, g, b, a, pixel; if (src == null) { throw new ArgumentNullException(nameof(src)); } if (dest == null) { throw new ArgumentNullException(nameof(dest)); } if (format == BufferFormat.Unknown) { throw new ArgumentException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, format), nameof(format)); } uint *srcPtr = (uint *)src; uint *destPtr = (uint *)dest; switch (format) { case BufferFormat.R10G10B10A2_Typeless: case BufferFormat.R10G10B10A2_UInt: case BufferFormat.R10G10B10A2_UNorm: case BufferFormat.R10G10B10_Xr_Bias_A2_UNorm: for (int i = 0; i < size; i += 4) { if (src != dest) { pixel = *(srcPtr++); } else { pixel = *(destPtr); } r = ((pixel & 0x3FF00000) >> 20); g = (pixel & 0x000FFC00); b = ((pixel & 0x000003FF) << 20); a = ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) ? 0xC0000000 : pixel & 0xC0000000; *destPtr = r | g | b | a; destPtr++; } return; case BufferFormat.R8G8B8A8_Typeless: case BufferFormat.R8G8B8A8_UNorm: case BufferFormat.R8G8B8A8_UNorm_SRgb: case BufferFormat.B8G8R8A8_UNorm: case BufferFormat.B8G8R8X8_UNorm: case BufferFormat.B8G8R8A8_Typeless: case BufferFormat.B8G8R8A8_UNorm_SRgb: case BufferFormat.B8G8R8X8_Typeless: case BufferFormat.B8G8R8X8_UNorm_SRgb: for (int i = 0; i < size; i += 4) { if (src != dest) { pixel = *(srcPtr++); } else { pixel = *(destPtr); } r = ((pixel & 0xFF0000) >> 16); g = (pixel & 0x00FF00); b = ((pixel & 0x0000FF) << 16); a = ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) ? 0xFF000000 : pixel & 0xFF000000; *destPtr = r | g | b | a; destPtr++; } return; } if (src != dest) { Unsafe.CopyBlock(dest, src, (uint)size); } }
/// <summary> /// Function to copy (or update in-place) a line with opaque alpha substituion (if required). /// </summary> /// <param name="src">The pointer to the source data.</param> /// <param name="srcPitch">The pitch of the source data.</param> /// <param name="dest">The pointer to the destination data.</param> /// <param name="destPitch">The pitch of the destination data.</param> /// <param name="format">Format of the destination buffer.</param> /// <param name="bitFlags">Image bit conversion control flags.</param> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="format"/> parameter is Unknown.</exception> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="src"/> or the <paramref name="dest"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when the <paramref name="srcPitch"/> or the <paramref name="destPitch"/> parameter is less than 0.</exception> /// <remarks>Use this method to copy a single scanline of an image and (optionally) set an opaque constant alpha value.</remarks> public static unsafe void CopyScanline(void *src, int srcPitch, void *dest, int destPitch, BufferFormat format, ImageBitFlags bitFlags) { if (src == null) { throw new ArgumentNullException(nameof(src)); } if (dest == null) { throw new ArgumentNullException(nameof(dest)); } if (format == BufferFormat.Unknown) { throw new ArgumentException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, format), nameof(format)); } int size = (src == dest) ? destPitch : (srcPitch.Min(destPitch)); if ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) { // Do a straight copy. switch (format) { case BufferFormat.R32G32B32A32_Typeless: case BufferFormat.R32G32B32A32_Float: case BufferFormat.R32G32B32A32_UInt: case BufferFormat.R32G32B32A32_SInt: { uint alpha = (format == BufferFormat.R32G32B32_Float) ? 0x3F800000 : ((format == BufferFormat.R32G32B32_SInt) ? 0x7FFFFFFF : 0xFFFFFFFF); uint *srcPtr = (uint *)src; uint *destPtr = (uint *)dest; for (int i = 0; i < size; i += 16) { // If not in-place copy, then copy from the source. if (src != dest) { *(destPtr++) = *(srcPtr++); *(destPtr++) = *(srcPtr++); *(destPtr++) = *(srcPtr++); } *(destPtr++) = alpha; } } return; case BufferFormat.R16G16B16A16_Typeless: case BufferFormat.R16G16B16A16_Float: case BufferFormat.R16G16B16A16_UNorm: case BufferFormat.R16G16B16A16_UInt: case BufferFormat.R16G16B16A16_SNorm: case BufferFormat.R16G16B16A16_SInt: { ushort alpha = 0xFFFF; switch (format) { case BufferFormat.R16G16B16A16_Float: alpha = 0x3C00; break; case BufferFormat.R16G16B16A16_SInt: case BufferFormat.R16G16B16A16_SNorm: alpha = 0x7FFF; break; } ushort *srcPtr = (ushort *)src; ushort *destPtr = (ushort *)dest; for (int i = 0; i < size; i += 8) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = *srcPtr; srcPtr += 4; } *destPtr += 3; *(destPtr++) = alpha; } } return; case BufferFormat.R10G10B10A2_Typeless: case BufferFormat.R10G10B10A2_UNorm: case BufferFormat.R10G10B10A2_UInt: case BufferFormat.R10G10B10_Xr_Bias_A2_UNorm: { uint *srcPtr = (uint *)src; uint *destPtr = (uint *)dest; for (int i = 0; i < size; i += 4) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = (*srcPtr) & 0x3FFFFFFF; srcPtr++; } *destPtr |= 0xC0000000; destPtr++; } } return; case BufferFormat.R8G8B8A8_Typeless: case BufferFormat.R8G8B8A8_UNorm: case BufferFormat.R8G8B8A8_UNorm_SRgb: case BufferFormat.R8G8B8A8_UInt: case BufferFormat.R8G8B8A8_SNorm: case BufferFormat.R8G8B8A8_SInt: case BufferFormat.B8G8R8A8_UNorm: case BufferFormat.B8G8R8A8_Typeless: case BufferFormat.B8G8R8A8_UNorm_SRgb: { uint alpha = ((format == BufferFormat.R8G8B8A8_SInt) || (format == BufferFormat.R8G8B8A8_SNorm)) ? 0x7F000000 : 0xFF000000; uint *srcPtr = (uint *)src; uint *destPtr = (uint *)dest; for (int i = 0; i < size; i += 4) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = (*srcPtr) & 0xFFFFFF; srcPtr++; } *destPtr |= alpha; destPtr++; } } return; case BufferFormat.B4G4R4A4_UNorm: { ushort *srcPtr = (ushort *)src; ushort *destPtr = (ushort *)dest; for (int i = 0; i < size; i += 2) { // If not in-place copy, then copy from the source. if (src != dest) { *(destPtr++) = (ushort)((*srcPtr++) | 0xF000); } else { *(destPtr++) |= 0xF000; } } } return; case BufferFormat.B5G5R5A1_UNorm: { ushort *srcPtr = (ushort *)src; ushort *destPtr = (ushort *)dest; for (int i = 0; i < size; i += 2) { // If not in-place copy, then copy from the source. if (src != dest) { *(destPtr++) = (ushort)((*srcPtr++) | 0x8000); } else { *(destPtr++) |= 0x8000; } } } return; case BufferFormat.A8_UNorm: Unsafe.InitBlock(dest, 0xff, (uint)size); return; } } // Copy if not doing an in-place update. if (dest != src) { Unsafe.CopyBlock(dest, src, (uint)size); } }
/// <summary> /// Function to copy (or update in-place) a line with opaque alpha substituion (if required). /// </summary> /// <param name="src">The pointer to the source data.</param> /// <param name="srcPitch">The pitch of the source data.</param> /// <param name="dest">The pointer to the destination data.</param> /// <param name="destPitch">The pitch of the destination data.</param> /// <param name="format">Format of the destination buffer.</param> /// <param name="bitFlags">Image bit conversion control flags.</param> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="format"/> parameter is Unknown.</exception> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="src"/> or the <paramref name="dest"/> parameter is NULL.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="srcPitch"/> or the <paramref name="destPitch"/> parameter is less than 0.</exception> /// <remarks>Use this method to copy a single scanline of an image and (optionally) set an opaque constant alpha value.</remarks> protected unsafe void CopyScanline(void *src, int srcPitch, void *dest, int destPitch, BufferFormat format, ImageBitFlags bitFlags) { if (src == null) { throw new ArgumentNullException("src"); } if (dest == null) { throw new ArgumentNullException("dest"); } if (format == BufferFormat.Unknown) { throw new ArgumentException(string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, BufferFormat.Unknown), "format"); } int size = (src == dest) ? destPitch : (srcPitch.Min(destPitch)); if ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) { // Do a straight copy. switch (format) { case BufferFormat.R32G32B32A32: case BufferFormat.R32G32B32A32_Float: case BufferFormat.R32G32B32A32_UInt: case BufferFormat.R32G32B32A32_Int: { uint alpha = (format == BufferFormat.R32G32B32_Float) ? 0x3F800000 : ((format == BufferFormat.R32G32B32_Int) ? 0x7FFFFFFF : 0xFFFFFFFF); var srcPtr = (uint *)src; var destPtr = (uint *)dest; for (int i = 0; i < size; i += 16) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = *srcPtr; srcPtr += 4; } *destPtr += 3; *(destPtr++) = alpha; } } return; case BufferFormat.R16G16B16A16: case BufferFormat.R16G16B16A16_Float: case BufferFormat.R16G16B16A16_UIntNormal: case BufferFormat.R16G16B16A16_UInt: case BufferFormat.R16G16B16A16_IntNormal: case BufferFormat.R16G16B16A16_Int: { ushort alpha = 0xFFFF; switch (format) { case BufferFormat.R16G16B16A16_Float: alpha = 0x3C00; break; case BufferFormat.R16G16B16A16_Int: case BufferFormat.R16G16B16A16_IntNormal: alpha = 0x7FFF; break; } var srcPtr = (ushort *)src; var destPtr = (ushort *)dest; for (int i = 0; i < size; i += 8) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = *srcPtr; srcPtr += 4; } *destPtr += 3; *(destPtr++) = alpha; } } return; case BufferFormat.R10G10B10A2: case BufferFormat.R10G10B10A2_UIntNormal: case BufferFormat.R10G10B10A2_UInt: case BufferFormat.R10G10B10_XR_BIAS_A2_UIntNormal: { var srcPtr = (uint *)src; var destPtr = (uint *)dest; for (int i = 0; i < size; i += 4) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = (*srcPtr) & 0x3FFFFFFF; srcPtr++; } *destPtr |= 0xC0000000; destPtr++; } } return; case BufferFormat.R8G8B8A8: case BufferFormat.R8G8B8A8_UIntNormal: case BufferFormat.R8G8B8A8_UIntNormal_sRGB: case BufferFormat.R8G8B8A8_UInt: case BufferFormat.R8G8B8A8_IntNormal: case BufferFormat.R8G8B8A8_Int: case BufferFormat.B8G8R8A8_UIntNormal: case BufferFormat.B8G8R8A8: case BufferFormat.B8G8R8A8_UIntNormal_sRGB: { uint alpha = ((format == BufferFormat.R8G8B8A8_Int) || (format == BufferFormat.R8G8B8A8_IntNormal)) ? 0x7F000000 : 0xFF000000; var srcPtr = (uint *)src; var destPtr = (uint *)dest; for (int i = 0; i < size; i += 4) { // If not in-place copy, then copy from the source. if (src != dest) { *destPtr = (*srcPtr) & 0xFFFFFF; srcPtr++; } *destPtr |= alpha; destPtr++; } } return; case BufferFormat.B5G5R5A1_UIntNormal: { var srcPtr = (ushort *)src; var destPtr = (ushort *)dest; for (int i = 0; i < size; i += 2) { // If not in-place copy, then copy from the source. if (src != dest) { *(destPtr++) = (ushort)((*srcPtr++) | 0x8000); } else { *(destPtr++) |= 0x8000; } } } return; case BufferFormat.A8_UIntNormal: DirectAccess.FillMemory(dest, 0xFF, size); return; } } // Copy if not doing an in-place update. if (dest != src) { DirectAccess.MemoryCopy(dest, src, size); } }
/// <summary> /// Function to copy (or update in-place) with bits swizzled to match another format. /// </summary> /// <param name="src">The pointer to the source data.</param> /// <param name="srcPitch">The pitch of the source data.</param> /// <param name="dest">The pointer to the destination data.</param> /// <param name="destPitch">The pitch of the destination data.</param> /// <param name="format">Format of the destination buffer.</param> /// <param name="bitFlags">Image bit conversion control flags.</param> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="format"/> parameter is Unknown.</exception> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="src"/> or the <paramref name="dest"/> parameter is NULL.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="srcPitch"/> or the <paramref name="destPitch"/> parameter is less than 0.</exception> /// <remarks>Use this method to copy a single scanline and swizzle the bits of an image and (optionally) set an opaque constant alpha value.</remarks> protected unsafe void SwizzleScanline(void *src, int srcPitch, void *dest, int destPitch, BufferFormat format, ImageBitFlags bitFlags) { int size = srcPitch.Min(destPitch); uint r, g, b, a, pixel; if (src == null) { throw new ArgumentNullException("src"); } if (dest == null) { throw new ArgumentNullException("dest"); } if (format == BufferFormat.Unknown) { throw new ArgumentException(string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, BufferFormat.Unknown), "format"); } var srcPtr = (uint *)src; var destPtr = (uint *)dest; switch (format) { case BufferFormat.R10G10B10A2: case BufferFormat.R10G10B10A2_UInt: case BufferFormat.R10G10B10A2_UIntNormal: case BufferFormat.R10G10B10_XR_BIAS_A2_UIntNormal: for (int i = 0; i < size; i += 4) { if (src != dest) { pixel = *(srcPtr++); } else { pixel = *(destPtr); } r = ((pixel & 0x3FF00000) >> 20); g = (pixel & 0x000FFC00); b = ((pixel & 0x000003FF) << 20); a = ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) ? 0xC0000000 : pixel & 0xC0000000; *destPtr = r | g | b | a; destPtr++; } return; case BufferFormat.R8G8B8A8: case BufferFormat.R8G8B8A8_UIntNormal: case BufferFormat.R8G8B8A8_UIntNormal_sRGB: case BufferFormat.B8G8R8A8_UIntNormal: case BufferFormat.B8G8R8X8_UIntNormal: case BufferFormat.B8G8R8A8: case BufferFormat.B8G8R8A8_UIntNormal_sRGB: case BufferFormat.B8G8R8X8: case BufferFormat.B8G8R8X8_UIntNormal_sRGB: for (int i = 0; i < size; i += 4) { if (src != dest) { pixel = *(srcPtr++); } else { pixel = *(destPtr); } r = ((pixel & 0xFF0000) >> 16); g = (pixel & 0x00FF00); b = ((pixel & 0x0000FF) << 16); a = ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) ? 0xFF000000 : pixel & 0xFF000000; *destPtr = r | g | b | a; destPtr++; } return; } if (src != dest) { DirectAccess.MemoryCopy(dest, src, size); } }
/// <summary> /// Function to copy (or update in-place) with bits swizzled to match another format. /// </summary> /// <param name="src">The pointer to the source data.</param> /// <param name="srcPitch">The pitch of the source data.</param> /// <param name="dest">The pointer to the destination data.</param> /// <param name="destPitch">The pitch of the destination data.</param> /// <param name="format">Format of the destination buffer.</param> /// <param name="bitFlags">Image bit conversion control flags.</param> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="format"/> parameter is Unknown.</exception> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="src"/> or the <paramref name="dest"/> parameter is NULL.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="srcPitch"/> or the <paramref name="destPitch"/> parameter is less than 0.</exception> /// <remarks>Use this method to copy a single scanline and swizzle the bits of an image and (optionally) set an opaque constant alpha value.</remarks> protected unsafe void SwizzleScanline(IntPtr src, int srcPitch, IntPtr dest, int destPitch, BufferFormat format, ImageBitFlags bitFlags) { SwizzleScanline(src.ToPointer(), srcPitch, dest.ToPointer(), destPitch, format, bitFlags); }
/// <summary> /// Function to expand a 16BPP scan line in an image to a 32BPP RGBA line. /// </summary> /// <param name="src">The pointer to the source data.</param> /// <param name="srcPitch">The pitch of the source data.</param> /// <param name="srcFormat">Format to convert from.</param> /// <param name="dest">The pointer to the destination data.</param> /// <param name="destPitch">The pitch of the destination data.</param> /// <param name="bitFlags">Image bit conversion control flags.</param> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="srcFormat" /> is not a 16 BPP format.</exception> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="src"/> or the <paramref name="dest"/> parameter is NULL.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="srcPitch"/> or the <paramref name="destPitch"/> parameter is less than 0.</exception> /// <remarks> /// Use this to expand a 16 BPP (B5G6R5 or B5G5R5A1 format) into a 32 BPP R8G8B8A8 (normalized unsigned integer) format. /// </remarks> protected unsafe void Expand16BPPScanline(void *src, int srcPitch, BufferFormat srcFormat, void *dest, int destPitch, ImageBitFlags bitFlags) { var srcPtr = (ushort *)src; var destPtr = (uint *)dest; if ((srcFormat != BufferFormat.B5G5R5A1_UIntNormal) && (srcFormat != BufferFormat.B5G6R5_UIntNormal)) { throw new ArgumentException(string.Format(Resources.GORGFX_IMAGE_NOT_16BPP, srcFormat), "srcFormat"); } if (src == null) { throw new ArgumentNullException("src"); } if (dest == null) { throw new ArgumentNullException("dest"); } for (int srcCount = 0, destCount = 0; ((srcCount < srcPitch) && (destCount < destPitch)); srcCount += 2, destCount += 4) { ushort srcPixel = *(srcPtr++); uint R = 0, G = 0, B = 0, A = 0; switch (srcFormat) { case BufferFormat.B5G6R5_UIntNormal: R = (uint)((srcPixel & 0xF800) >> 11); G = (uint)((srcPixel & 0x07E0) >> 5); B = (uint)(srcPixel & 0x001F); R = ((R << 3) | (R >> 2)); G = ((G << 2) | (G >> 4)) << 8; B = ((B << 3) | (B >> 2)) << 16; A = 0xFF000000; break; case BufferFormat.B5G5R5A1_UIntNormal: R = (uint)((srcPixel & 0x7C00) >> 10); G = (uint)((srcPixel & 0x03E0) >> 5); B = (uint)(srcPixel & 0x001F); R = ((R << 3) | (R >> 2)); G = ((G << 3) | (G >> 2)) << 8; B = ((B << 3) | (B >> 2)) << 16; A = ((bitFlags & ImageBitFlags.OpaqueAlpha) == ImageBitFlags.OpaqueAlpha) ? 0xFF000000 : (((srcPixel & 0x8000) != 0) ? 0xFF000000 : 0); break; } *(destPtr++) = R | G | B | A; } }
/// <summary> /// Function to expand a 16BPP line in an image to a 32BPP RGBA line. /// </summary> /// <param name="src">The pointer to the source data.</param> /// <param name="srcPitch">The pitch of the source data.</param> /// <param name="srcFormat">Format to convert from.</param> /// <param name="dest">The pointer to the destination data.</param> /// <param name="destPitch">The pitch of the destination data.</param> /// <param name="bitFlags">Image bit conversion control flags.</param> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="srcFormat"/> is not a 16 BPP format.</exception> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="src"/> or the <paramref name="dest"/> parameter is IntPtr.Zero.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="srcPitch"/> or the <paramref name="destPitch"/> parameter is less than 0.</exception> /// <remarks>Use this to expand a 16 BPP (B5G6R5 or B5G5R5A1 format) into a 32 BPP R8G8B8A8 (normalized unsigned integer) format. /// <para>This overload is for languages that don't support unsafe code (e.g. Visual Basic .NET).</para> /// </remarks> protected unsafe void Expand16BPPScanline(IntPtr src, int srcPitch, BufferFormat srcFormat, IntPtr dest, int destPitch, ImageBitFlags bitFlags) { Expand16BPPScanline(src.ToPointer(), srcPitch, srcFormat, dest.ToPointer(), destPitch, bitFlags); }