///*************************************************************************
        ///   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");
                }
            }
        }