private void WriteIndices(BitmapData destData) { ARGBPixel *sPtr = _srcPixels; ushort id; byte * dPtr = (byte *)destData.Scan0; int step, val; if (destData.PixelFormat == PixelFormat.Format8bppIndexed) { step = destData.Stride - _width; for (int y = 0; y < _height; y++, dPtr += step) { for (int x = 0; x < _width; x++) { _idFunc(*sPtr++, &id); *dPtr++ = (byte)_groupTable[id]->_box->_index; } } } else { step = destData.Stride - ((_width + 1) / 2); for (int y = 0; y < _height; y++, dPtr += step) { for (int x = _width; x > 0; x -= 2) { _idFunc(*sPtr++, &id); val = _groupTable[id]->_box->_index << 4; if (x > 1) { _idFunc(*sPtr++, &id); val |= _groupTable[id]->_box->_index & 0xF; } *dPtr++ = (byte)val; } } } }
public virtual Bitmap DecodeTexture(VoidPtr addr, int w, int h, int mipLevel) { addr += GetMipOffset(ref w, ref h, mipLevel); int aw = w.Align(BlockWidth), ah = h.Align(BlockHeight); using (DIB dib = new DIB(w, h, BlockWidth, BlockHeight, PixelFormat.Format32bppArgb)) { int sStep = BlockWidth * BlockHeight * BitsPerPixel / 8; int bStride = aw * BitsPerPixel / 8; for (int y = 0; y < ah; y += BlockHeight) { ARGBPixel *dPtr = (ARGBPixel *)dib.Scan0 + (y * aw); VoidPtr sPtr = addr + (y * bStride); for (int x = 0; x < aw; x += BlockWidth, dPtr += BlockWidth, sPtr += sStep) { DecodeBlock(sPtr, dPtr, aw); } } return(dib.ToBitmap()); } }
private MedianCut(Bitmap bmp, WiiPixelFormat texFormat, WiiPaletteFormat palFormat) { //Set output format if (texFormat == WiiPixelFormat.CI4) _outFormat = PixelFormat.Format4bppIndexed; else if (texFormat == WiiPixelFormat.CI8) _outFormat = PixelFormat.Format8bppIndexed; else throw new ArgumentException("Invalid pixel format."); //Set conversion functions if (palFormat == WiiPaletteFormat.IA8) { _idFunc = IA8Handler; _idConv = IA8Converter; } else if (palFormat == WiiPaletteFormat.RGB565) { _idFunc = RGB565Handler; _idConv = RGB565Converter; } else { _idFunc = RGB5A3Handler; _idConv = RGB5A3Converter; } //Lock/set source data _srcBmp = bmp; _width = bmp.Width; _height = bmp.Height; _size = _width * _height; _srcData = bmp.LockBits(new Rectangle(0, 0, _width, _height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); _srcPixels = (ARGBPixel*)_srcData.Scan0; //Create buffers _boxes = (ColorBox*)Marshal.AllocHGlobal(256 * sizeof(ColorBox)); _groupTable = (ColorEntry**)Marshal.AllocHGlobal(65536 * 4); }
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); }
protected override void DecodeBlock(VoidPtr blockAddr, ARGBPixel *dPtr, int width) { byte *s1 = (byte *)blockAddr; byte *s2 = s1 + 32; byte *d2 = (byte *)dPtr; for (int y = 0; y < 4; y++, d2 += (width - 4) << 2) { for (int x = 0; x < 4; x++, d2 += 4) { d2[3] = *s1++; d2[2] = *s1++; d2[1] = *s2++; d2[0] = *s2++; } } //RGBA8Pixel* sPtr = (RGBA8Pixel*)blockAddr; ////ARGBPixel* dPtr = (ARGBPixel*)destAddr; //for (int y = 0; y < 4; y++, dPtr += width) // for (int x = 0; x < 4; sPtr = (RGBA8Pixel*)((int)sPtr + 2) ) // dPtr[x++] = (ARGBPixel)(*sPtr); }
public void Dispose() { if (_boxes != null) { Marshal.FreeHGlobal((IntPtr)_boxes); _boxes = null; } if (_groupTable != null) { Marshal.FreeHGlobal((IntPtr)_groupTable); _groupTable = null; } if (_srcBmp != null) { _srcBmp.UnlockBits(_srcData); _srcBmp = null; _srcData = null; _srcPixels = null; } GC.SuppressFinalize(this); }
protected abstract void EncodeBlock(ARGBPixel *sPtr, VoidPtr blockAddr, int width);
public static unsafe Bitmap IndexColors(this Bitmap src, ColorPalette palette, PixelFormat format) { int w = src.Width, h = src.Height; int entries = palette.Entries.Length; switch (format) { case PixelFormat.Format4bppIndexed: { entries = Math.Min(entries, 16); break; } case PixelFormat.Format8bppIndexed: { entries = Math.Min(entries, 256); break; } default: { throw new ArgumentException("Pixel format is not an indexed format."); } } Bitmap dst = new Bitmap(w, h, format); dst.Palette = palette; BitmapData sData = src.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); BitmapData dData = dst.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, format); ARGBPixel *sPtr = (ARGBPixel *)sData.Scan0; for (int y = 0; y < h; y++) { byte *dPtr = (byte *)dData.Scan0 + (y * dData.Stride); for (int x = 0; x < w; x++) { ARGBPixel p = *sPtr++; int bestDist = Int32.MaxValue, bestIndex = 0; for (int z = 0; z < entries; z++) { int dist = p.DistanceTo(palette.Entries[z]); if (dist < bestDist) { bestDist = dist; bestIndex = z; } } if (format == PixelFormat.Format4bppIndexed) { byte val = *dPtr; if ((x % 2) == 0) { *dPtr = (byte)((bestIndex << 4) | (val & 0x0F)); } else { *dPtr++ = (byte)((val & 0xF0) | (bestIndex & 0x0F)); } } else { *dPtr++ = (byte)bestIndex; } } } dst.UnlockBits(dData); src.UnlockBits(sData); return(dst); }
public static unsafe void Clamp(this Bitmap bmp, WiiPixelFormat format) { int w = bmp.Width, h = bmp.Height; BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); PixelClamper clmp; switch (format) { case WiiPixelFormat.I4: { clmp = p => { *p = ((I4Pixel)(*p))[0]; }; break; } case WiiPixelFormat.I8: { clmp = p => { *p = (ARGBPixel)(I8Pixel)(*p); }; break; } case WiiPixelFormat.IA4: { clmp = p => { *p = (IA4Pixel)(*p); }; break; } case WiiPixelFormat.IA8: { clmp = p => { *p = (IA8Pixel)(*p); }; break; } case WiiPixelFormat.RGB565: { clmp = p => { *p = (ARGBPixel)(wRGB565Pixel)(*p); }; break; } case WiiPixelFormat.RGB5A3: { clmp = p => { *p = (ARGBPixel)(wRGB5A3Pixel)(*p); }; break; } case WiiPixelFormat.RGBA8: default: { clmp = p => { }; break; } } for (ARGBPixel *ptr = (ARGBPixel *)data.Scan0, ceil = ptr + w * h; ptr < ceil;) { clmp(ptr++); } bmp.UnlockBits(data); }
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); }
public void Set(ARGBPixel *p) { A = p->A; R = p->R; G = p->G; B = p->B; }
private unsafe void Load(int index, int program, PLT0Node palette) { if (_context == null) { return; } Source = null; if (Texture != null) { Texture.Delete(); } Texture = new GLTexture(_context, 0, 0); Texture.Bind(index, program); //ctx._states[String.Format("{0}_TexRef", Name)] = Texture; Bitmap bmp = null; TEX0Node tNode = null; if (_context._states.ContainsKey("_Node_Refs")) { List <ResourceNode> nodes = _context._states["_Node_Refs"] as List <ResourceNode>; List <ResourceNode> searched = new List <ResourceNode>(nodes.Count); foreach (ResourceNode n in nodes) { ResourceNode node = n.RootNode; if (searched.Contains(node)) { continue; } searched.Add(node); //Search node itself first if ((tNode = node.FindChild("Textures(NW4R)/" + Name, true) as TEX0Node) != null) { Source = tNode; if (palette != null) { bmp = tNode.GetImage(0, palette); } else { bmp = tNode.GetImage(0); } } else { //Then search node directory string path = node._origPath; if (path != null) { DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(path)); foreach (FileInfo file in dir.GetFiles(Name + ".*")) { if (file.Name.EndsWith(".tga")) { Source = file.FullName; bmp = TGA.FromFile(file.FullName); break; } else if (file.Name.EndsWith(".png") || file.Name.EndsWith(".tiff") || file.Name.EndsWith(".tif")) { Source = file.FullName; bmp = (Bitmap)Bitmap.FromFile(file.FullName); break; } } } } if (bmp != null) { break; } } searched.Clear(); if (bmp != null) { int w = bmp.Width, h = bmp.Height, size = w * h; Texture._width = w; Texture._height = h; //_context.glTexParameter(GLTextureTarget.Texture2D, GLTextureParameter.MagFilter, (int)GLTextureFilter.LINEAR); //_context.glTexParameter(GLTextureTarget.Texture2D, GLTextureParameter.MinFilter, (int)GLTextureFilter.NEAREST_MIPMAP_LINEAR); //_context.glTexParameter(GLTextureTarget.Texture2D, GLTextureParameter.BaseLevel, 0); //if (tNode != null) // _context.glTexParameter(GLTextureTarget.Texture2D, GLTextureParameter.MaxLevel, tNode.LevelOfDetail); //else // _context.glTexParameter(GLTextureTarget.Texture2D, GLTextureParameter.MaxLevel, 0); BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); try { using (UnsafeBuffer buffer = new UnsafeBuffer(size << 2)) { ARGBPixel *sPtr = (ARGBPixel *)data.Scan0; ABGRPixel *dPtr = (ABGRPixel *)buffer.Address; for (int i = 0; i < size; i++) { *dPtr++ = (ABGRPixel)(*sPtr++); } int res = _context.gluBuild2DMipmaps(GLTextureTarget.Texture2D, GLInternalPixelFormat._4, w, h, GLPixelDataFormat.RGBA, GLPixelDataType.UNSIGNED_BYTE, buffer.Address); if (res != 0) { } } } finally { bmp.UnlockBits(data); bmp.Dispose(); } } } }
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 void Decode(ARGBPixel *image, int imgX, int imgY, int imgW, int imgH) { Decode(image + (imgX + (imgY * imgW)), imgW); }
protected abstract void DecodeBlock(VoidPtr blockAddr, ARGBPixel *destAddr, int width);
public static ARGBPixel[] ExtractColors(MDL0ColorData *colors) { int count = colors->_numEntries; ARGBPixel[] c = new ARGBPixel[count]; fixed(ARGBPixel *p = c) { ARGBPixel *dPtr = p; switch (colors->Type) { case WiiColorComponentType.RGB565: { wRGB565Pixel *sPtr = (wRGB565Pixel *)colors->Data; for (int i = 0; i < count; i++) { *dPtr++ = (ARGBPixel)(*sPtr++); } break; } case WiiColorComponentType.RGB8: { wRGBPixel *sPtr = (wRGBPixel *)colors->Data; for (int i = 0; i < count; i++) { *dPtr++ = (ARGBPixel)(*sPtr++); } break; } case WiiColorComponentType.RGBX8: { wRGBXPixel *sPtr = (wRGBXPixel *)colors->Data; for (int i = 0; i < count; i++) { *dPtr++ = (ARGBPixel)(*sPtr++); } break; } case WiiColorComponentType.RGBA4: { wRGBA4Pixel *sPtr = (wRGBA4Pixel *)colors->Data; for (int i = 0; i < count; i++) { *dPtr++ = (ARGBPixel)(*sPtr++); } break; } case WiiColorComponentType.RGBA6: { wRGBA6Pixel *sPtr = (wRGBA6Pixel *)colors->Data; for (int i = 0; i < count; i++) { *dPtr++ = (ARGBPixel)(*sPtr++); } break; } case WiiColorComponentType.RGBA8: { wRGBAPixel *sPtr = (wRGBAPixel *)colors->Data; for (int i = 0; i < count; i++) { *dPtr++ = (ARGBPixel)(*sPtr++); } break; } } } return(c); }
internal unsafe void Render(GLContext context, uint[] texIds) { if (!_enabled) { return; } //context.glEnable(GLEnableCap.Texture2D); if (_parent._uvData[0] == null) { return; } //Vector3* vPtr = (Vector3*)_parent._vertices.Address; //Vector3* nPtr = _parent._normals != null ? (Vector3*)_parent._normals.Address : null; ARGBPixel *c1Ptr = _parent._colors1 != null ? (ARGBPixel *)_parent._colors1.Address : null; ARGBPixel *c2Ptr = _parent._colors2 != null ? (ARGBPixel *)_parent._colors2.Address : null; //Vector2* uvPtr = _parent._uvData[0] != null ? (Vector2*)_parent._uvData[0].Address : null; int numUV = 0; Vector2 *[] uPtrs = new Vector2 *[8]; while (_parent._uvData[numUV] != null) { uPtrs[numUV] = (Vector2 *)_parent._uvData[numUV].Address; numUV++; } Vector3 v, n; Vector2 u; uint id; fixed(Vector3 *vPtr = _vertices) fixed(Vector3 * nPtr = _normals) { for (int t = 0; t < 1; t++) { if ((id = texIds[t]) == 0) { continue; } context.glBindTexture(GLTextureTarget.Texture2D, id); context.glBegin(_type); for (int i = 0; i < _elements; i++) { if (c1Ptr != null) { context.glColor4((byte *)&c1Ptr[_colorIndices[0][i]]); } //if(c2Ptr != null) // context.glColor4((byte*)&c2Ptr[_colorIndices[1][i]]); context.glNormal((float *)&nPtr[i]); context.glTexCoord2((float *)&uPtrs[0][_uvIndices[0][i]]); //u = uPtrs[t][_uvIndices[t][i]]; //context.glTexCoord2((float*)&u); context.glVertex3v((float *)&vPtr[i]); } context.glEnd(); } } context.CheckErrors(); }