private static SubStream GetChunkData(SubStream data, long offset) { int totalsize = (((12 + (int)data.GetByte(offset + 6) + 7) & -8) + data.GetInt32(offset + 8) + 7) & -8; return new SubStream(data, offset, totalsize); }
private static SubStream GetChunkData(SubStream data, long offset) { int totalsize = (((12 + (int)data.GetByte(offset + 6) + 7) & -8) + data.GetInt32(offset + 8) + 7) & -8; return(new SubStream(data, offset, totalsize)); }
public DDSImage(SubStream data) { if (data.GetByte(0) == 'D' && data.GetByte(1) == 'D' && data.GetByte(2) == 'S' && data.GetByte(3) == ' ') { Height = data.GetInt32(12); Width = data.GetInt32(16); Depth = data.GetInt32(24); Flags = data.GetUInt32(8); Pitch = data.GetInt32(20); FourCC = Encoding.ASCII.GetString(data.GetBytes(84, 4)); RGBBitCount = data.GetInt32(88); RedMask = data.GetUInt32(92); GreenMask = data.GetUInt32(96); BlueMask = data.GetUInt32(100); AlphaMask = data.GetUInt32(104); Data = data; ImageOffset = 128; if (Depth == 0) { Depth = 1; } if ((Flags & 8) == 0) { Pitch = Width * RGBBitCount / 8; } IsARGB32 = (FourCC == "DXT1" || FourCC == "DXT2" || FourCC == "DXT3" || FourCC == "DXT4" || FourCC == "DXT5" || FourCC == "\0\0\0\0"); IntensityFactor = 1.0; try { FailureReason = null; switch (FourCC) { case "DXT1": Bitmap = GetBitmapFromDDS_DXT1(Data, ImageOffset, Width, Height, out HasAlpha); break; case "DXT2": Bitmap = GetBitmapFromDDS_DXT3(Data, ImageOffset, Width, Height, true, out HasAlpha); break; case "DXT3": Bitmap = GetBitmapFromDDS_DXT3(Data, ImageOffset, Width, Height, false, out HasAlpha); break; case "DXT4": Bitmap = GetBitmapFromDDS_DXT5(Data, ImageOffset, Width, Height, true, out HasAlpha); break; case "DXT5": Bitmap = GetBitmapFromDDS_DXT5(Data, ImageOffset, Width, Height, false, out HasAlpha); break; case "\0\0\0\0": Bitmap = GetBitmapFromDDS_RAW(Data, ImageOffset, Width, Height, Pitch, RGBBitCount, RedMask, GreenMask, BlueMask, AlphaMask, out HasAlpha, out IsARGB32); break; case "q\0\0\0": Bitmap = GetBitmapFromDDS_ARGB16F(Data, ImageOffset, Width, Height, out HasAlpha, out IntensityFactor); break; default: Bitmap = null; FailureReason = String.Format("Unknown DDS FourCC {0:X2}:{1:X2}:{2:X2}:{3:X2}", Data.GetByte(84), Data.GetByte(85), Data.GetByte(86), Data.GetByte(87)); break; } } catch (Exception ex) { Bitmap = null; FailureReason = ex.Message; } } else { throw new NotImplementedException(String.Format("Unknown file format {0:X2}:{1:X2}:{2:X2}:{3:X2}", data.GetByte(0), data.GetByte(1), data.GetByte(2), data.GetByte(3))); } }
protected static Bitmap GetBitmapFromDDS_DXT5(SubStream data, int offset, int width, int height, bool IsDXT4, out bool hasalpha) { Bitmap bmp = new Bitmap(width, height, IsDXT4 ? PixelFormat.Format32bppPArgb : PixelFormat.Format32bppArgb); byte[] bmpraw = new byte[width * height * 4]; hasalpha = false; for (int y = 0; y < height; y += 4) { for (int x = 0; x < width; x += 4) { byte[] a = new byte[8]; a[0] = data.GetByte(offset); a[1] = data.GetByte(offset + 1); if (a[0] > a[1]) { a[2] = (byte)(((int)a[0] * 6 + a[1] * 1 + 3) / 7); a[3] = (byte)(((int)a[0] * 5 + a[1] * 2 + 3) / 7); a[4] = (byte)(((int)a[0] * 4 + a[1] * 3 + 3) / 7); a[5] = (byte)(((int)a[0] * 3 + a[1] * 4 + 3) / 7); a[6] = (byte)(((int)a[0] * 2 + a[1] * 5 + 3) / 7); a[7] = (byte)(((int)a[0] * 1 + a[1] * 6 + 3) / 7); } else { a[2] = (byte)(((int)a[0] * 4 + a[1] * 1 + 2) / 5); a[3] = (byte)(((int)a[0] * 3 + a[1] * 2 + 2) / 5); a[4] = (byte)(((int)a[0] * 2 + a[1] * 3 + 2) / 5); a[5] = (byte)(((int)a[0] * 1 + a[1] * 4 + 2) / 5); a[6] = 0x00; a[7] = 0xFF; } ulong alphasel = data.GetUInt64(offset) >> 16; byte[,] alphadata = new byte[4, 4]; for (int i = 0; i < 16; i++) { alphadata[i % 4, i / 4] = a[(alphasel >> (i * 3)) & 7]; } Color[,] colourdata = GetDXT1ColourBlock(data, offset + 8, true); for (int v = 0; v < 4; v++) { for (int u = 0; u < 4; u++) { if (x + u < width && y + v < height) { int i = ((y + v) * width + (x + u)) * 4; bmpraw[i] = colourdata[u, v].B; bmpraw[i + 1] = colourdata[u, v].G; bmpraw[i + 2] = colourdata[u, v].R; bmpraw[i + 3] = alphadata[u, v]; hasalpha |= alphadata[u, v] != 255; } } } offset += 16; } } BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, IsDXT4 ? PixelFormat.Format32bppPArgb : PixelFormat.Format32bppArgb); for (int y = 0; y < height; y++) { Marshal.Copy(bmpraw, y * width * 4, bmpdata.Scan0 + y * bmpdata.Stride, width * 4); } bmp.UnlockBits(bmpdata); return bmp; }
protected static Bitmap GetBitmapFromDDS_DXT5(SubStream data, int offset, int width, int height, bool IsDXT4, out bool hasalpha) { Bitmap bmp = new Bitmap(width, height, IsDXT4 ? PixelFormat.Format32bppPArgb : PixelFormat.Format32bppArgb); byte[] bmpraw = new byte[width * height * 4]; hasalpha = false; for (int y = 0; y < height; y += 4) { for (int x = 0; x < width; x += 4) { byte[] a = new byte[8]; a[0] = data.GetByte(offset); a[1] = data.GetByte(offset + 1); if (a[0] > a[1]) { a[2] = (byte)(((int)a[0] * 6 + a[1] * 1 + 3) / 7); a[3] = (byte)(((int)a[0] * 5 + a[1] * 2 + 3) / 7); a[4] = (byte)(((int)a[0] * 4 + a[1] * 3 + 3) / 7); a[5] = (byte)(((int)a[0] * 3 + a[1] * 4 + 3) / 7); a[6] = (byte)(((int)a[0] * 2 + a[1] * 5 + 3) / 7); a[7] = (byte)(((int)a[0] * 1 + a[1] * 6 + 3) / 7); } else { a[2] = (byte)(((int)a[0] * 4 + a[1] * 1 + 2) / 5); a[3] = (byte)(((int)a[0] * 3 + a[1] * 2 + 2) / 5); a[4] = (byte)(((int)a[0] * 2 + a[1] * 3 + 2) / 5); a[5] = (byte)(((int)a[0] * 1 + a[1] * 4 + 2) / 5); a[6] = 0x00; a[7] = 0xFF; } ulong alphasel = data.GetUInt64(offset) >> 16; byte[,] alphadata = new byte[4, 4]; for (int i = 0; i < 16; i++) { alphadata[i % 4, i / 4] = a[(alphasel >> (i * 3)) & 7]; } Color[,] colourdata = GetDXT1ColourBlock(data, offset + 8, true); for (int v = 0; v < 4; v++) { for (int u = 0; u < 4; u++) { if (x + u < width && y + v < height) { int i = ((y + v) * width + (x + u)) * 4; bmpraw[i] = colourdata[u, v].B; bmpraw[i + 1] = colourdata[u, v].G; bmpraw[i + 2] = colourdata[u, v].R; bmpraw[i + 3] = alphadata[u, v]; hasalpha |= alphadata[u, v] != 255; } } } offset += 16; } } BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, IsDXT4 ? PixelFormat.Format32bppPArgb : PixelFormat.Format32bppArgb); for (int y = 0; y < height; y++) { Marshal.Copy(bmpraw, y * width * 4, bmpdata.Scan0 + y * bmpdata.Stride, width * 4); } bmp.UnlockBits(bmpdata); return(bmp); }