protected override void EncodeBlock(ARGBPixel *sPtr, VoidPtr blockAddr, int width) { CMPRBlock *dPtr = (CMPRBlock *)blockAddr; for (int y = 0; y < 2; y++, sPtr += (width * 4)) { for (int x = 0; x < 8; x += 4) { *dPtr++ = CMPRBlock.Encode(&sPtr[x], width, false); } } }
public static CMPRBlock Encode(ARGBPixel* block, int width, bool fast) { CMPRBlock p = new CMPRBlock(); uint* pData = stackalloc uint[16]; ARGBPixel* pColor = (ARGBPixel*)pData; bool isSingle = true, hasAlpha = false, allAlpha = true; for (int y = 0, i = 0; y < 4; y++, block += width) { for (int x = 0; x < 4; i++) { pColor[i] = block[x++]; if (pData[i] != pData[0]) isSingle = false; if (pColor[i].A < 0x80) hasAlpha = true; else allAlpha = false; } } /* * Foreach block: * copy block to buffer * mirror remaning colors? * * If block is single color: * run optiml compress? * else * Initialize color set * Compress block using color set * * */ //BlockDecoder decoder = new BlockDecoder(width, 4, 4, 4); //bool isSingle = true, hasAlpha = false, allAlpha = true; //for (int i = 0; i < 16; i++) //{ // int index = decoder[i]; // pColor[i] = block[index]; // if (pData[i] != pData[0]) isSingle = false; // if (pColor[i].A < 0x80) hasAlpha = true; // else allAlpha = false; //} //bool isSingle = true, hasAlpha = false, allAlpha = true; //ARGBPixel* ptr = block; //int index = 0; //for (int y = 0; y < 4; y++, ptr += width - 4) //{ // for (int x = 0; x < 4; x++, ptr++, index++) // { // pColor[index] = block[(y * width) + x]; // if (pData[0] != pData[index]) isSingle = false; // if (pColor[index].A < 0x80) hasAlpha = true; // else allAlpha = false; // } //} //if (allAlpha) //{ // p._root0._data = 0; // p._root1._data = 0xFFFF; // p._lookup = 0xFFFFFFFF; //} //else if (isSingle) //{ // p._root0 = (RGB565Pixel)(*block); // p._root1._data = 0; // p._lookup = 0x00000000; //} //else //{ uint* palData = stackalloc uint[4]; ARGBPixel* palCol = (ARGBPixel*)palData; int bestDist = -1; for (int i = 0; i < 16; i++) { ARGBPixel p1 = pColor[i]; for (int x = i + 1; x < 16; x++) { ARGBPixel p2 = pColor[x]; int d = p1.DistanceTo(p2); if (d > bestDist) { bestDist = d; palCol[2] = p1; palCol[3] = p2; } } } wRGB565Pixel smax = (wRGB565Pixel)palCol[2]; wRGB565Pixel smin = (wRGB565Pixel)palCol[3]; if (smax < smin) { smax = (wRGB565Pixel)palCol[3]; smin = (wRGB565Pixel)palCol[2]; } if (hasAlpha) { p._root0 = smin; p._root1 = smax; palCol[0] = (ARGBPixel)smin; palCol[1] = (ARGBPixel)smax; palCol[2] = new ARGBPixel(255, (byte)((palCol[0].R + palCol[1].R) >> 1), (byte)((palCol[0].G + palCol[1].G) >> 1), (byte)((palCol[0].B + palCol[1].B) >> 1)); palCol[3] = new ARGBPixel(); } else { p._root0 = smax; p._root1 = smin; palCol[0] = (ARGBPixel)smax; palCol[1] = (ARGBPixel)smin; palCol[2] = new ARGBPixel(255, (byte)(((palCol[0].R << 1) + palCol[1].R) / 3), (byte)(((palCol[0].G << 1) + palCol[1].G) / 3), (byte)(((palCol[0].B << 1) + palCol[1].B) / 3)); palCol[3] = new ARGBPixel(255, (byte)(((palCol[1].R << 1) + palCol[0].R) / 3), (byte)(((palCol[1].G << 1) + palCol[0].G) / 3), (byte)(((palCol[1].B << 1) + palCol[0].B) / 3)); } uint indicies = 0; for (int i = 0, shift = 30; i < 16; i++, shift -= 2) { uint index = 3; if (pColor[i].A >= 0x80) { int bd = int.MaxValue; for (int x = 0; x < ((hasAlpha) ? 4 : 3); x++) { int dist = palCol[x].DistanceTo(pColor[i]); if (dist < bd) { bd = dist; index = (uint)x; } } } indicies |= index << shift; } p._lookup = indicies; //p = DXT1Fast.Compress(pColor); //} return p; }
public static CMPRBlock Encode(ARGBPixel *block, int width, bool fast) { CMPRBlock p = new CMPRBlock(); uint * pData = stackalloc uint[16]; ARGBPixel *pColor = (ARGBPixel *)pData; bool isSingle = true, hasAlpha = false, allAlpha = true; for (int y = 0, i = 0; y < 4; y++, block += width) { for (int x = 0; x < 4; i++) { pColor[i] = block[x++]; if (pData[i] != pData[0]) { isSingle = false; } if (pColor[i].A < 0x80) { hasAlpha = true; } else { allAlpha = false; } } } /* * Foreach block: * copy block to buffer * mirror remaning colors? * * If block is single color: * run optiml compress? * else * Initialize color set * Compress block using color set * * */ //BlockDecoder decoder = new BlockDecoder(width, 4, 4, 4); //bool isSingle = true, hasAlpha = false, allAlpha = true; //for (int i = 0; i < 16; i++) //{ // int index = decoder[i]; // pColor[i] = block[index]; // if (pData[i] != pData[0]) isSingle = false; // if (pColor[i].A < 0x80) hasAlpha = true; // else allAlpha = false; //} //bool isSingle = true, hasAlpha = false, allAlpha = true; //ARGBPixel* ptr = block; //int index = 0; //for (int y = 0; y < 4; y++, ptr += width - 4) //{ // for (int x = 0; x < 4; x++, ptr++, index++) // { // pColor[index] = block[(y * width) + x]; // if (pData[0] != pData[index]) isSingle = false; // if (pColor[index].A < 0x80) hasAlpha = true; // else allAlpha = false; // } //} //if (allAlpha) //{ // p._root0._data = 0; // p._root1._data = 0xFFFF; // p._lookup = 0xFFFFFFFF; //} //else if (isSingle) //{ // p._root0 = (RGB565Pixel)(*block); // p._root1._data = 0; // p._lookup = 0x00000000; //} //else //{ uint * palData = stackalloc uint[4]; ARGBPixel *palCol = (ARGBPixel *)palData; int bestDist = -1; for (int i = 0; i < 16; i++) { ARGBPixel p1 = pColor[i]; for (int x = i + 1; x < 16; x++) { ARGBPixel p2 = pColor[x]; int d = p1.DistanceTo(p2); if (d > bestDist) { bestDist = d; palCol[2] = p1; palCol[3] = p2; } } } wRGB565Pixel smax = (wRGB565Pixel)palCol[2]; wRGB565Pixel smin = (wRGB565Pixel)palCol[3]; if (smax < smin) { smax = (wRGB565Pixel)palCol[3]; smin = (wRGB565Pixel)palCol[2]; } if (hasAlpha) { p._root0 = smin; p._root1 = smax; palCol[0] = (ARGBPixel)smin; palCol[1] = (ARGBPixel)smax; palCol[2] = new ARGBPixel(255, (byte)((palCol[0].R + palCol[1].R) >> 1), (byte)((palCol[0].G + palCol[1].G) >> 1), (byte)((palCol[0].B + palCol[1].B) >> 1)); palCol[3] = new ARGBPixel(); } else { p._root0 = smax; p._root1 = smin; palCol[0] = (ARGBPixel)smax; palCol[1] = (ARGBPixel)smin; palCol[2] = new ARGBPixel(255, (byte)(((palCol[0].R << 1) + palCol[1].R) / 3), (byte)(((palCol[0].G << 1) + palCol[1].G) / 3), (byte)(((palCol[0].B << 1) + palCol[1].B) / 3)); palCol[3] = new ARGBPixel(255, (byte)(((palCol[1].R << 1) + palCol[0].R) / 3), (byte)(((palCol[1].G << 1) + palCol[0].G) / 3), (byte)(((palCol[1].B << 1) + palCol[0].B) / 3)); } uint indicies = 0; for (int i = 0, shift = 30; i < 16; i++, shift -= 2) { uint index = 3; if (pColor[i].A >= 0x80) { int bd = int.MaxValue; for (int x = 0; x < ((hasAlpha) ? 4 : 3); x++) { int dist = palCol[x].DistanceTo(pColor[i]); if (dist < bd) { bd = dist; index = (uint)x; } } } indicies |= index << shift; } p._lookup = indicies; //p = DXT1Fast.Compress(pColor); //} return(p); }
private static void optimizeEndPoints4(Vector3* points, CMPRBlock* block) { float alpha2_sum = 0.0f; float beta2_sum = 0.0f; float alphabeta_sum = 0.0f; Vector3 alphax_sum = new Vector3(); Vector3 betax_sum = new Vector3(); uint indices = block->_lookup; for (int i = 0, bi = 30; i < 16; ++i, bi -= 2) { uint bits = indices >> bi; float beta = bits & 1; if ((bits & 2) != 0) beta = (1 + beta) / 3.0f; float alpha = 1.0f - beta; alpha2_sum += alpha * alpha; beta2_sum += beta * beta; alphabeta_sum += alpha * beta; alphax_sum += alpha * points[i]; betax_sum += beta * points[i]; } float denom = alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum; if (Math.Abs(denom) <= 0.0001f) return; float factor = 1.0f / denom; Vector3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; Vector3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; a.Clamp(0.0f, 255.0f); b.Clamp(0.0f, 255.0f); ushort color0 = roundAndExpand(&a); ushort color1 = roundAndExpand(&b); if (color0 < color1) { Vector3 t = a; a = b; b = t; VoidPtr.Swap(&color0, &color1); } //CMPRBlock block = new CMPRBlock(); block->_root0._data = color0; block->_root1._data = color1; block->_lookup = computeIndices4(points, &a, &b); }
private static CMPRBlock optimalCompressDXT1(ARGBPixel c) { CMPRBlock block = new CMPRBlock(); uint indices = 0xAAAAAAAA; block._root0._data = (ushort)((OMatch5[c.R, 0] << 11) | (OMatch6[c.G, 0] << 5) | OMatch5[c.B, 0]); block._root1._data = (ushort)((OMatch5[c.R, 1] << 11) | (OMatch6[c.G, 1] << 5) | OMatch5[c.B, 1]); if (block._root0 < block._root1) { VoidPtr.Swap((short*)&block._root0, (short*)&block._root1); indices ^= 0x55555555; } block._lookup = indices; return block; }
private static CMPRBlock compressDXT1(ARGBPixel* pBlock) { float* pointData = stackalloc float[48]; Vector3* points = (Vector3*)pointData; extractColorBlockRGB(pBlock, points); // find min and max colors Vector3 maxColor, minColor; findMinMaxColorsBox(points, 16, &maxColor, &minColor); selectDiagonal(points, 16, &maxColor, &minColor); insetBBox(&maxColor, &minColor); ushort color0 = roundAndExpand(&maxColor); ushort color1 = roundAndExpand(&minColor); if (color0 < color1) { Vector3 t = maxColor; maxColor = minColor; minColor = t; VoidPtr.Swap(&color0, &color1); } CMPRBlock block = new CMPRBlock(); block._root0._data = color0; block._root1._data = color1; block._lookup = computeIndices4(points, &maxColor, &minColor); optimizeEndPoints4(points, &block); return block; }
public static CMPRBlock optimalCompressDXT1a(ARGBPixel rgba) { if (rgba.A < 128) { CMPRBlock block = new CMPRBlock(); block._root0._data = 0; block._root1._data = 0; block._lookup = 0xFFFFFFFF; return block; } else { return optimalCompressDXT1(rgba); } }
public static CMPRBlock compressDXT1a(ARGBPixel* img, int imgX, int imgY, int imgW, int imgH) { uint* pData = stackalloc uint[16]; ARGBPixel* pBlock = (ARGBPixel*)pData; bool hasAlpha = false; bool isSingle = true; ARGBPixel p; ARGBPixel* sPtr = img + (imgX + (imgY * imgW)); int index = 0; for (int y = 0; y < 4; y++) for (int x = 0; x < 4; x++) { p = sPtr[x + (y * imgW)]; pBlock[index++] = p; if (p != pBlock[0]) isSingle = false; if (p.A < 128) hasAlpha = true; } if (isSingle) return optimalCompressDXT1a(sPtr[0]); if (!hasAlpha) return compressDXT1(pBlock); // @@ Handle single RGB, with varying alpha? We need tables for single color compressor in 3 color mode. //else if (rgba.isSingleColorNoAlpha()) { ... } float* pointData = stackalloc float[48]; Vector3* points = (Vector3*)pointData; // read block //Vector3 block[16]; int num = extractColorBlockRGBA(pBlock, points); // find min and max colors Vector3 maxColor, minColor; findMinMaxColorsBox(points, num, &maxColor, &minColor); selectDiagonal(points, num, &maxColor, &minColor); insetBBox(&maxColor, &minColor); ushort color0 = roundAndExpand(&maxColor); ushort color1 = roundAndExpand(&minColor); if (color0 < color1) { Vector3 t = maxColor; maxColor = minColor; minColor = t; VoidPtr.Swap(&color0, &color1); } CMPRBlock block = new CMPRBlock(); block._root0._data = color1; block._root1._data = color0; block._lookup = computeIndices3(pBlock, &maxColor, &minColor); // optimizeEndPoints(block, dxtBlock); return block; }