static void pvrtcGetDecompressedPixels(PVRTCWord P, PVRTCWord Q, PVRTCWord R, PVRTCWord S, ref Pixel32[] pColorData, byte ui8Bpp) { int[][] i32ModulationValues = new int[16][]; for (int i = 0; i < i32ModulationValues.Length; i++) { i32ModulationValues[i] = new int[8]; } int[][] i32ModulationModes = new int[16][]; for (int i = 0; i < i32ModulationModes.Length; i++) { i32ModulationModes[i] = new int[8]; } Pixel128S[] upscaledColorA = new Pixel128S[32]; Pixel128S[] upscaledColorB = new Pixel128S[32]; uint ui32WordWidth = 4; uint ui32WordHeight = 4; if (ui8Bpp == 2) { ui32WordWidth = 8; } unpackModulations(P, 0, 0, i32ModulationValues, i32ModulationModes, ui8Bpp); unpackModulations(Q, (int)ui32WordWidth, 0, i32ModulationValues, i32ModulationModes, ui8Bpp); unpackModulations(R, 0, (int)ui32WordHeight, i32ModulationValues, i32ModulationModes, ui8Bpp); unpackModulations(S, (int)ui32WordWidth, (int)ui32WordHeight, i32ModulationValues, i32ModulationModes, ui8Bpp); interpolateColors(getColorA(P.u32ColorData), getColorA(Q.u32ColorData), getColorA(R.u32ColorData), getColorA(S.u32ColorData), ref upscaledColorA, ui8Bpp); interpolateColors(getColorB(P.u32ColorData), getColorB(Q.u32ColorData), getColorB(R.u32ColorData), getColorB(S.u32ColorData), ref upscaledColorB, ui8Bpp); for (uint y = 0; y < ui32WordHeight; y++) { for (uint x = 0; x < ui32WordWidth; x++) { int mod = getModulationValues(i32ModulationValues, i32ModulationModes, x + ui32WordWidth / 2, y + ui32WordHeight / 2, ui8Bpp); bool punchthroughAlpha = false; if (mod > 10) { punchthroughAlpha = true; mod -= 10; } Pixel128S result; result.red = (upscaledColorA[y * ui32WordWidth + x].red * (8 - mod) + upscaledColorB[y * ui32WordWidth + x].red * mod) / 8; result.green = (upscaledColorA[y * ui32WordWidth + x].green * (8 - mod) + upscaledColorB[y * ui32WordWidth + x].green * mod) / 8; result.blue = (upscaledColorA[y * ui32WordWidth + x].blue * (8 - mod) + upscaledColorB[y * ui32WordWidth + x].blue * mod) / 8; if (punchthroughAlpha) { result.alpha = 0; } else { result.alpha = (upscaledColorA[y * ui32WordWidth + x].alpha * (8 - mod) + upscaledColorB[y * ui32WordWidth + x].alpha * mod) / 8; } if (ui8Bpp == 2) { pColorData[y * ui32WordWidth + x].red = (byte)result.red; pColorData[y * ui32WordWidth + x].green = (byte)result.green; pColorData[y * ui32WordWidth + x].blue = (byte)result.blue; pColorData[y * ui32WordWidth + x].alpha = (byte)result.alpha; } else if (ui8Bpp == 4) { pColorData[y + x * ui32WordHeight].red = (byte)result.red; pColorData[y + x * ui32WordHeight].green = (byte)result.green; pColorData[y + x * ui32WordHeight].blue = (byte)result.blue; pColorData[y + x * ui32WordHeight].alpha = (byte)result.alpha; } } } }
static void interpolateColors(Pixel32 P, Pixel32 Q, Pixel32 R, Pixel32 S, ref Pixel128S[] pPixel, byte ui8Bpp) { uint ui32WordWidth = 4; uint ui32WordHeight = 4; if (ui8Bpp == 2) { ui32WordWidth = 8; } Pixel128S hP = new Pixel128S() { red = (int)P.red, green = (int)P.green, blue = (int)P.blue, alpha = (int)P.alpha }; Pixel128S hQ = new Pixel128S() { red = (int)Q.red, green = (int)Q.green, blue = (int)Q.blue, alpha = (int)Q.alpha }; Pixel128S hR = new Pixel128S() { red = (int)R.red, green = (int)R.green, blue = (int)R.blue, alpha = (int)R.alpha }; Pixel128S hS = new Pixel128S() { red = (int)S.red, green = (int)S.green, blue = (int)S.blue, alpha = (int)S.alpha }; Pixel128S QminusP = new Pixel128S() { red = hQ.red - hP.red, green = hQ.green - hP.green, blue = hQ.blue - hP.blue, alpha = hQ.alpha - hP.alpha }; Pixel128S SminusR = new Pixel128S() { red = hS.red - hR.red, green = hS.green - hR.green, blue = hS.blue - hR.blue, alpha = hS.alpha - hR.alpha }; hP.red *= (int)ui32WordWidth; hP.green *= (int)ui32WordWidth; hP.blue *= (int)ui32WordWidth; hP.alpha *= (int)ui32WordWidth; hR.red *= (int)ui32WordWidth; hR.green *= (int)ui32WordWidth; hR.blue *= (int)ui32WordWidth; hR.alpha *= (int)ui32WordWidth; if (ui8Bpp == 2) { for (uint x = 0; x < ui32WordWidth; x++) { Pixel128S result = new Pixel128S() { red = 4 * hP.red, green = 4 * hP.green, blue = 4 * hP.blue, alpha = 4 * hP.alpha }; Pixel128S dY = new Pixel128S() { red = hR.red - hP.red, green = hR.green - hP.green, blue = hR.blue - hP.blue, alpha = hR.alpha - hP.alpha }; for (uint y = 0; y < ui32WordHeight; y++) { pPixel[y * ui32WordWidth + x].red = (int)((result.red >> 7) + (result.red >> 2)); pPixel[y * ui32WordWidth + x].green = (int)((result.green >> 7) + (result.green >> 2)); pPixel[y * ui32WordWidth + x].blue = (int)((result.blue >> 7) + (result.blue >> 2)); pPixel[y * ui32WordWidth + x].alpha = (int)((result.alpha >> 5) + (result.alpha >> 1)); result.red += dY.red; result.green += dY.green; result.blue += dY.blue; result.alpha += dY.alpha; } hP.red += QminusP.red; hP.green += QminusP.green; hP.blue += QminusP.blue; hP.alpha += QminusP.alpha; hR.red += SminusR.red; hR.green += SminusR.green; hR.blue += SminusR.blue; hR.alpha += SminusR.alpha; } } else { for (uint y = 0; y < ui32WordHeight; y++) { Pixel128S result = new Pixel128S() { red = 4 * hP.red, green = 4 * hP.green, blue = 4 * hP.blue, alpha = 4 * hP.alpha }; Pixel128S dY = new Pixel128S() { red = hR.red - hP.red, green = hR.green - hP.green, blue = hR.blue - hP.blue, alpha = hR.alpha - hP.alpha }; for (uint x = 0; x < ui32WordWidth; x++) { pPixel[y * ui32WordWidth + x].red = (int)((result.red >> 6) + (result.red >> 1)); pPixel[y * ui32WordWidth + x].green = (int)((result.green >> 6) + (result.green >> 1)); pPixel[y * ui32WordWidth + x].blue = (int)((result.blue >> 6) + (result.blue >> 1)); pPixel[y * ui32WordWidth + x].alpha = (int)((result.alpha >> 4) + (result.alpha)); result.red += dY.red; result.green += dY.green; result.blue += dY.blue; result.alpha += dY.alpha; } hP.red += QminusP.red; hP.green += QminusP.green; hP.blue += QminusP.blue; hP.alpha += QminusP.alpha; hR.red += SminusR.red; hR.green += SminusR.green; hR.blue += SminusR.blue; hR.alpha += SminusR.alpha; } } }