Пример #1
0
        public static RgbValue YuvToRgb(YuvValue yuv)
        {
            RgbValue rgb = new RgbValue();

            rgb.r = (byte)Clip(yuv.y + (91881 * yuv.v >> 16) - 179);
            rgb.g = (byte)Clip(yuv.y - ((22544 * yuv.u + 46793 * yuv.v) >> 16) + 135);
            rgb.b = (byte)Clip(yuv.y + (116129 * yuv.u >> 16) - 226);

            return(rgb);
        }
Пример #2
0
        // https://stackoverflow.com/questions/1737726/how-to-perform-rgb-yuv-conversion-in-c-c

        public static YuvValue RgbToYuv(RgbValue rgb)
        {
            YuvValue yuv = new YuvValue();

            yuv.y = Clip((19595 * rgb.r + 38470 * rgb.g + 7471 * rgb.b) >> 16);
            yuv.u = Clip((36962 * (rgb.b - Clip((19595 * rgb.r + 38470 * rgb.g + 7471 * rgb.b) >> 16)) >> 16) + 128);
            yuv.v = Clip((46727 * (rgb.r - Clip((19595 * rgb.r + 38470 * rgb.g + 7471 * rgb.b) >> 16)) >> 16) + 128);

            return(yuv);
        }
Пример #3
0
        /// Borrowed from Microprose: Magic The Gathering (1997)
        /// (can't identify if its borrowed from somewhere else :-))

        /// Buggy.

        public static YuvValue RgbToYuv2(RgbValue rgb)
        {
            YuvValue yuv = new YuvValue();

            yuv.y = (64 * rgb.g + 8 * rgb.r + 5 * rgb.b) / 28;
            yuv.u = (4 * rgb.b - yuv.y + 0x400) / 2;
            yuv.v = (32 * rgb.r - 8 * yuv.y + 0x1998) / 13;

            return(yuv);
        }
Пример #4
0
        public static RgbValue YuvToRgb2(YuvValue yuv)
        {
            RgbValue rgb = new RgbValue();

            int r = yuv.y + yuv.v + yuv.v / 2 + yuv.v / 8 - 0x333;
            int b = yuv.y + yuv.u * 2 - 0x400;
            int g = yuv.y * 2 - yuv.y / 4 - r / 2 - b / 4 - b / 16;

            rgb.r = (byte)Clip(r / 4);
            rgb.g = (byte)Clip(g / 4);
            rgb.b = (byte)Clip(b / 4);

            return(rgb);
        }
Пример #5
0
        public byte [] Compress(Image image, int iterations = 3)
        {
            int width  = image.Width;
            int height = image.Height;

            YuvValue [] yuvSurface = new YuvValue[width * height];

            /// RGB -> Yuv

            Bitmap bitmap = new Bitmap(image);

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    Color color = bitmap.GetPixel(x, y);

                    RgbValue rgb = new RgbValue();
                    rgb.r = color.R;
                    rgb.g = color.G;
                    rgb.b = color.B;

                    yuvSurface[y * width + x] = Yuv.RgbToYuv(rgb);
                }
            }

            /// Lerp U/V
            /// Seems doesnt't affect compression ratio much...

            //LerpUV(width, height, yuvSurface);

            /// Extract components and align on power of 2

            int alignedSize = UpperPowerOfTwo(Math.Max(width, height));

            Int32[] yvalues = new Int32[alignedSize * alignedSize];
            Int32[] uvalues = new Int32[alignedSize * alignedSize];
            Int32[] vvalues = new Int32[alignedSize * alignedSize];

            for (int y = 0; y < alignedSize; y++)
            {
                for (int x = 0; x < alignedSize; x++)
                {
                    if (y >= height || x >= width)
                    {
                        yvalues[y * alignedSize + x] = -1;
                        uvalues[y * alignedSize + x] = -1;
                        vvalues[y * alignedSize + x] = -1;
                    }
                    else
                    {
                        yvalues[y * alignedSize + x] = yuvSurface[y * width + x].y;
                        uvalues[y * alignedSize + x] = yuvSurface[y * width + x].u;
                        vvalues[y * alignedSize + x] = yuvSurface[y * width + x].v;
                    }
                }
            }

            /// Adjust border pixels by last color, to avoid edge glitching

            if ((width & 1) != 0)
            {
                for (int y = 0; y < height; y++)
                {
                    yvalues[y * alignedSize + width] = yvalues[y * alignedSize + width - 1];
                    uvalues[y * alignedSize + width] = uvalues[y * alignedSize + width - 1];
                    vvalues[y * alignedSize + width] = vvalues[y * alignedSize + width - 1];
                }
            }

            if ((height & 1) != 0)
            {
                for (int x = 0; x < width; x++)
                {
                    yvalues[height * alignedSize + x] = yvalues[(height - 1) * alignedSize + x];
                    uvalues[height * alignedSize + x] = uvalues[(height - 1) * alignedSize + x];
                    vvalues[height * alignedSize + x] = vvalues[(height - 1) * alignedSize + x];
                }
            }

            /// Wavelet

            Wavelet.FWT(yvalues, alignedSize, alignedSize, iterations);
            Wavelet.FWT(uvalues, alignedSize, alignedSize, iterations);
            Wavelet.FWT(vvalues, alignedSize, alignedSize, iterations);

            /// Gzip

            byte[] ycomp = Gzip.Compress(ToByteArray(yvalues));
            byte[] ucomp = Gzip.Compress(ToByteArray(uvalues));
            byte[] vcomp = Gzip.Compress(ToByteArray(vvalues));

            /// Header

            Int32[] header = new Int32[8];

            header[0] = alignedSize;
            header[1] = width;
            header[2] = height;
            header[3] = iterations;

            header[4] = ycomp.Length;
            header[5] = ucomp.Length;
            header[6] = vcomp.Length;
            header[7] = WayaSignature;

            /// Waya Image

            byte[] headerByte = ToByteArray(header);
            byte[] waveImage  = new byte[headerByte.Length + ycomp.Length + ucomp.Length + vcomp.Length];

            headerByte.CopyTo(waveImage, 0);
            ycomp.CopyTo(waveImage, headerByte.Length);
            ucomp.CopyTo(waveImage, headerByte.Length + ycomp.Length);
            vcomp.CopyTo(waveImage, headerByte.Length + ycomp.Length + ucomp.Length);

            return(waveImage);
        }
Пример #6
0
        public Image Decompress(byte [] data)
        {
            byte[] headerByte = new byte[8 * 4];

            Array.Copy(data, 0, headerByte, 0, headerByte.Length);
            Int32[] header = ToIntArray(headerByte);

            int alignedSize = header[0];
            int width       = header[1];
            int height      = header[2];
            int iterations  = header[3];

            int ycompSize = header[4];
            int ucompSize = header[5];
            int vcompSize = header[6];
            int signature = header[7];

            if (signature != WayaSignature)
            {
                return(null);
            }

            Bitmap bitmap = new Bitmap(width, height);

            YuvValue[] yuvSurface = new YuvValue[width * height];

            byte[] ycomp = new byte[ycompSize];
            byte[] ucomp = new byte[ucompSize];
            byte[] vcomp = new byte[vcompSize];

            Array.Copy(data, headerByte.Length, ycomp, 0, ycompSize);
            Array.Copy(data, headerByte.Length + ycompSize, ucomp, 0, ucompSize);
            Array.Copy(data, headerByte.Length + ycompSize + ucompSize, vcomp, 0, vcompSize);

            /// Gzip

            Int32[] yvalues = ToIntArray(Gzip.Decompress(ycomp));
            Int32[] uvalues = ToIntArray(Gzip.Decompress(ucomp));
            Int32[] vvalues = ToIntArray(Gzip.Decompress(vcomp));

            /// Wavelet

            Wavelet.IWT(yvalues, alignedSize, alignedSize, iterations);
            Wavelet.IWT(uvalues, alignedSize, alignedSize, iterations);
            Wavelet.IWT(vvalues, alignedSize, alignedSize, iterations);

            /// Extract components

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    yuvSurface[y * width + x] = new YuvValue();

                    yuvSurface[y * width + x].y = yvalues[y * alignedSize + x];
                    yuvSurface[y * width + x].u = uvalues[y * alignedSize + x];
                    yuvSurface[y * width + x].v = vvalues[y * alignedSize + x];
                }
            }

            /// Yuv -> RGB

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    RgbValue rgb   = Yuv.YuvToRgb(yuvSurface[y * width + x]);
                    Color    color = Color.FromArgb(rgb.r, rgb.g, rgb.b);
                    bitmap.SetPixel(x, y, color);
                }
            }

            return(bitmap);
        }