Example #1
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);
        }
Example #2
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);
        }