public static bool PaletteHistogram(Bitmap bmp, out Bitmap bmpHist)
        {
            if (bmp.PixelFormat != PixelFormat.Format8bppIndexed)
            {
                bmpHist = null;
                return false;
            }

            int w = bmp.Width;
            int h = bmp.Height;

            int[] hist = new int[256];

            BmpProc8 bd = new BmpProc8(bmp);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                    hist[bd[x, y]]++;

            bd.Dispose();

            int max = -1;
            for (int i = 0; i < 256; i++)
                if (hist[i] > max) max = hist[i];

            for (int i = 0; i < 256; i++)
                hist[i] = hist[i] * 140 / max;

            bmpHist = new Bitmap(275, 180, PixelFormat.Format24bppRgb);

            Graphics g = Graphics.FromImage(bmpHist);
            g.Clear(Color.AntiqueWhite);

            Pen pen = new Pen(Color.Gray, 1F);

            for (int i = 0; i < 256; i++)
                g.DrawLine(pen, 10 + i, 150, 10 + i, 150 - hist[i]);

            pen.Color = Color.Black;

            g.DrawLine(pen, 8, 150, 8, 10);

            for (int i = 0; i <= 20; i++)
                if ((i % 2) == 0)
                    g.DrawLine(pen, 8, 150 - 7 * i, 4, 150 - 7 * i);
                else
                    g.DrawLine(pen, 8, 150 - 7 * i, 6, 150 - 7 * i);

            g.DrawLine(pen, 10, 150, 10 + 255, 150);

            for (int i = 0; i <= 51; i++)
                if ((i % 2) == 0)
                    g.DrawLine(pen, 10 + 5 * i, 150, 10 + 5 * i, 154);
                else
                    g.DrawLine(pen, 10 + 5 * i, 150, 10 + 5 * i, 152);

            ColorPalette pal = bmp.Palette;

            for (int i = 0; i < 256; i++)
            {
                pen.Color = pal.Entries[i];
                g.DrawLine(pen, 10 + i, 175, 10 + i, 158);
            }

            g.Dispose();

            return true;
        }
        public static bool Oscillo(ref Bitmap bmp, int width, bool bHorizontal,
                                                        Color dark, Color bright)
        {
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

            if ((width < 2) | (width > 10)) return false;

            int w = bmp.Width;
            int h = bmp.Height;

            int interval = width * 2 + 1;

            double sum;
            int count;

            Bitmap tmp = bmp.Clone() as Bitmap;
            GrayScale(ref tmp);
            HistoStretch(ref tmp);

            Pen pn = new Pen(Color.Black, 1.0f);

            Graphics g = Graphics.FromImage(bmp);
            g.Clear(Color.White);
            g.SmoothingMode = SmoothingMode.AntiAlias;

            BmpProc8 src = new BmpProc8(tmp);

            if (bHorizontal)
                for (int y = width; y < h + width; y += interval)
                    for (int x = 0; x < w; x++)
                    {
                        sum = 0; count = 0;
                        for (int iy = y - width; iy <= y + width; iy++)
                        {
                            if (iy > h - 1) break;
                            count++;
                            sum += 255 - src[x, iy];
                        }
                        sum = sum * width / (count * 255d);
                        sum = Math.Max(0.1d, sum);

                        g.DrawLine(pn, (float)x, (float)(y + sum),
                                                   (float)x, (float)(y - sum));
                    }
            else
                for (int x = width; x < w + width; x += interval)
                    for (int y = 0; y < h; y++)
                    {
                        sum = 0; count = 0;
                        for (int ix = x - width; ix <= x + width; ix++)
                        {
                            if (ix > w - 1) break;
                            count++;
                            sum += 255 - src[ix, y];
                        }
                        sum = sum * width / (count * 255d);
                        sum = Math.Max(0.1d, sum);

                        g.DrawLine(pn, (float)(x - sum), (float)y,
                                                  (float)(x + sum), (float)y);
                    }

            src.Dispose();
            g.Dispose();

            GrayScale(ref bmp);

            SetTwoColorGrayPalette(bmp, dark, bright);

            return true;
        }
        public static bool Invert8(ref Bitmap bmp)
        {
            if (bmp.PixelFormat != PixelFormat.Format8bppIndexed)
                return false;

            int w = bmp.Width;
            int h = bmp.Height;

            BmpProc8 src = new BmpProc8(bmp);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                    src[x, y] = (byte)(255 - src[x, y]);

            src.Dispose();

            return true;
        }
        public static bool HistoStretch(ref Bitmap graybmp, params double[] limit)
        {
            if (graybmp.PixelFormat != PixelFormat.Format8bppIndexed)
                return false;

            int w = graybmp.Width;
            int h = graybmp.Height;

            double stretchfactor = 1.00;

            int threshold = (int)(w * h * 0.015);

            if (limit.Length != 0) threshold = (int)(w * h * limit[0] / 100);

            int[] hist = new int[256];

            BmpProc8 src = new BmpProc8(graybmp);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                    hist[src[x, y]]++;

            int lt = 0;
            for (int i = 0; i < 256; i++)
            {
                lt += hist[i];
                if (lt > threshold)
                {
                    lt = i;
                    break;
                }
            }

            int ht = 0;
            for (int i = 255; i >= 0; i--)
            {
                ht += hist[i];
                if (ht > threshold)
                {
                    ht = i;
                    break;
                }
            }

            double originalrange = ht - lt + 1;
            double stretchedrange = originalrange + stretchfactor * (255 - originalrange);
            double scalefactor = stretchedrange / originalrange;

            for (int i = 0; i < 256; i++)
                hist[i] = AdjustByte(scalefactor * (i - lt));

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                    src[x, y] = (byte)hist[src[x, y]];

            src.Dispose();

            return true;
        }
        public static bool GrayScale8(ref Bitmap bmp8)
        {
            if (bmp8.PixelFormat != PixelFormat.Format8bppIndexed)
                return false;

            int w = bmp8.Width;
            int h = bmp8.Height;

            ColorPalette pal = bmp8.Palette;

            byte[] cl = new byte[pal.Entries.Length];

            Color c;

            for (int i = 0; i < pal.Entries.Length; i++)
            {
                c = pal.Entries[i];
                cl[i] = (byte)(c.R * 0.299 + c.G * 0.587 + c.B * 0.114);
            }

            BmpProc8 bd = new BmpProc8(bmp8);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                    bd[x, y] = cl[bd[x, y]];

            bd.Dispose();

            return SetGrayPalette(bmp8);
        }
        public static bool Diacross(ref Bitmap bmp, bool bFine,
                                            Color penColor, Color bkColor)
        {
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

            int w = bmp.Width;
            int h = bmp.Height;

            Graphics g;

            GrayScale(ref bmp);
            HistoStretch(ref bmp);

            Bitmap[] pattern = new Bitmap[4];
            TextureBrush[] tb = new TextureBrush[4];

            if (bFine)
            {
                Pen pn = new Pen(penColor, 1.8f);
                pn.Alignment = PenAlignment.Center;

                PointF[] start = { new PointF(0f, 0.5f), new PointF(0.5f, 0F),
                                            new PointF(0f, 2.5f), new PointF(2.5f, 0f) };
                PointF[] stop = { new PointF(4f, 0.5f), new PointF(0.5f, 4f),
                                            new PointF(4f, 2.5f), new PointF(2.5f, 4f) };

                float[] angle = { -37f, -53f };

                for (int i = 0; i < 4; i++)
                {
                    pattern[i] = new Bitmap(4, 4, PixelFormat.Format24bppRgb);
                    g = Graphics.FromImage(pattern[i]);
                    g.Clear(Color.White);
                    g.DrawLine(pn, start[i], stop[i]);
                    g.Dispose();

                    tb[i] = MakePatternBrush(pattern[i], angle[i % 2]);
                }

                pn.Dispose();
            }
            else
            {
                Pen pn = new Pen(penColor, 2.2f);
                pn.Alignment = PenAlignment.Center;

                Point[] start = { new Point(0, 1), new Point(1, 0),
                                        new Point(0, 4), new Point(4, 0) };
                Point[] stop = { new Point(9, 1), new Point(1, 9),
                                        new Point(9, 4), new Point(4, 9) };

                float[] angle = { -30f, -60f };

                for (int i = 0; i < 4; i++)
                {
                    pattern[i] = new Bitmap(6, 6, PixelFormat.Format32bppArgb);
                    g = Graphics.FromImage(pattern[i]);
                    g.Clear(Color.White);
                    g.DrawLine(pn, start[i], stop[i]);
                    g.Dispose();

                    tb[i] = MakePatternBrush(pattern[i], angle[i % 2]);
                }

                pn.Dispose();
            }

            Bitmap dst = new Bitmap(w, h, PixelFormat.Format24bppRgb);
            Graphics gdst = Graphics.FromImage(dst);
            gdst.Clear(bkColor);

            byte[] th = { 255, 191, 128, 64 };

            Bitmap tgt;

            BmpProc8 mod = new BmpProc8(bmp);

            for (int i = 0; i < 4; i++)
            {

                tgt = new Bitmap(w, h, PixelFormat.Format32bppArgb);

                g = Graphics.FromImage(tgt);
                g.FillRectangle(tb[i], 0, 0, w, h);
                g.Dispose();
                tb[i].Dispose();
                pattern[i].Dispose();

                BmpProc32 src = new BmpProc32(tgt);

                for (int y = 0; y < h; y++)
                    for (int x = 0; x < w; x++)
                    {
                        if (mod[x, y] < th[i])
                            src[x, y, eRGB.a] =
                                AdjustByte((double)(255 - src[x, y, eRGB.r]) *
                                    ((1d - ((double)mod[x, y] / (double)th[i]))));
                        else
                            src[x, y, eRGB.a] = 0;
                    }

                src.Dispose();

                gdst.DrawImageUnscaled(tgt, 0, 0);

                tgt.Dispose();
            }

            mod.Dispose();
            bmp.Dispose();
            gdst.Dispose();

            bmp = dst;
            return true;
        }