Пример #1
0
        /// <summary>
        /// Process RAW!!!! bytes
        /// </summary>
        /// <param name="bytesOrig">RAW BYTES!!!!! NOT(!) Bitmap.Save() bytes!!!!</param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="gamma"></param>
        /// <param name="minQuality"></param>
        /// <param name="maxQuality"></param>
        /// <param name="speed">1: slowest-beast quality, 10: fastest and rough</param>
        /// <returns>PNG bytes!!!!!</returns>
        public static byte[] Compress(
            byte[] bytesOrig
            , int width
            , int height
            , double gamma   = 0.0d
            , int minQuality = 50
            , int maxQuality = 90
            , int speed      = 1
            )
        {
            IntPtr ptrAttr      = IntPtr.Zero;
            IntPtr ptrImgSrc    = IntPtr.Zero;
            IntPtr ptrImgResult = IntPtr.Zero;

            try {
                ptrAttr = imagequant.liq_attr_create();
                if (ptrAttr == IntPtr.Zero)
                {
                    Console.WriteLine("can't create attr");
                    return(null);
                }

                ptrImgSrc = imagequant.liq_image_create_rgba(ptrAttr, bytesOrig, width, height, gamma);
                if (ptrImgSrc == IntPtr.Zero)
                {
                    Console.WriteLine("can't create image");
                    return(null);
                }

                var errQual = imagequant.liq_set_quality(ptrAttr, minQuality, maxQuality);
                if (liq_error.LIQ_OK != errQual)
                {
                    Console.WriteLine("can't set quality");
                    return(null);
                }
                var errSpeed = imagequant.liq_set_speed(ptrAttr, speed);
                if (liq_error.LIQ_OK != errSpeed)
                {
                    Console.WriteLine("can't set speed");
                    return(null);
                }

                ptrImgResult = imagequant.liq_quantize_image(ptrAttr, ptrImgSrc);
                if (ptrImgResult == IntPtr.Zero)
                {
                    Console.WriteLine("can't quantize image");
                    return(null);
                }

                //var buffer_size = width * height;
                /// !!!!! 4x for ARGB
                //var buffer_size = width * height * 4;
                var buffer_size   = bytesOrig.Length;
                var bytesRemapped = new byte[buffer_size];

                var err = imagequant.liq_write_remapped_image(ptrImgResult, ptrImgSrc, bytesRemapped, (UIntPtr)buffer_size);
                if (err != liq_error.LIQ_OK)
                {
                    Console.WriteLine("remapping error");
                    return(null);
                }


                // APPLY PALETTE
                liq_palette liqPal = (liq_palette)Marshal.PtrToStructure(imagequant.liq_get_palette(ptrImgResult), typeof(liq_palette));

                byte[] bytesOut = null;
                using (Bitmap bmpOut = new Bitmap(width, height, PixelFormat.Format8bppIndexed)) {
                    ColorPalette pal = bmpOut.Palette;

                    //make sure that we only use as many entries as we have available
                    int liqPalCnt = liqPal.count;
                    int bmpPalCnt = pal.Entries.Length;
                    int palCnt    = liqPalCnt < bmpPalCnt ? liqPalCnt : bmpPalCnt;

                    for (int i = 0; i < palCnt; i++)
                    {
                        liq_color liqCol = liqPal.entries[i];
                        pal.Entries[i] = Color.FromArgb(liqCol.a, liqCol.r, liqCol.g, liqCol.b);
                    }

                    // if there are more bmp entries than liq entries, set to invisible
                    if (liqPalCnt < bmpPalCnt)
                    {
                        for (int i = liqPalCnt; i < bmpPalCnt; i++)
                        {
                            pal.Entries[i] = Color.FromArgb(0, 0, 0, 0);
                        }
                    }

                    //!!!!!
                    // Palette IS NOT A REFERENCE!!! HAS TO BE SET AGAIN!!!!!
                    bmpOut.Palette = pal;

                    BitmapData bmpData = bmpOut.LockBits(
                        new Rectangle(0, 0, bmpOut.Width, bmpOut.Height)
                        , ImageLockMode.WriteOnly
                        //, bmpOut.PixelFormat
                        //, PixelFormat.Format32bppArgb
                        //, PixelFormat.Format32bppRgb
                        //, PixelFormat.Format32bppPArgb
                        , PixelFormat.Format8bppIndexed
                        );
                    int bmpDataLength = bmpData.Stride * bmpData.Height;
                    Marshal.Copy(bytesRemapped, 0, bmpData.Scan0, bmpDataLength /* compressed.Length*/);
                    // !!!!! JUST FOR TESTING, write orignal data
                    //Marshal.Copy(orig, 0, bmpData.Scan0, bmpDataLength /* compressed.Length*/);
                    bmpOut.UnlockBits(bmpData);


                    using (MemoryStream msOut = new MemoryStream()) {
                        bmpOut.Save(msOut, ImageFormat.Png);
                        bytesOut = msOut.GetBuffer();
                    }
                }

                return(bytesOut);
            }
            catch (Exception ex) {
                Console.WriteLine($"unexpected error {ex}");
                return(null);
            }
            finally {
                imagequant.liq_image_destroy(ptrImgSrc);
                imagequant.liq_result_destroy(ptrImgResult);
                imagequant.liq_attr_destroy(ptrAttr);
            }
        }
Пример #2
0
 public static extern liq_error liq_image_add_fixed_color(liq_image_ptr img, liq_color color);