///************************************************************************* /// Pixel packing/unpacking utilities ///************************************************************************* // ///<summary> // /// Pack a color value to memory // ///</summary> // ///<param name="color">The color</param> // ///<param name="format">Pixel format in which to write the color</param> // ///<param name="dest">Destination memory location</param> // public static void PackColor(System.Drawing.Color color, PixelFormat format, IntPtr dest) { // PackColor(color.r, color.g, color.b, color.a, format, dest); // } ///<summary> /// Pack a color value to memory ///</summary> ///<param name="r,g,b,a">The four color components, range 0x00 to 0xFF</param> ///<param name="format">Pixelformat in which to write the color</param> ///<param name="dest">Destination memory location</param> unsafe public void PackColor(uint r, uint g, uint b, uint a, PixelFormat format, byte *dest) { PixelFormatDescription des = PixelConverter.GetDescriptionFor(format); if ((des.flags & PixelFormatFlags.NativeEndian) != 0) { // Shortcut for integer formats packing uint value = (((Bitwise.FixedToFixed(r, 8, des.rbits) << des.rshift) & des.rmask) | ((Bitwise.FixedToFixed(g, 8, des.gbits) << des.gshift) & des.gmask) | ((Bitwise.FixedToFixed(b, 8, des.bbits) << des.bshift) & des.bmask) | ((Bitwise.FixedToFixed(a, 8, des.abits) << des.ashift) & des.amask)); // And write to memory Bitwise.IntWrite(dest, des.elemBytes, value); } else { // Convert to float PackColor((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f, format, dest); } }
// /** Unpack a color value from memory // @param color The color is returned here // @param pf Pixelformat in which to read the color // @param src Source memory location // */ // protected static void UnpackColor(ref System.Drawing.Color color, PixelFormat pf, IntPtr src) { // UnpackColor(color.r, color.g, color.b, color.a, pf, src); // } /** Unpack a color value from memory * @param r,g,b,a The color is returned here (as byte) * @param pf Pixelformat in which to read the color * @param src Source memory location * @remarks This function returns the color components in 8 bit precision, * this will lose precision when coming from A2R10G10B10 or floating * point formats. */ unsafe public static void UnpackColor(ref byte r, ref byte g, ref byte b, ref byte a, PixelFormat pf, byte *src) { PixelFormatDescription des = PixelConverter.GetDescriptionFor(pf); if ((des.flags & PixelFormatFlags.NativeEndian) != 0) { // Shortcut for integer formats unpacking uint value = Bitwise.IntRead(src, des.elemBytes); if ((des.flags & PixelFormatFlags.Luminance) != 0) { // Luminance format -- only rbits used r = g = b = (byte)Bitwise.FixedToFixed((value & des.rmask) >> des.rshift, des.rbits, 8); } else { r = (byte)Bitwise.FixedToFixed((value & des.rmask) >> des.rshift, des.rbits, 8); g = (byte)Bitwise.FixedToFixed((value & des.gmask) >> des.gshift, des.gbits, 8); b = (byte)Bitwise.FixedToFixed((value & des.bmask) >> des.bshift, des.bbits, 8); } if ((des.flags & PixelFormatFlags.HasAlpha) != 0) { a = (byte)Bitwise.FixedToFixed((value & des.amask) >> des.ashift, des.abits, 8); } else { a = 255; // No alpha, default a component to full } } else { // Do the operation with the more generic floating point float rr, gg, bb, aa; UnpackColor(out rr, out gg, out bb, out aa, pf, src); r = Bitwise.FloatToByteFixed(rr); g = Bitwise.FloatToByteFixed(gg); b = Bitwise.FloatToByteFixed(bb); a = Bitwise.FloatToByteFixed(aa); } }
///<summary> /// Pack a color value to memory ///</summary> ///<param name="r,g,b,a"> /// The four color components, range 0.0f to 1.0f /// (an exception to this case exists for floating point pixel /// formats, which don't clamp to 0.0f..1.0f) ///</param> ///<param name="format">Pixelformat in which to write the color</param> ///<param name="dest">Destination memory location</param> unsafe public static void PackColor(float r, float g, float b, float a, PixelFormat format, byte *dest) { // Catch-it-all here PixelFormatDescription des = PixelConverter.GetDescriptionFor(format); if ((des.flags & PixelFormatFlags.NativeEndian) != 0) { // Do the packing uint value = ((Bitwise.FloatToFixed(r, des.rbits) << des.rshift) & des.rmask) | ((Bitwise.FloatToFixed(g, des.gbits) << des.gshift) & des.gmask) | ((Bitwise.FloatToFixed(b, des.bbits) << des.bshift) & des.bmask) | ((Bitwise.FloatToFixed(a, des.abits) << des.ashift) & des.amask); // And write to memory Bitwise.IntWrite(dest, des.elemBytes, value); } else { switch (format) { case PixelFormat.FLOAT32_R: ((float *)dest)[0] = r; break; case PixelFormat.FLOAT32_RGB: ((float *)dest)[0] = r; ((float *)dest)[1] = g; ((float *)dest)[2] = b; break; case PixelFormat.FLOAT32_RGBA: ((float *)dest)[0] = r; ((float *)dest)[1] = g; ((float *)dest)[2] = b; ((float *)dest)[3] = a; break; case PixelFormat.FLOAT16_R: ((ushort *)dest)[0] = Bitwise.FloatToHalf(r); break; case PixelFormat.FLOAT16_RGB: ((ushort *)dest)[0] = Bitwise.FloatToHalf(r); ((ushort *)dest)[1] = Bitwise.FloatToHalf(g); ((ushort *)dest)[2] = Bitwise.FloatToHalf(b); break; case PixelFormat.FLOAT16_RGBA: ((ushort *)dest)[0] = Bitwise.FloatToHalf(r); ((ushort *)dest)[1] = Bitwise.FloatToHalf(g); ((ushort *)dest)[2] = Bitwise.FloatToHalf(b); ((ushort *)dest)[3] = Bitwise.FloatToHalf(a); break; // case PixelFormat.SHORT_RGBA: // ((ushort*)dest)[0] = Bitwise.FloatToFixed(r, 16); // ((ushort*)dest)[1] = Bitwise.FloatToFixed(g, 16); // ((ushort*)dest)[2] = Bitwise.FloatToFixed(b, 16); // ((ushort*)dest)[3] = Bitwise.FloatToFixed(a, 16); // break; // case PixelFormat.BYTE_LA: // ((byte*)dest)[0] = Bitwise.FloatToFixed(r, 8); // ((byte*)dest)[1] = Bitwise.FloatToFixed(a, 8); // break; default: // Not yet supported throw new Exception("Pack to " + format + " not implemented, in PixelUtil.PackColor"); } } }
unsafe public static void UnpackColor(out float r, out float g, out float b, out float a, PixelFormat pf, byte *src) { PixelFormatDescription des = PixelConverter.GetDescriptionFor(pf); if ((des.flags & PixelFormatFlags.NativeEndian) != 0) { // Shortcut for integer formats unpacking uint value = Bitwise.IntRead(src, des.elemBytes); if ((des.flags & PixelFormatFlags.Luminance) != 0) { // Luminance format -- only rbits used r = g = b = Bitwise.FixedToFloat( (value & des.rmask) >> des.rshift, des.rbits); } else { r = Bitwise.FixedToFloat((value & des.rmask) >> des.rshift, des.rbits); g = Bitwise.FixedToFloat((value & des.gmask) >> des.gshift, des.gbits); b = Bitwise.FixedToFloat((value & des.bmask) >> des.bshift, des.bbits); } if ((des.flags & PixelFormatFlags.HasAlpha) != 0) { a = Bitwise.FixedToFloat((value & des.amask) >> des.ashift, des.abits); } else { a = 1.0f; // No alpha, default a component to full } } else { switch (pf) { case PixelFormat.FLOAT32_R: r = g = b = ((float *)src)[0]; a = 1.0f; break; case PixelFormat.FLOAT32_RGB: r = ((float *)src)[0]; g = ((float *)src)[1]; b = ((float *)src)[2]; a = 1.0f; break; case PixelFormat.FLOAT32_RGBA: r = ((float *)src)[0]; g = ((float *)src)[1]; b = ((float *)src)[2]; a = ((float *)src)[3]; break; case PixelFormat.FLOAT16_R: r = g = b = Bitwise.HalfToFloat(((ushort *)src)[0]); a = 1.0f; break; case PixelFormat.FLOAT16_RGB: r = Bitwise.HalfToFloat(((ushort *)src)[0]); g = Bitwise.HalfToFloat(((ushort *)src)[1]); b = Bitwise.HalfToFloat(((ushort *)src)[2]); a = 1.0f; break; case PixelFormat.FLOAT16_RGBA: r = Bitwise.HalfToFloat(((ushort *)src)[0]); g = Bitwise.HalfToFloat(((ushort *)src)[1]); b = Bitwise.HalfToFloat(((ushort *)src)[2]); a = Bitwise.HalfToFloat(((ushort *)src)[3]); break; // case PixelFormat.SHORT_RGBA: // r = Bitwise.FixedToFloat(((ushort*)src)[0], 16); // g = Bitwise.FixedToFloat(((ushort*)src)[1], 16); // b = Bitwise.FixedToFloat(((ushort*)src)[2], 16); // a = Bitwise.FixedToFloat(((ushort*)src)[3], 16); // break; // case PixelFormat.BYTE_LA: // r = g = b = Bitwise.FixedToFloat(((byte*)src)[0], 8); // a = Bitwise.FixedToFloat(((byte*)src)[1], 8); // break; default: // Not yet supported throw new Exception("Unpack from " + pf + " not implemented, in PixelUtil.UnpackColor"); } } }