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))); }
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); }
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); }
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); }
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 }
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()); } }
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); }
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]; } } } } }
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; } } }
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; } }
/* 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))); }
/// <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); } } } } }
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()); } }
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); }
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]]; } } }
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)); } }
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; } }
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; } } } } }
public static uint Encode(this ColorFormat colorFormat, OutputPixel outputPixel) { return(colorFormat.Encode(outputPixel.R, outputPixel.G, outputPixel.B, outputPixel.A)); }
public static unsafe uint Encode_RGBA_8888_Pixel(OutputPixel Pixel) { return *(uint *)&Pixel; }
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); }
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); }
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; }
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]]; } } } }
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]]; } } }
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(); } }
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); }
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 }
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; }
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; } } } } }
/// <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); } } } } }