Beispiel #1
0
        protected override async Task <OutputFrame> TickInternal()
        {
            await _readWaitSemaphore.WaitAsync();

            var frame = _frame;

            _pixels = new OutputPixel[_videoSize.Width * _videoSize.Height];
            int i = 0;

            for (int y = 0; y < _videoSize.Height; y++)
            {
                for (int x = 0; x < _videoSize.Width; x++)
                {
                    int pixelIdx = i * 3;
                    var argb     = unchecked ((uint)(frame[pixelIdx] | frame[pixelIdx + 1] << 8 | frame[pixelIdx + 2] << 16 | 0xFF << 24));

                    _pixels[i] = new OutputPixel(x, y, argb);

                    i++;
                }
            }
            _writeWaitSemaphore.Release();

            var outputPixels = _pixels;

            return(new OutputFrame(0, 0, outputPixels, -1, false));
        }
        private unsafe void Decode_PALETTE_T8()
        {
            var Input = (byte *)_Input;

            if (Palette == null || PaletteType == GuPixelFormats.NONE)
            {
                throw (new Exception("Palette required!"));
            }
            OutputPixel[] PalettePixels;
            int           PaletteSize = 256;

            PalettePixels = new OutputPixel[PaletteSize];
            var Translate = new int[PaletteSize];

            fixed(OutputPixel *PalettePixelsPtr = PalettePixels)
            {
                Decode(PaletteType, Palette, PalettePixelsPtr, PalettePixels.Length, 1);
                //Decode(PaletteType, Palette, PalettePixelsPtr, PaletteCount);
            }

            for (int n = 0; n < PaletteSize; n++)
            {
                Translate[n] = ((PaletteStart + n) >> PaletteShift) & PaletteMask;
            }

            for (int y = 0, n = 0; y < Height; y++)
            {
                var InputRow = (byte *)&InputByte[y * StrideWidth];
                for (int x = 0; x < Width; x++, n++)
                {
                    byte Value = InputRow[x];
                    Output[n] = PalettePixels[Translate[(Value >> 0) & 0xFF]];
                }
            }
        }
        protected override Task <OutputFrame> TickInternal()
        {
            var maxOffsetX = CanvasSize.Width - boxSize.Width + 1;
            var maxOffsetY = CanvasSize.Height - boxSize.Height + 1;

            var color = (uint)random.Next() | 0xFF000000;
            //var color = random.Next(0, 100) > 50 ? Color.White : Color.Black;
            var offsetX = this.random.Next(0, maxOffsetX);
            var offsetY = this.random.Next(0, maxOffsetY);

            var toReturn = new OutputPixel[boxSize.Width * boxSize.Height];

            int i      = 0;
            var width  = boxSize.Width;
            var height = boxSize.Height;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    toReturn[i++] = new OutputPixel(x, y, color);
                }
            }

            return(Task.FromResult(new OutputFrame(offsetX, offsetY, toReturn)));
        }
Beispiel #4
0
        protected OutputPixel[] DrawImage(Bitmap image, Point offset, bool mirror = false)
        {
            var offsetX = offset.X;
            var offsetY = offset.Y;

            var canvasSize = this.CanvasSize;

            if (image.PixelFormat != PixelFormatToUse)
            {
                throw new ArgumentException($"image must be {PixelFormatToUse}");
            }

            var bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, PixelFormatToUse);
            var stride     = bitmapData.Stride;
            var dataLength = stride * bitmapData.Height;
            var bytes      = new byte[dataLength];

            Marshal.Copy(bitmapData.Scan0, bytes, 0, dataLength);
            image.UnlockBits(bitmapData);

            var width  = image.Width;
            var height = image.Height;

            var canvasWidth  = canvasSize.Width;
            var canvasHeight = canvasSize.Height;

            var toReturn = new OutputPixel[width * height];

            int i = 0;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int pixelIndex = ((mirror ? width - x - 1 : x) * BytesPerPixel + (y * stride));
                    var renderX    = x + offsetX;
                    var renderY    = y + offsetY;
                    if (renderX < 0 || renderY < 0 || renderX >= canvasWidth || renderY >= canvasHeight)
                    {
                        continue;
                    }

                    byte a = bytes[pixelIndex + 3];
                    byte r = bytes[pixelIndex + 2];
                    byte g = bytes[pixelIndex + 1];
                    byte b = bytes[pixelIndex];

                    uint argb = unchecked ((uint)(a << 24 | r << 16 | g << 8 | b));
                    toReturn[i].X     = (x + offsetX);
                    toReturn[i].Y     = (y + offsetY);
                    toReturn[i].Color = argb;
                    i++;
                }
            }

            return(toReturn);
        }
Beispiel #5
0
        private static ushort Encode_RGBA_5650_Pixel(OutputPixel pixel)
        {
            uint Out = 0;

            BitUtils.InsertScaled(ref Out, 0, 5, pixel.R, 255);
            BitUtils.InsertScaled(ref Out, 5, 6, pixel.G, 255);
            BitUtils.InsertScaled(ref Out, 11, 5, pixel.B, 255);
            return((ushort)Out);
        }
Beispiel #6
0
        private static ushort Encode_RGBA_4444_Pixel(OutputPixel pixel)
        {
            uint Out = 0;

            BitUtils.InsertScaled(ref Out, 0, 4, pixel.R, 255);
            BitUtils.InsertScaled(ref Out, 4, 4, pixel.G, 255);
            BitUtils.InsertScaled(ref Out, 8, 4, pixel.B, 255);
            BitUtils.InsertScaled(ref Out, 12, 4, pixel.A, 255);
            return((ushort)Out);
        }
        public static ushort Encode_RGBA_5551_Pixel(OutputPixel pixel)
        {
            uint Out = 0;

            BitUtils.InsertScaled(ref Out, 0, 5, pixel.R, 255);
            BitUtils.InsertScaled(ref Out, 5, 5, pixel.G, 255);
            BitUtils.InsertScaled(ref Out, 10, 5, pixel.B, 255);
            BitUtils.InsertScaled(ref Out, 15, 1, pixel.A, 255);
            return((ushort)Out);
        }
Beispiel #8
0
        protected void _SetVertexInfoColor(OutputPixel color)
        {
            VertexInfo->Color.X = color.R / 255.0f;
            VertexInfo->Color.Y = color.G / 255.0f;
            VertexInfo->Color.Z = color.B / 255.0f;
#if true
            VertexInfo->Color.W = color.A / 255.0f;
#else
            VertexInfo->Color.W = 1.0f;
#endif
        }
Beispiel #9
0
 public void SetPixel(int X, int Y, OutputPixel Color)
 {
     if (!IsValidPosition(X, Y)) return;
     //var Position = PixelFormatDecoder.GetPixelsSize(GuPixelFormat, Y * Width + X);
     var Position = GetOffset(X, Y);
     uint Value = this.ColorFormat.Encode(Color);
     switch (this.BitsPerPixel)
     {
         case 16: *(ushort*)(Address + Position) = (ushort)Value; break;
         case 32: *(uint*)(Address + Position) = (uint)Value; break;
         default: throw(new NotImplementedException());
     }
 }
Beispiel #10
0
        public OutputPixel[] GetPixels()
        {
            var o      = new OutputPixel[Width * Height];
            var length = Width * Height;
            var n      = 0;

            for (var y = 0; y < Height; y++)
            {
                for (var x = 0; x < Width; x++)
                {
                    o[n++] = this.GetPixel(x, y);
                }
            }
            return(o);
        }
Beispiel #11
0
        private void Decode_COMPRESSED_DXT1()
        {
            var colors = new OutputPixel[4];

            for (int y = 0, ni = 0; y < _height; y += 4)
            {
                for (int x = 0; x < _width; x += 4, ni++)
                {
                    var block = ((Dxt1Block *)_inputByte)[ni];

                    colors[0] = Decode_RGBA_5650_Pixel(block.Color0)
                                .Transform((r, g, b, a) => OutputPixel.FromRgba(b, g, r, a));
                    colors[1] = Decode_RGBA_5650_Pixel(block.Color1)
                                .Transform((r, g, b, a) => OutputPixel.FromRgba(b, g, r, a));

                    if (block.Color0 > block.Color1)
                    {
                        colors[2] = OutputPixel.OperationPerComponent(colors[0], colors[1],
                                                                      (a, b) => (byte)(a * 2 / 3 + b * 1 / 3));
                        colors[3] = OutputPixel.OperationPerComponent(colors[0], colors[1],
                                                                      (a, b) => (byte)(a * 1 / 3 + b * 2 / 3));
                    }
                    else
                    {
                        colors[2] = OutputPixel.OperationPerComponent(colors[0], colors[1],
                                                                      (a, b) => (byte)(a * 1 / 2 + b * 1 / 2));
                        colors[3] = OutputPixel.FromRgba(0, 0, 0, 0);
                    }

                    var no = 0;
                    for (var y2 = 0; y2 < 4; y2++)
                    {
                        for (var x2 = 0; x2 < 4; x2++, no++)
                        {
                            var color = (block.ColorLookup >> (2 * no)) & 0x3;

                            var rx = x + x2;
                            var ry = y + y2;
                            var n  = ry * _width + rx;

                            _output[n] = colors[color];
                        }
                    }
                }
            }
        }
Beispiel #12
0
        private unsafe void Decode_RGBA_8888()
        {
            var Input = (uint *)_Input;

            for (int y = 0, n = 0; y < Height; y++)
            {
                var InputRow = (uint *)&InputByte[y * StrideWidth];
                for (int x = 0; x < Width; x++, n++)
                {
                    OutputPixel Value = *((OutputPixel *)&InputRow[x]);
                    Output[n].R = Value.R;
                    Output[n].G = Value.G;
                    Output[n].B = Value.B;
                    Output[n].A = Value.A;
                }
            }
        }
Beispiel #13
0
        private void Decode_PALETTE_T8()
        {
            var input = (byte *)_input;

            var paletteSize   = 256;
            var palettePixels = new OutputPixel[paletteSize];
            var translate     = new int[paletteSize];

            if (_palette == null || _paletteType == GuPixelFormats.None)
            {
                var n = 0;
                for (var y = 0; y < _height; y++)
                {
                    var inputRow = &_inputByte[y * _strideWidth];
                    for (var x = 0; x < _width; x++, n++)
                    {
                        // @TODO: This is probably wrong!
                        _output[n] = palettePixels[inputRow[x]];
                    }
                }
            }
            else
            {
                fixed(OutputPixel *palettePixelsPtr = palettePixels)
                {
                    Decode(_paletteType, _palette, palettePixelsPtr, palettePixels.Length, 1);
                    //Decode(PaletteType, Palette, PalettePixelsPtr, PaletteCount);
                }

                for (int n = 0; n < paletteSize; n++)
                {
                    translate[n] = ((_paletteStart + n) >> _paletteShift) & _paletteMask;
                }

                for (int y = 0, n = 0; y < _height; y++)
                {
                    var inputRow = &_inputByte[y * _strideWidth];
                    for (var x = 0; x < _width; x++, n++)
                    {
                        var value = inputRow[x];
                        _output[n] = palettePixels[translate[(value >> 0) & 0xFF]];
                    }
                }
            }
        }
            public void SetPixel(int X, int Y, OutputPixel Color)
            {
                if (X < 0 || Y < 0)
                {
                    return;
                }
                if (X >= Width || Y >= Height)
                {
                    return;
                }
                var Offset       = GetOffset(X, Y);
                var WriteAddress = (byte *)(Address + Offset);

                //byte C = (byte)((Color.R + Color.G + Color.B) * 15 / 3 / 255);
                byte C = (byte)(Color.R * 15 / 255);

                switch (FontPixelFormat)
                {
                case sceLibFont.FontPixelFormat.PSP_FONT_PIXELFORMAT_4:
                    *WriteAddress = (byte)((*WriteAddress & 0xF0) | ((C & 0xF) << 0));
                    break;

                case sceLibFont.FontPixelFormat.PSP_FONT_PIXELFORMAT_4_REV:
                    *WriteAddress = (byte)((*WriteAddress & 0x0F) | ((C & 0xF) << 4));
                    break;

                case sceLibFont.FontPixelFormat.PSP_FONT_PIXELFORMAT_8:
                    *WriteAddress = Color.A;
                    break;

                case sceLibFont.FontPixelFormat.PSP_FONT_PIXELFORMAT_24:
                    *(WriteAddress + 0) = Color.R;
                    *(WriteAddress + 1) = Color.G;
                    *(WriteAddress + 2) = Color.B;
                    break;

                case sceLibFont.FontPixelFormat.PSP_FONT_PIXELFORMAT_32:
                    *(WriteAddress + 0) = Color.R;
                    *(WriteAddress + 1) = Color.G;
                    *(WriteAddress + 2) = Color.B;
                    *(WriteAddress + 3) = Color.A;
                    break;
                }
            }
Beispiel #15
0
        /*
        public static uint EncodePixel(GuPixelFormats PixelFormat, OutputPixel Color)
        {
            return ColorFormatFromPixelFormat(PixelFormat).Encode(Color.R, Color.G, Color.B, Color.A);
        }

        public static OutputPixel DecodePixel(GuPixelFormats PixelFormat, uint Value)
        {
            throw new NotImplementedException();
        }
        */
        public static void Decode(GuPixelFormats PixelFormat, void* Input, OutputPixel* Output, int Width, int Height, void* Palette = null, GuPixelFormats PaletteType = GuPixelFormats.NONE, int PaletteCount = 0, int PaletteStart = 0, int PaletteShift = 0, int PaletteMask = 0xFF, int StrideWidth = -1, bool IgnoreAlpha = false)
        {
            if (StrideWidth == -1) StrideWidth = GetPixelsSize(PixelFormat, Width);
            var PixelFormatInt = (int)PixelFormat;
            var PixelFormatDecoder = new PixelFormatDecoder()
            {
                _Input = Input,
                InputByte = (byte *)Input,
                InputShort = (ushort*)Input,
                InputInt = (uint*)Input,
                Output = Output,
                StrideWidth = StrideWidth,
                Width = Width,
                Height = Height,
                Palette = Palette,
                PaletteType = PaletteType,
                PaletteCount = PaletteCount,
                PaletteStart = PaletteStart,
                PaletteShift = PaletteShift,
                PaletteMask = PaletteMask,
            };
            //Console.WriteLine(PixelFormat);
            switch (PixelFormat)
            {
                case GuPixelFormats.RGBA_5650: PixelFormatDecoder.Decode_RGBA_5650(); break;
                case GuPixelFormats.RGBA_5551: PixelFormatDecoder.Decode_RGBA_5551(); break;
                case GuPixelFormats.RGBA_4444: PixelFormatDecoder.Decode_RGBA_4444(); break;
                case GuPixelFormats.RGBA_8888: PixelFormatDecoder.Decode_RGBA_8888(); break;
                case GuPixelFormats.PALETTE_T4: PixelFormatDecoder.Decode_PALETTE_T4(); break;
                case GuPixelFormats.PALETTE_T8: PixelFormatDecoder.Decode_PALETTE_T8(); break;
                case GuPixelFormats.PALETTE_T16: PixelFormatDecoder.Decode_PALETTE_T16(); break;
                case GuPixelFormats.PALETTE_T32: PixelFormatDecoder.Decode_PALETTE_T32(); break;
                case GuPixelFormats.COMPRESSED_DXT1: PixelFormatDecoder.Decode_COMPRESSED_DXT1(); break;
                case GuPixelFormats.COMPRESSED_DXT3: PixelFormatDecoder.Decode_COMPRESSED_DXT3(); break;
                case GuPixelFormats.COMPRESSED_DXT5: PixelFormatDecoder.Decode_COMPRESSED_DXT5(); break;
                default: throw(new InvalidOperationException());
            }
            if (IgnoreAlpha)
            {
                for (int y = 0, n = 0; y < Height; y++) for (int x = 0; x < Width; x++, n++) Output[n].A = 0xFF;
            }
            //DecoderCallbackTable[PixelFormatInt](Input, Output, PixelCount, Width, Palette, PaletteType, PaletteCount, PaletteStart, PaletteShift, PaletteMask);
        }
        protected override Task <OutputFrame> TickInternal()
        {
            var height = CanvasSize.Height;
            var width  = CanvasSize.Width;
            var color  = unchecked ((uint)Color.Black.ToArgb());

            var toReturn = new OutputPixel[width * height];
            var i        = 0;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    toReturn[i++] = new OutputPixel(x, y, color);
                }
            }

            return(Task.FromResult(new OutputFrame(0, 0, toReturn, 0, true)));
        }
Beispiel #17
0
        /// <summary>
        /// DXT2 and DXT3 (collectively also known as Block Compression 2 or BC2) converts 16 input pixels
        /// (corresponding to a 4x4 pixel block) into 128 bits of output, consisting of 64 bits of alpha channel data
        /// (4 bits for each pixel) followed by 64 bits of color data, encoded the same way as DXT1 (with the exception
        /// that the 4 color version of the DXT1 algorithm is always used instead of deciding which version to use based
        /// on the relative values of  and ). In DXT2, the color data is interpreted as being premultiplied by alpha, in
        /// DXT3 it is interpreted as not having been premultiplied by alpha. Typically DXT2/3 are well suited to images
        /// with sharp alpha transitions, between translucent and opaque areas.
        /// </summary>
        private void Decode_COMPRESSED_DXT3()
        {
            var colors = new OutputPixel[4];

            var ni = 0;

            for (var y = 0; y < _height; y += 4)
            {
                for (var x = 0; x < _width; x += 4, ni++)
                {
                    var block = ((Dxt3Block *)_inputByte)[ni];
                    colors[0] = Decode_RGBA_5650_Pixel(block.Color0)
                                .Transform((r, g, b, a) => OutputPixel.FromRgba(b, g, r, a));
                    colors[1] = Decode_RGBA_5650_Pixel(block.Color1)
                                .Transform((r, g, b, a) => OutputPixel.FromRgba(b, g, r, a));
                    colors[2] = OutputPixel.OperationPerComponent(colors[0], colors[1],
                                                                  (a, b) => (byte)(((a * 2) / 3) + ((b * 1) / 3)));
                    colors[3] = OutputPixel.OperationPerComponent(colors[0], colors[1],
                                                                  (a, b) => (byte)(((a * 1) / 3) + ((b * 2) / 3)));

                    var no = 0;
                    for (var y2 = 0; y2 < 4; y2++)
                    {
                        for (var x2 = 0; x2 < 4; x2++, no++)
                        {
                            var alpha = (block.Alpha >> (4 * no)) & 0xF;
                            var color = (block.ColorLookup >> (2 * no)) & 0x3;

                            var rx = (x + x2);
                            var ry = (y + y2);
                            var n  = ry * _width + rx;

                            _output[n]   = colors[color];
                            _output[n].A = (byte)((alpha * 0xFF) / 0xF);
                        }
                    }
                }
            }
        }
Beispiel #18
0
        public void SetPixel(int x, int y, OutputPixel color)
        {
            if (!IsValidPosition(x, y))
            {
                return;
            }
            //var Position = PixelFormatDecoder.GetPixelsSize(GuPixelFormat, Y * Width + X);
            var position = GetOffset(x, y);
            var value    = ColorFormat.Encode(color);

            switch (BitsPerPixel)
            {
            case 16:
                *(ushort *)(Address + position) = (ushort)value;
                break;

            case 32:
                *(uint *)(Address + position) = value;
                break;

            default: throw(new NotImplementedException());
            }
        }
Beispiel #19
0
        private bool ColorsEqual(OutputPixel oldPixel, OutputPixel newPixel)
        {
            const int threshold = 10;

            var c1 = oldPixel.Color;
            var c2 = newPixel.Color;

            if (c1 == c2)
            {
                return(true);
            }

            var diff = (long)(c1 & 0xFF) - (c2 & 0xFF);

            if (diff > threshold || diff < -threshold)
            {
                return(false);
            }
            c1 >>= 8;
            c2 >>= 8;

            diff = (long)(c1 & 0xFF) - (c2 & 0xFF);
            if (diff > threshold || diff < -threshold)
            {
                return(false);
            }
            c1 >>= 8;
            c2 >>= 8;

            diff = (long)(c1 & 0xFF) - (c2 & 0xFF);
            if (diff > threshold || diff < -threshold)
            {
                return(false);
            }

            return(true);
        }
Beispiel #20
0
        private void Decode_PALETTE_T4()
        {
            if (_palette == null || _paletteType == GuPixelFormats.None)
            {
                Console.WriteLine("Palette required!");
                return;
            }

            const int paletteSize   = 256;
            var       palettePixels = new OutputPixel[paletteSize];
            var       translate     = new int[paletteSize];

            fixed(OutputPixel *palettePixelsPtr = palettePixels)
            {
                Decode(_paletteType, _palette, palettePixelsPtr, palettePixels.Length, 1);
                //Decode(PaletteType, Palette, PalettePixelsPtr, PaletteCount);
            }

            //Console.WriteLine(PalettePixels.Length);
            for (var n = 0; n < 16; n++)
            {
                translate[n] = ((_paletteStart + n) >> _paletteShift) & _paletteMask;
                //Console.WriteLine(PalettePixels[Translate[n]]);
            }

            for (int y = 0, n = 0; y < _height; y++)
            {
                var inputRow = &_inputByte[y * _strideWidth];
                for (var x = 0; x < _width / 2; x++, n++)
                {
                    var value = inputRow[x];
                    _output[n * 2 + 0] = palettePixels[translate[(value >> 0) & 0xF]];
                    _output[n * 2 + 1] = palettePixels[translate[(value >> 4) & 0xF]];
                }
            }
        }
Beispiel #21
0
 public static void Encode(GuPixelFormats GuPixelFormat, OutputPixel* Input, byte* _Output, int Count)
 {
     switch (GuPixelFormat)
     {
         case GuPixelFormats.RGBA_8888: { var Output = (uint*)_Output; for (int n = 0; n < Count; n++) *Output++ = Encode_RGBA_8888_Pixel(*Input++); } break;
         case GuPixelFormats.RGBA_5551: { var Output = (ushort*)_Output; for (int n = 0; n < Count; n++) *Output++ = Encode_RGBA_5551_Pixel(*Input++); } break;
         case GuPixelFormats.RGBA_5650: { var Output = (ushort*)_Output; for (int n = 0; n < Count; n++) *Output++ = Encode_RGBA_5650_Pixel(*Input++); } break;
         case GuPixelFormats.RGBA_4444: { var Output = (ushort*)_Output; for (int n = 0; n < Count; n++) *Output++ = Encode_RGBA_4444_Pixel(*Input++); } break;
         default:
             throw(new NotImplementedException("Not implemented " + GuPixelFormat));
     }
 }
Beispiel #22
0
        public static void Encode(GuPixelFormats GuPixelFormat, OutputPixel* Input, byte* Output, int BufferWidth, int Width, int Height)
        {
            var IncOut = GetPixelsSize(GuPixelFormat, BufferWidth);

            for (int y = 0; y < Height; y++)
            {
                Encode(GuPixelFormat, Input, Output, Width);
                Input += Width;
                Output += IncOut;
            }
        }
Beispiel #23
0
        private void Decode_COMPRESSED_DXT5()
        {
            //Console.Error.WriteLine("Not Implemented: Decode_COMPRESSED_DXT5");
            //throw new NotImplementedException();

            //_Decode_Unimplemented();

            var colors = new OutputPixel[4];

            var ni = 0;

            for (var y = 0; y < _height; y += 4)
            {
                for (var x = 0; x < _width; x += 4, ni++)
                {
                    var block = ((Dxt5Block *)_inputByte)[ni];
                    colors[0] = Decode_RGBA_5650_Pixel(block.Color0)
                                .Transform((r, g, b, a) => OutputPixel.FromRgba(b, g, r, a));
                    colors[1] = Decode_RGBA_5650_Pixel(block.Color1)
                                .Transform((r, g, b, a) => OutputPixel.FromRgba(b, g, r, a));
                    colors[2] = OutputPixel.OperationPerComponent(colors[0], colors[1],
                                                                  (a, b) => (byte)(a * 2 / 3 + b * 1 / 3));
                    colors[3] = OutputPixel.OperationPerComponent(colors[0], colors[1],
                                                                  (a, b) => (byte)(a * 1 / 3 + b * 2 / 3));

                    // Create Alpha Lookup
                    var alphaLookup = new byte[8];
                    var alphas      = (ushort)(block.Alpha >> 48);
                    var alpha0      = (byte)((alphas >> 0) & 0xFF);
                    var alpha1      = (byte)((alphas >> 8) & 0xFF);

                    alphaLookup[0] = alpha0;
                    alphaLookup[1] = alpha1;
                    if (alpha0 > alpha1)
                    {
                        alphaLookup[2] = (byte)((6 * alpha0 + alpha1) / 7);
                        alphaLookup[3] = (byte)((5 * alpha0 + 2 * alpha1) / 7);
                        alphaLookup[4] = (byte)((4 * alpha0 + 3 * alpha1) / 7);
                        alphaLookup[5] = (byte)((3 * alpha0 + 4 * alpha1) / 7);
                        alphaLookup[6] = (byte)((2 * alpha0 + 5 * alpha1) / 7);
                        alphaLookup[7] = (byte)((alpha0 + 6 * alpha1) / 7);
                    }
                    else
                    {
                        alphaLookup[2] = (byte)((4 * alpha0 + alpha1) / 5);
                        alphaLookup[3] = (byte)((3 * alpha0 + 2 * alpha1) / 5);
                        alphaLookup[4] = (byte)((2 * alpha0 + 3 * alpha1) / 5);
                        alphaLookup[5] = (byte)((alpha0 + 4 * alpha1) / 5);
                        alphaLookup[6] = (byte)0x00;
                        alphaLookup[7] = (byte)0xFF;
                    }

                    var no = 0;
                    for (var y2 = 0; y2 < 4; y2++)
                    {
                        for (var x2 = 0; x2 < 4; x2++, no++)
                        {
                            var alpha = alphaLookup[(block.Alpha >> (3 * no)) & 0x7];
                            var color = (block.ColorLookup >> (2 * no)) & 0x3;

                            var rx = x + x2;
                            var ry = y + y2;
                            var n  = ry * _width + rx;

                            _output[n]   = colors[color];
                            _output[n].A = alpha;
                        }
                    }
                }
            }
        }
Beispiel #24
0
 public static uint Encode(this ColorFormat colorFormat, OutputPixel outputPixel)
 {
     return(colorFormat.Encode(outputPixel.R, outputPixel.G, outputPixel.B, outputPixel.A));
 }
Beispiel #25
0
 public static unsafe uint Encode_RGBA_8888_Pixel(OutputPixel Pixel)
 {
     return *(uint *)&Pixel;
 }
Beispiel #26
0
 private static uint Encode_RGBA_8888_Pixel(OutputPixel pixel) => *(uint *)&pixel;
 public static uint Encode(this ColorFormat ColorFormat, OutputPixel OutputPixel)
 {
     return ColorFormat.Encode(OutputPixel.R, OutputPixel.G, OutputPixel.B, OutputPixel.A);
 }
Beispiel #28
0
        static OutputPixel[] CreateContributor(int inputWidth, int leftIn, int rightIn, int outputWidth, float filterRadius, Func <float, float> calcWeight)
        {
            var contributor = new OutputPixel[outputWidth];

            float scale       = (float)outputWidth / (rightIn - leftIn);
            float factor      = scale < 1 ? scale : 1;
            float sourceWidth = filterRadius / factor;
            int   cbbStride   = (int)Math.Ceiling(2 * sourceWidth) + 1;

            for (int i = 0; i < outputWidth; ++i)
            {
                var o = new OutputPixel();
                o.P = new InputPixel[cbbStride];

                if (filterRadius > 0)
                {
                    double sum    = 0;
                    int    n      = 0;
                    float  center = leftIn + (i + 0.5f) / scale;
                    int    left   = (int)Math.Floor(center - sourceWidth);
                    int    right  = left + cbbStride - 1;
                    for (int j = left; j <= right; ++j)
                    {
                        float weight = calcWeight((center - j - 0.5f) * factor);

                        o.P[n].Pixel = j;

                        // reflection
                        if (o.P[n].Pixel < 0)
                        {
                            o.P[n].Pixel = Math.Min(-o.P[n].Pixel, inputWidth);
                        }
                        if (o.P[n].Pixel >= inputWidth)
                        {
                            o.P[n].Pixel = Math.Max(2 * inputWidth - o.P[n].Pixel - 2, 0);
                        }

                        o.P[n].Weight = weight;
                        ++n;
                        sum       += weight;
                        o.MinPixel = left;
                        o.MaxPixel = right;
                    }

                    o.N         = n;
                    o.Normalize = (float)(1.0 / sum);
                }
                else
                {
                    // nearest neighbor case
                    o.MinPixel = leftIn + (int)((i + 0.5f) / scale);
                    o.MaxPixel = o.MinPixel;
                    o.P        = new InputPixel[] { new InputPixel {
                                                        Pixel = o.MinPixel, Weight = calcWeight(0)
                                                    } };
                    o.N         = 1;
                    o.Normalize = 1;
                }

                contributor[i] = o;
            }
            return(contributor);
        }
 public static uint Encode_RGBA_8888_Pixel(OutputPixel pixel)
 {
     return(*(uint *)&pixel);
 }
Beispiel #30
0
 public static unsafe ushort Encode_RGBA_5650_Pixel(OutputPixel Pixel)
 {
     uint Out = 0;
     BitUtils.InsertScaled(ref Out, 0, 5, Pixel.R, 255);
     BitUtils.InsertScaled(ref Out, 5, 6, Pixel.G, 255);
     BitUtils.InsertScaled(ref Out, 11, 5, Pixel.B, 255);
     return (ushort)Out;
 }
Beispiel #31
0
        private unsafe void Decode_PALETTE_T8()
        {
            var Input = (byte*)_Input;

            int PaletteSize = 256;
            OutputPixel[] PalettePixels = new OutputPixel[PaletteSize];
            var Translate = new int[PaletteSize];

            if (Palette == null || PaletteType == GuPixelFormats.NONE)
            {
                for (int y = 0, n = 0; y < Height; y++)
                {
                    var InputRow = (byte*)&InputByte[y * StrideWidth];
                    for (int x = 0; x < Width; x++, n++)
                    {
                        Output[n] = PalettePixels[0];
                    }
                }
            }
            else
            {
                fixed (OutputPixel* PalettePixelsPtr = PalettePixels)
                {
                    Decode(PaletteType, Palette, PalettePixelsPtr, PalettePixels.Length, 1);
                    //Decode(PaletteType, Palette, PalettePixelsPtr, PaletteCount);
                }
                for (int n = 0; n < PaletteSize; n++)
                {
                    Translate[n] = ((PaletteStart + n) >> PaletteShift) & PaletteMask;
                }

                for (int y = 0, n = 0; y < Height; y++)
                {
                    var InputRow = (byte*)&InputByte[y * StrideWidth];
                    for (int x = 0; x < Width; x++, n++)
                    {
                        byte Value = InputRow[x];
                        Output[n] = PalettePixels[Translate[(Value >> 0) & 0xFF]];
                    }
                }
            }
        }
Beispiel #32
0
        private unsafe void Decode_PALETTE_T4()
        {
            var Input = (byte*)_Input;

            if (Palette == null || PaletteType == GuPixelFormats.NONE)
            {
                Console.WriteLine("Palette required!");
                return;
            }

            OutputPixel[] PalettePixels;
            int PaletteSize = 256;
            PalettePixels = new OutputPixel[PaletteSize];
            var Translate = new int[PaletteSize];
            fixed (OutputPixel* PalettePixelsPtr = PalettePixels)
            {
                Decode(PaletteType, Palette, PalettePixelsPtr, PalettePixels.Length, 1);
                //Decode(PaletteType, Palette, PalettePixelsPtr, PaletteCount);
            }
            //Console.WriteLine(PalettePixels.Length);
            for (int n = 0; n < 16; n++)
            {
                Translate[n] = ((PaletteStart + n) >> PaletteShift) & PaletteMask;
                //Console.WriteLine(PalettePixels[Translate[n]]);
            }

            for (int y = 0, n = 0; y < Height; y++)
            {
                var InputRow = (byte*)&InputByte[y * StrideWidth];
                for (int x = 0; x < Width / 2; x++, n++)
                {
                    byte Value = InputRow[x];
                    Output[n * 2 + 0] = PalettePixels[Translate[(Value >> 0) & 0xF]];
                    Output[n * 2 + 1] = PalettePixels[Translate[(Value >> 4) & 0xF]];
                }
            }
        }
Beispiel #33
0
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            GL.ClearColor(0f, 0f, 0f, 1f);
            GL.Clear(ClearBufferMask.ColorBufferBit);

            if (SimplifiedPspEmulator != null)
            {
                if (texture <= 0)
                {
                    texture = GL.GenTexture();
                }

                GL.BindTexture(TextureTarget.Texture2D, texture);
                CheckError("BindTexture");
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
                                (int)TextureMinFilter.Nearest);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter,
                                (int)TextureMagFilter.Nearest);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS,
                                (int)TextureWrapMode.ClampToEdge);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT,
                                (int)TextureWrapMode.ClampToEdge);
                CheckError("TexParameter");
                var bitmap      = SimplifiedPspEmulator.Display.TakePspScreenshot();
                var pixelsArray = new OutputPixel[bitmap.Area];
                fixed(OutputPixel *pixels = pixelsArray)
                {
                    PixelFormatDecoder.Decode(bitmap.GuPixelFormat, bitmap.Address, pixels, bitmap.Width,
                                              bitmap.Height);

                    /*
                     * var data = new byte[512 * 272 * 4];
                     * for (int i = 0; i < 512 * 272 * 4; i++)
                     * {
                     *  data[i] = 0x10;
                     *  //pixels[i] = OutputPixel.FromRgba(255, 128, 128, 255);
                     * }
                     * Console.WriteLine($"{bitmap.Width}, {bitmap.Height}, {pixels[0]}");
                     */
                    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bitmap.Width, bitmap.Height, 0,
                                  PixelFormat.Bgra, PixelType.UnsignedByte, new IntPtr(pixels));
                    CheckError("TexImage2D");
                    GL.BindTexture(TextureTarget.Texture2D, 0);
                    CheckError("BindTexture");
                }

                GL.Viewport(0, 0, Width, Height);
                CheckError("Viewport");

                GL.Enable(EnableCap.Texture2D);
                GL.MatrixMode(MatrixMode.Projection);
                CheckError("MatrixMode");
                GL.LoadIdentity();
                GL.Ortho(-1.0, 1.0, -1.0, 1.0, 0.0, 4.0);

                GL.MatrixMode(MatrixMode.Modelview);
                GL.LoadIdentity();
                GL.BindTexture(TextureTarget.Texture2D, texture);
                CheckError("BindTexture");

                GL.Begin(BeginMode.Quads);

                GL.TexCoord2(0.0f, 1.0f);
                GL.Vertex2(-1f, -1f);
                GL.TexCoord2(1.0f, 1.0f);
                GL.Vertex2(+1f, -1f);
                GL.TexCoord2(1.0f, 0.0f);
                GL.Vertex2(+1f, +1f);
                GL.TexCoord2(0.0f, 0.0f);
                GL.Vertex2(-1f, +1f);

                GL.End();
                CheckError("End");
            }


            //GL.BindTexture(TextureTarget.Texture2D, 0);
            SwapBuffers();

            if (SimplifiedPspEmulator != null)
            {
                UpdateAnalogCounter(pressingAnalogLeftSet, ref pressingAnalogLeft);
                UpdateAnalogCounter(pressingAnalogUpSet, ref pressingAnalogUp);
                UpdateAnalogCounter(pressingAnalogDownSet, ref pressingAnalogDown);
                UpdateAnalogCounter(pressingAnalogRightSet, ref pressingAnalogRight);

                lx = pressingAnalogLeft != 0 ? -pressingAnalogLeft : pressingAnalogRight;
                ly = pressingAnalogUp != 0 ? -pressingAnalogUp : pressingAnalogDown;

                ctrlData.X         = lx / 3f;
                ctrlData.Y         = ly / 3f;
                ctrlData.TimeStamp = (uint)Emulator.InjectContext.GetInstance <PspRtc>().UnixTimeStampTS.Milliseconds;

                //Console.WriteLine($"controller.InsertSceCtrlData({ctrlData})");
                Emulator.InjectContext.GetInstance <PspController>().InsertSceCtrlData(ctrlData);

                Emulator.InjectContext.GetInstance <PspDisplay>().TriggerVBlankEnd();
            }
        }
Beispiel #34
0
        public TTexture Get(GpuStateStruct GpuState)
        {
            var TextureMappingState = GpuState.TextureMappingState;
            var ClutState           = TextureMappingState.ClutState;
            var TextureState        = TextureMappingState.TextureState;

            TTexture Texture;
            //GC.Collect();
            bool Swizzled       = TextureState.Swizzled;
            uint TextureAddress = TextureState.Mipmap0.Address;
            uint ClutAddress    = ClutState.Address;
            var  ClutFormat     = ClutState.PixelFormat;
            var  ClutStart      = ClutState.Start;
            var  ClutDataStart  = PixelFormatDecoder.GetPixelsSize(ClutFormat, ClutStart);

            ulong Hash1   = TextureAddress | (ulong)((ClutAddress + ClutDataStart) << 32);
            bool  Recheck = false;

            if (Cache.TryGetValue(Hash1, out Texture))
            {
                if (Texture.RecheckTimestamp != RecheckTimestamp)
                {
                    Recheck = true;
                }
            }
            else
            {
                Recheck = true;
            }

            if (Recheck)
            {
                //Console.Write(".");

                //Console.WriteLine("{0:X}", ClutAddress);

                var TextureFormat = TextureState.PixelFormat;
                //var Width = TextureState->Mipmap0.TextureWidth;

                int BufferWidth = TextureState.Mipmap0.BufferWidth;

                // FAKE!
                //BufferWidth = TextureState->Mipmap0.TextureWidth;

                var Height          = TextureState.Mipmap0.TextureHeight;
                var TextureDataSize = PixelFormatDecoder.GetPixelsSize(TextureFormat, BufferWidth * Height);
                if (ClutState.NumberOfColors > 256)
                {
                    ClutState.NumberOfColors = 256;
                }
                var ClutDataSize = PixelFormatDecoder.GetPixelsSize(ClutFormat, ClutState.NumberOfColors);
                var ClutCount    = ClutState.NumberOfColors;
                var ClutShift    = ClutState.Shift;
                var ClutMask     = ClutState.Mask;

                //Console.WriteLine(TextureFormat);

                // INVALID TEXTURE
                if (!PspMemory.IsRangeValid(TextureAddress, TextureDataSize) || TextureDataSize > 2048 * 2048 * 4)
                {
                    Console.Error.WriteLineColored(ConsoleColor.DarkRed,
                                                   "UPDATE_TEXTURE(TEX={0},CLUT={1}:{2}:{3}:{4}:0x{5:X},SIZE={6}x{7},{8},Swizzled={9})",
                                                   TextureFormat, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask, BufferWidth, Height,
                                                   BufferWidth, Swizzled);
                    Console.Error.WriteLineColored(ConsoleColor.DarkRed,
                                                   "Invalid TEXTURE! TextureAddress=0x{0:X}, TextureDataSize={1}", TextureAddress,
                                                   TextureDataSize);
                    if (InvalidTexture == null)
                    {
                        InvalidTexture = new TTexture();
                        InvalidTexture.Init(GpuImpl);

                        int InvalidTextureWidth = 2, InvalidTextureHeight = 2;
                        int InvalidTextureSize = InvalidTextureWidth * InvalidTextureHeight;
                        var Data = new OutputPixel[InvalidTextureSize];
                        fixed(OutputPixel *DataPtr = Data)
                        {
                            var Color1 = OutputPixel.FromRgba(0xFF, 0x00, 0x00, 0xFF);
                            var Color2 = OutputPixel.FromRgba(0x00, 0x00, 0xFF, 0xFF);

                            for (int n = 0; n < InvalidTextureSize; n++)
                            {
                                DataPtr[n] = (n & 1) != 0 ? Color1 : Color2;
                            }
                            InvalidTexture.SetData(Data, InvalidTextureWidth, InvalidTextureHeight);
                        }
                    }
                    return(InvalidTexture);
                }

                //Console.WriteLine("TextureAddress=0x{0:X}, TextureDataSize=0x{1:X}", TextureAddress, TextureDataSize);

                byte *TexturePointer = null;
                byte *ClutPointer    = null;

                try
                {
                    TexturePointer = (byte *)PspMemory.PspAddressToPointerSafe(TextureAddress);
                    ClutPointer    = (byte *)PspMemory.PspAddressToPointerSafe(ClutAddress);
                }
                catch (PspMemory.InvalidAddressException InvalidAddressException)
                {
                    throw InvalidAddressException;
                }

                TextureCacheKey TextureCacheKey = new TextureCacheKey()
                {
                    TextureAddress = TextureAddress,
                    TextureFormat  = TextureFormat,
                    TextureHash    = FastHash(TexturePointer, TextureDataSize),

                    ClutHash    = FastHash(&ClutPointer[ClutDataStart], ClutDataSize),
                    ClutAddress = ClutAddress,
                    ClutFormat  = ClutFormat,
                    ClutStart   = ClutStart,
                    ClutShift   = ClutShift,
                    ClutMask    = ClutMask,
                    Swizzled    = Swizzled,

                    ColorTestEnabled  = GpuState.ColorTestState.Enabled,
                    ColorTestRef      = GpuState.ColorTestState.Ref,
                    ColorTestMask     = GpuState.ColorTestState.Mask,
                    ColorTestFunction = GpuState.ColorTestState.Function,
                };

                if (Texture == null || !Texture.TextureCacheKey.Equals(TextureCacheKey))
                {
                    string TextureName = "texture_" + TextureCacheKey.TextureHash + "_" + TextureCacheKey.ClutHash +
                                         "_" + TextureFormat + "_" + ClutFormat + "_" + BufferWidth + "x" + Height +
                                         "_" + Swizzled;
#if DEBUG_TEXTURE_CACHE
                    Console.Error.WriteLine("UPDATE_TEXTURE(TEX={0},CLUT={1}:{2}:{3}:{4}:0x{5:X},SIZE={6}x{7},{8},Swizzled={9})", TextureFormat, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask, BufferWidth, Height, BufferWidth, Swizzled);
#endif
                    Texture = new TTexture();
                    Texture.Init(GpuImpl);
                    Texture.TextureCacheKey = TextureCacheKey;
                    //Texture.Hash = Hash1;

                    {
                        //int TextureWidth = Math.Max(BufferWidth, Height);
                        //int TextureHeight = Math.Max(BufferWidth, Height);
                        int TextureWidth       = BufferWidth;
                        int TextureHeight      = Height;
                        int TextureWidthHeight = TextureWidth * TextureHeight;

                        fixed(OutputPixel *TexturePixelsPointer = DecodedTextureBuffer)
                        {
                            if (Swizzled)
                            {
                                fixed(byte *SwizzlingBufferPointer = SwizzlingBuffer)
                                {
                                    PointerUtils.Memcpy(SwizzlingBuffer, TexturePointer, TextureDataSize);
                                    PixelFormatDecoder.UnswizzleInline(TextureFormat, (void *)SwizzlingBufferPointer,
                                                                       BufferWidth, Height);
                                    PixelFormatDecoder.Decode(
                                        TextureFormat, (void *)SwizzlingBufferPointer, TexturePixelsPointer,
                                        BufferWidth, Height,
                                        ClutPointer, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask,
                                        strideWidth: PixelFormatDecoder.GetPixelsSize(TextureFormat, TextureWidth)
                                        );
                                }
                            }
                            else
                            {
                                PixelFormatDecoder.Decode(
                                    TextureFormat, (void *)TexturePointer, TexturePixelsPointer, BufferWidth, Height,
                                    ClutPointer, ClutFormat, ClutCount, ClutStart, ClutShift, ClutMask,
                                    strideWidth: PixelFormatDecoder.GetPixelsSize(TextureFormat, TextureWidth)
                                    );
                            }

                            if (TextureCacheKey.ColorTestEnabled)
                            {
                                byte EqualValue, NotEqualValue;

                                switch (TextureCacheKey.ColorTestFunction)
                                {
                                case ColorTestFunctionEnum.GuAlways:
                                    EqualValue    = 0xFF;
                                    NotEqualValue = 0xFF;
                                    break;

                                case ColorTestFunctionEnum.GuNever:
                                    EqualValue    = 0x00;
                                    NotEqualValue = 0x00;
                                    break;

                                case ColorTestFunctionEnum.GuEqual:
                                    EqualValue    = 0xFF;
                                    NotEqualValue = 0x00;
                                    break;

                                case ColorTestFunctionEnum.GuNotequal:
                                    EqualValue    = 0x00;
                                    NotEqualValue = 0xFF;
                                    break;

                                default: throw new NotImplementedException();
                                }

                                ConsoleUtils.SaveRestoreConsoleState(() =>
                                {
                                    Console.BackgroundColor = ConsoleColor.Red;
                                    Console.ForegroundColor = ConsoleColor.Yellow;
                                    Console.Error.WriteLine("{0} : {1}, {2} : ref:{3} : mask:{4}",
                                                            TextureCacheKey.ColorTestFunction, EqualValue, NotEqualValue,
                                                            TextureCacheKey.ColorTestRef, TextureCacheKey.ColorTestMask);
                                });

                                for (int n = 0; n < TextureWidthHeight; n++)
                                {
                                    if ((TexturePixelsPointer[n] & TextureCacheKey.ColorTestMask).Equals(
                                            TextureCacheKey.ColorTestRef & TextureCacheKey.ColorTestMask))
                                    {
                                        TexturePixelsPointer[n].A = EqualValue;
                                    }
                                    else
                                    {
                                        TexturePixelsPointer[n].A = NotEqualValue;
                                    }
                                    if (TexturePixelsPointer[n].A == 0)
                                    {
                                        //Console.Write("yup!");
                                    }
                                }
                            }

                            var TextureInfo = new TextureHookInfo()
                            {
                                TextureCacheKey = TextureCacheKey,
                                Data            = DecodedTextureBuffer,
                                Width           = TextureWidth,
                                Height          = TextureHeight
                            };

                            MessageBus.Dispatch(TextureInfo);

                            var Result = Texture.SetData(TextureInfo.Data, TextureInfo.Width, TextureInfo.Height);
                        }
                    }
                    if (Cache.ContainsKey(Hash1))
                    {
                        Cache[Hash1].Dispose();
                    }
                    Cache[Hash1] = Texture;
                }
            }

            Texture.RecheckTimestamp = RecheckTimestamp;

            return(Texture);
        }
Beispiel #35
0
 protected void _SetVertexInfoColor(OutputPixel Color)
 {
     VertexInfo->Color.X = (float)(Color.R) / 255.0f;
     VertexInfo->Color.Y = (float)(Color.G) / 255.0f;
     VertexInfo->Color.Z = (float)(Color.B) / 255.0f;
     #if true
     VertexInfo->Color.W = (float)(Color.A) / 255.0f;
     #else
     VertexInfo->Color.W = 1.0f;
     #endif
 }
Beispiel #36
0
 public static unsafe ushort Encode_RGBA_4444_Pixel(OutputPixel Pixel)
 {
     uint Out = 0;
     BitUtils.InsertScaled(ref Out, 0, 4, Pixel.R, 255);
     BitUtils.InsertScaled(ref Out, 4, 4, Pixel.G, 255);
     BitUtils.InsertScaled(ref Out, 8, 4, Pixel.B, 255);
     BitUtils.InsertScaled(ref Out, 12, 4, Pixel.A, 255);
     return (ushort)Out;
 }
Beispiel #37
0
        private unsafe void Decode_COMPRESSED_DXT5()
        {
            //Console.Error.WriteLine("Not Implemented: Decode_COMPRESSED_DXT5");
            //throw new NotImplementedException();

            //_Decode_Unimplemented();

            var Colors = new OutputPixel[4];

            for (int y = 0, ni = 0; y < Height; y += 4)
            {
                for (int x = 0; x < Width; x += 4, ni++)
                {
                    var Block = ((Dxt5Block*)InputByte)[ni];
                    Colors[0] = Decode_RGBA_5650_Pixel(Block.Color0).Transform((R, G, B, A) => OutputPixel.FromRGBA(B, G, R, A));
                    Colors[1] = Decode_RGBA_5650_Pixel(Block.Color1).Transform((R, G, B, A) => OutputPixel.FromRGBA(B, G, R, A));
                    Colors[2] = OutputPixel.OperationPerComponent(Colors[0], Colors[1], (a, b) => { return (byte)(((a * 2) / 3) + ((b * 1) / 3)); });
                    Colors[3] = OutputPixel.OperationPerComponent(Colors[0], Colors[1], (a, b) => { return (byte)(((a * 1) / 3) + ((b * 2) / 3)); });

                    // Create Alpha Lookup
                    var AlphaLookup = new byte[8];
                    var Alphas = (ushort)(Block.Alpha >> 48);
                    var Alpha0 = (byte)((Alphas >> 0) & 0xFF);
                    var Alpha1 = (byte)((Alphas >> 8) & 0xFF);

                    AlphaLookup[0] = Alpha0;
                    AlphaLookup[1] = Alpha1;
                    if (Alpha0 > Alpha1)
                    {
                        AlphaLookup[2] = (byte)((6 * Alpha0 + Alpha1) / 7);
                        AlphaLookup[3] = (byte)((5 * Alpha0 + 2 * Alpha1) / 7);
                        AlphaLookup[4] = (byte)((4 * Alpha0 + 3 * Alpha1) / 7);
                        AlphaLookup[5] = (byte)((3 * Alpha0 + 4 * Alpha1) / 7);
                        AlphaLookup[6] = (byte)((2 * Alpha0 + 5 * Alpha1) / 7);
                        AlphaLookup[7] = (byte)((Alpha0 + 6 * Alpha1) / 7);
                    }
                    else
                    {
                        AlphaLookup[2] = (byte)((4 * Alpha0 + Alpha1) / 5);
                        AlphaLookup[3] = (byte)((3 * Alpha0 + 2 * Alpha1) / 5);
                        AlphaLookup[4] = (byte)((2 * Alpha0 + 3 * Alpha1) / 5);
                        AlphaLookup[5] = (byte)((Alpha0 + 4 * Alpha1) / 5);
                        AlphaLookup[6] = (byte)(0x00);
                        AlphaLookup[7] = (byte)(0xFF);
                    }

                    for (int y2 = 0, no = 0; y2 < 4; y2++)
                    {
                        for (int x2 = 0; x2 < 4; x2++, no++)
                        {
                            var Alpha = AlphaLookup[((Block.Alpha >> (3 * no)) & 0x7)];
                            var Color = ((Block.ColorLookup >> (2 * no)) & 0x3);

                            int rx = (x + x2);
                            int ry = (y + y2);
                            int n = ry * Width + rx;

                            Output[n] = Colors[Color];
                            Output[n].A = Alpha;
                        }
                    }
                }
            }
        }
Beispiel #38
0
        /// <summary>
        /// DXT2 and DXT3 (collectively also known as Block Compression 2 or BC2) converts 16 input pixels
        /// (corresponding to a 4x4 pixel block) into 128 bits of output, consisting of 64 bits of alpha channel data
        /// (4 bits for each pixel) followed by 64 bits of color data, encoded the same way as DXT1 (with the exception
        /// that the 4 color version of the DXT1 algorithm is always used instead of deciding which version to use based
        /// on the relative values of  and ). In DXT2, the color data is interpreted as being premultiplied by alpha, in
        /// DXT3 it is interpreted as not having been premultiplied by alpha. Typically DXT2/3 are well suited to images
        /// with sharp alpha transitions, between translucent and opaque areas.
        /// </summary>
        private unsafe void Decode_COMPRESSED_DXT3()
        {
            var Colors = new OutputPixel[4];

            for (int y = 0, ni = 0; y < Height; y += 4)
            {
                for (int x = 0; x < Width; x += 4, ni++)
                {
                    var Block = ((Dxt3Block*)InputByte)[ni];
                    Colors[0] = Decode_RGBA_5650_Pixel(Block.Color0).Transform((R, G, B, A) => OutputPixel.FromRGBA(B, G, R, A));
                    Colors[1] = Decode_RGBA_5650_Pixel(Block.Color1).Transform((R, G, B, A) => OutputPixel.FromRGBA(B, G, R, A));
                    Colors[2] = OutputPixel.OperationPerComponent(Colors[0], Colors[1], (a, b) => { return (byte)(((a * 2) / 3) + ((b * 1) / 3)); });
                    Colors[3] = OutputPixel.OperationPerComponent(Colors[0], Colors[1], (a, b) => { return (byte)(((a * 1) / 3) + ((b * 2) / 3)); });

                    for (int y2 = 0, no = 0; y2 < 4; y2++)
                    {
                        for (int x2 = 0; x2 < 4; x2++, no++)
                        {
                            var Alpha = ((Block.Alpha >> (4 * no)) & 0xF);
                            var Color = ((Block.ColorLookup >> (2 * no)) & 0x3);

                            int rx = (x + x2);
                            int ry = (y + y2);
                            int n = ry * Width + rx;

                            Output[n] = Colors[Color];
                            Output[n].A = (byte)((Alpha * 0xFF) / 0xF);
                        }
                    }
                }
            }
        }