Пример #1
0
 internal void Insert(Argb color)
 {
     if (this.Bits > 0)
     {
         this.Array[this.Index(color)] = color;
     }
 }
Пример #2
0
        /// The palette (color-indexing) transform replaces pixels with indices into
        /// a palette that is stored before the image data. If the palette is
        /// sufficiently small, multiple indices are packed into a single pixel.
        internal static Image PaletteTransform(BitWriter b, Image image, Palette palette)
        {
            b.WriteBits(1, 1);
            b.WriteBits(3, 2);
            WritePalette(b, palette);

            int packSize =
                palette.Count <= 2 ? 8 :
                palette.Count <= 4 ? 4 :
                palette.Count <= 16 ? 2 : 1;

            int packedWidth = (image.Width + packSize - 1) / packSize;
            var palettized  = new Image(packedWidth, image.Height);

            for (int y = 0; y < image.Height; ++y)
            {
                for (int i = 0; i < packedWidth; ++i)
                {
                    int pack = 0;
                    for (int j = 0; j < packSize; ++j)
                    {
                        int x = i * packSize + j;
                        if (x >= image.Width)
                        {
                            break;
                        }
                        int colorIndex = palette.Indices[image[x, y]];
                        pack |= colorIndex << (j * (8 / packSize));
                    }
                    palettized[i, y] = new Argb(255, 0, (byte)pack, 0);
                }
            }

            return(palettized);
        }
Пример #3
0
 static Argb ClampAddSubtractHalf(Argb a, Argb b)
 {
     return(new Argb(
                Clamp(a.A + (a.A - b.A) / 2),
                Clamp(a.R + (a.R - b.R) / 2),
                Clamp(a.G + (a.G - b.G) / 2),
                Clamp(a.B + (a.B - b.B) / 2)));
 }
Пример #4
0
 static Argb ClampAddSubtractFull(Argb l, Argb t, Argb tl)
 {
     return(new Argb(
                Clamp(l.A + t.A - tl.A),
                Clamp(l.R + t.R - tl.R),
                Clamp(l.G + t.G - tl.G),
                Clamp(l.B + t.B - tl.B)));
 }
Пример #5
0
 static Argb Average2(Argb a, Argb b)
 {
     return(new Argb(
                (byte)((a.A + b.A) / 2),
                (byte)((a.R + b.R) / 2),
                (byte)((a.G + b.G) / 2),
                (byte)((a.B + b.B) / 2)));
 }
Пример #6
0
        internal static uint Hash(Argb argb)
        {
            uint x1 = argb.ToUInt();
            uint x2 = (x1 * 47491) ^ ~(x1 * 41227);
            uint x3 = x2 * (x2 << 3) ^ ~(x2 >> 5) ^ (x2 >> 13);
            uint x4 = (x3 * 20389) ^ ~(x3 * 28111);

            return(x4);
        }
Пример #7
0
 internal bool Lookup(Argb color, out int index)
 {
     if (this.Bits <= 0)
     {
         index = 0; return(false);
     }
     index = this.Index(color);
     return(this.Array[index] == color);
 }
Пример #8
0
        internal static uint Hash(Argb a1, Argb a2, Argb a3)
        {
            uint h1 = Hash(a1);
            uint h2 = Hash(a2);
            uint h3 = Hash(a3);
            uint x1 = h1 ^ (h2 * 32369) ^ ~(h3 * 39217);
            uint x2 = ~(h1 * 40483) ^ h2 ^ (h3 * 42943);
            uint x3 = (x1 << 3) ^ (x2 >> 7);

            return(x3);
        }
Пример #9
0
        static Argb Select(Argb l, Argb t, Argb tl)
        {
            int pA = l.A + t.A - tl.A;
            int pR = l.R + t.R - tl.R;
            int pG = l.G + t.G - tl.G;
            int pB = l.B + t.B - tl.B;

            int pL = Abs(pA - l.A) + Abs(pR - l.R) + Abs(pG - l.G) + Abs(pB - l.B);
            int pT = Abs(pA - t.A) + Abs(pR - t.R) + Abs(pG - t.G) + Abs(pB - t.B);

            return(pL < pT ? l : t);
        }
Пример #10
0
        /// The prediction transform predicts the values of pixels using their
        /// already decoded neighbors, storing only the difference between the
        /// predicted and actual value. There are 14 prediction modes and which mode
        /// is used is determined from an encoded subsample image.
        internal static Image PredictTransform(BitWriter b, Image image)
        {
            b.WriteBits(1, 1);
            b.WriteBits(0, 2);

            int tileBits      = 4;
            int tileSize      = 0;
            int blockedWidth  = 0;
            int blockedHeight = 0;

            while (tileBits < 2 + 8)
            {
                tileSize      = 1 << tileBits;
                blockedWidth  = (image.Width + tileSize - 1) / tileSize;
                blockedHeight = (image.Height + tileSize - 1) / tileSize;
                if (blockedWidth * blockedHeight < 2000)
                {
                    break;
                }
                ++tileBits;
            }

            b.WriteBits(tileBits - 2, 3);
            var blocks      = new Image(blockedWidth, blockedHeight);
            var residuals   = new Image(image.Width, image.Height);
            var accumHistos = Enumerable.Range(0, 4).Select(_ => new Histogram(256)).ToList();

            for (int y = 0; y < blockedHeight; ++y)
            {
                for (int x = 0; x < blockedWidth; ++x)
                {
                    int    bestPrediction = 0;
                    double bestEntropy    = PredictEntropy(image, tileBits, x, y, 0, accumHistos);
                    for (int i = 1; i < PREDICTIONS.Count; ++i)
                    {
                        double entropy = PredictEntropy(image, tileBits, x, y, i, accumHistos);
                        if (entropy < bestEntropy)
                        {
                            bestPrediction = i;
                            bestEntropy    = entropy;
                        }
                    }

                    blocks[x, y] = new Argb(255, 0, (byte)bestPrediction, 0);
                    PredictBlock(image, residuals, tileBits, x, y, bestPrediction, accumHistos);
                }
            }

            ImageData.WriteImageData(b, blocks, false);
            return(residuals);
        }
Пример #11
0
        /// Computes all the histograms from an image.
        static List <Histogram> ComputeHistograms(Image image,
                                                  Palette paletteOrNull, out bool hasAlpha)
        {
            var histos = Enumerable.Range(0, (int)HistogramIdx._COUNT)
                         .Select(_ => new Histogram(256)).ToList();

            Argb previous = new Argb(255, 0, 0, 0);

            hasAlpha = false;
            for (int i = 0; i < image.Pixels.Length; ++i)
            {
                Argb pixel = image.Pixels[i];

                if (pixel.A != 255)
                {
                    hasAlpha = true;
                }
                Argb delta = pixel - previous;
                previous = pixel;

                histos[(int)HistogramIdx.RED].Hit(pixel.R);
                histos[(int)HistogramIdx.GREEN].Hit(pixel.G);
                histos[(int)HistogramIdx.BLUE].Hit(pixel.B);
                histos[(int)HistogramIdx.ALPHA].Hit(pixel.A);

                histos[(int)HistogramIdx.DELTA_RED].Hit(delta.R);
                histos[(int)HistogramIdx.DELTA_GREEN].Hit(delta.G);
                histos[(int)HistogramIdx.DELTA_BLUE].Hit(delta.B);
                histos[(int)HistogramIdx.DELTA_ALPHA].Hit(delta.A);

                histos[(int)HistogramIdx.RED_MINUS_GREEN].Hit((byte)(pixel.R - pixel.G));
                histos[(int)HistogramIdx.BLUE_MINUS_GREEN].Hit((byte)(pixel.B - pixel.G));
                histos[(int)HistogramIdx.DELTA_RED_MINUS_DELTA_GREEN]
                .Hit((byte)(delta.R - delta.G));
                histos[(int)HistogramIdx.DELTA_BLUE_MINUS_DELTA_GREEN]
                .Hit((byte)(delta.B - delta.G));

                if (paletteOrNull != null)
                {
                    histos[(int)HistogramIdx.PALETTE].Hit(paletteOrNull.Indices[pixel]);
                }
            }
            return(histos);
        }
Пример #12
0
        /// Computes the predicted value for a single image pixel given the
        /// prediction mode.
        static Argb Predict(Image image, int x, int y, int prediction)
        {
            if (x == 0 && y == 0)
            {
                return(new Argb(255, 0, 0, 0));
            }
            else if (x == 0)
            {
                return(image[x, y - 1]);
            }
            else if (y == 0)
            {
                return(image[x - 1, y]);
            }

            int  i        = y * image.Width + x;
            Argb top      = image.Pixels[i - image.Width];
            Argb left     = image.Pixels[i - 1];
            Argb topLeft  = image.Pixels[i - image.Width - 1];
            Argb topRight = image.Pixels[i - image.Width + 1];

            return(PREDICTIONS[prediction](top, left, topLeft, topRight));
        }
Пример #13
0
 private int Index(Argb color)
 {
     return((int)((uint)(color.ToUInt() * 0x1e35a7bd) >> (32 - this.Bits)));
 }
Пример #14
0
            internal void AddChain(Argb a1, Argb a2, Argb a3, int index)
            {
                int i = (int)(Argb.Hash(a1, a2, a3) % this.Chains.Count());

                this.Chains[i] = new Chain(this.Chains[i], index);
            }
Пример #15
0
 internal Chain GetChain(Argb a1, Argb a2, Argb a3)
 {
     return(this.Chains[(int)(Argb.Hash(a1, a2, a3) % this.Chains.Count())]);
 }