Example #1
0
        /// <summary>
        /// quantizes the specified image using a floyd-steinberg error diffusion dithering
        /// </summary>
        private unsafe void QuantizeFloydSteinberg(ColorBgra *pixels, int width, int height)
        {
            if (_octree == null)
            {
                return;
            }
            int       index = 0;
            ColorBgra col;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++, index++)
                {
                    col = _octree.Table[_octree.GetOctreeIndex(pixels[index])];
                    int er = (int)pixels[index].R - (int)col.R,
                        eg = (int)pixels[index].G - (int)col.G,
                        eb = (int)pixels[index].B - (int)col.B;
                    #region error matrix
                    for (int i = 0; i < 2; i++)
                    {
                        int iy = i + y;
                        if (iy >= 0 && iy < height)
                        {
                            for (int j = -1; j < 2; j++)
                            {
                                int jx = j + x;
                                if (jx >= 0 && jx < width)
                                {
                                    //load error dispersion from matrix
                                    int w = floydsteinbergmatrix[i][j + 1];
                                    if (w != 0)
                                    {
                                        int k = jx + iy * width;
                                        pixels[k].Red   += (er * w) / floydsteinbergsum;
                                        pixels[k].Green += (eg * w) / floydsteinbergsum;
                                        pixels[k].Blue  += (eb * w) / floydsteinbergsum;
                                    }
                                }
                            }
                        }
                        #endregion
                    }
                    pixels[index] = col;
                }
            }
        }
Example #2
0
        /// <summary>
        /// writes the image to the specified stream
        /// </summary>
        public override void Write(Stream str)
        {
            if (str == null)
            {
                throw new ArgumentNullException("str");
            }
            //write header
            BITMAPINFOHEADER header = new BITMAPINFOHEADER(
                _bitmap.Size,
                _bitsperpixel,
                this.SizeInBytes,
                (1 << _bitsperpixel) & 0xFF);

            header.Write(str);
            using (SimpleWriter wrt = new SimpleWriter(str))
            {
                #region write palette
                foreach (ColorBgra value in _octree.Table)
                {
                    wrt.Write(value.B);
                    wrt.Write(value.G);
                    wrt.Write(value.R);
                    wrt.Write((byte)0);                    //reserved
                }
                #endregion
                #region write indexed data
                //write bitmap
                BitmapData bd = _bitmap.LockBits(
                    new Rectangle(Point.Empty, _bitmap.Size),
                    ImageLockMode.ReadWrite,
                    PixelFormat.Format32bppArgb);
                ColorBgra *scan0 = (ColorBgra *)bd.Scan0;
                //write indexed data
                int indexmask = (1 << _bitsperpixel) - 1,
                    indexdata = 0;
                scan0 += bd.Width * bd.Height;
                for (int y = 0; y < bd.Height; y++)
                {
                    scan0 -= bd.Width;
                    int indexpos = 8 - _bitsperpixel;
                    indexdata = 0;
                    for (int x = 0; x < bd.Width; x++)
                    {
                        indexdata |=
                            (_octree.GetOctreeIndex(scan0[x]) & indexmask) << indexpos;
                        if (indexpos % 8 == 0)
                        {
                            indexpos += (16 - _bitsperpixel);
                        }
                        else
                        {
                            indexpos -= _bitsperpixel;
                        }
                        if (indexpos >= 32)
                        {
                            wrt.Write(indexdata);
                            indexdata = 0;
                            indexpos -= 32;
                        }
                    }
                    if (indexpos != (8 - _bitsperpixel))
                    {
                        wrt.Write(indexdata);
                    }
                }
                ANDMap.WriteToStream(bd, wrt);
                #endregion
                _bitmap.UnlockBits(bd);
            }
        }