public void Load(Stream input) { uint num = (uint)input.ReadUInt32(); if (num != 0x20534444) { throw new FormatException("File does not appear to be a DDS image"); } this.m_header.Read(input); if ((this.m_header.m_pixelFormat.m_flags != 0) && ((this.m_header.m_pixelFormat.m_flags & 4) == 0)) { DdsFileFormat format; if ((((this.m_header.m_pixelFormat.m_flags == 0x41) && (this.m_header.m_pixelFormat.m_rgbBitCount == 0x20)) && ((this.m_header.m_pixelFormat.m_rBitMask == 0xff0000) && (this.m_header.m_pixelFormat.m_gBitMask == 0xff00))) && ((this.m_header.m_pixelFormat.m_bBitMask == 0xff) && (this.m_header.m_pixelFormat.m_aBitMask == 0xff000000))) { format = DdsFileFormat.DDS_FORMAT_A8R8G8B8; } else if ((((this.m_header.m_pixelFormat.m_flags == 0x40) && (this.m_header.m_pixelFormat.m_rgbBitCount == 0x20)) && ((this.m_header.m_pixelFormat.m_rBitMask == 0xff0000) && (this.m_header.m_pixelFormat.m_gBitMask == 0xff00))) && ((this.m_header.m_pixelFormat.m_bBitMask == 0xff) && (this.m_header.m_pixelFormat.m_aBitMask == 0))) { format = DdsFileFormat.DDS_FORMAT_X8R8G8B8; } else if ((((this.m_header.m_pixelFormat.m_flags == 0x41) && (this.m_header.m_pixelFormat.m_rgbBitCount == 0x20)) && ((this.m_header.m_pixelFormat.m_rBitMask == 0xff) && (this.m_header.m_pixelFormat.m_gBitMask == 0xff00))) && ((this.m_header.m_pixelFormat.m_bBitMask == 0xff0000) && (this.m_header.m_pixelFormat.m_aBitMask == 0xff000000))) { format = DdsFileFormat.DDS_FORMAT_A8B8G8R8; } else if ((((this.m_header.m_pixelFormat.m_flags == 0x40) && (this.m_header.m_pixelFormat.m_rgbBitCount == 0x20)) && ((this.m_header.m_pixelFormat.m_rBitMask == 0xff) && (this.m_header.m_pixelFormat.m_gBitMask == 0xff00))) && ((this.m_header.m_pixelFormat.m_bBitMask == 0xff0000) && (this.m_header.m_pixelFormat.m_aBitMask == 0))) { format = DdsFileFormat.DDS_FORMAT_X8B8G8R8; } else if ((((this.m_header.m_pixelFormat.m_flags == 0x41) && (this.m_header.m_pixelFormat.m_rgbBitCount == 0x10)) && ((this.m_header.m_pixelFormat.m_rBitMask == 0x7c00) && (this.m_header.m_pixelFormat.m_gBitMask == 0x3e0))) && ((this.m_header.m_pixelFormat.m_bBitMask == 0x1f) && (this.m_header.m_pixelFormat.m_aBitMask == 0x8000))) { format = DdsFileFormat.DDS_FORMAT_A1R5G5B5; } else if ((((this.m_header.m_pixelFormat.m_flags == 0x41) && (this.m_header.m_pixelFormat.m_rgbBitCount == 0x10)) && ((this.m_header.m_pixelFormat.m_rBitMask == 0xf00) && (this.m_header.m_pixelFormat.m_gBitMask == 240))) && ((this.m_header.m_pixelFormat.m_bBitMask == 15) && (this.m_header.m_pixelFormat.m_aBitMask == 0xf000))) { format = DdsFileFormat.DDS_FORMAT_A4R4G4B4; } else if ((((this.m_header.m_pixelFormat.m_flags == 0x40) && (this.m_header.m_pixelFormat.m_rgbBitCount == 0x18)) && ((this.m_header.m_pixelFormat.m_rBitMask == 0xff0000) && (this.m_header.m_pixelFormat.m_gBitMask == 0xff00))) && ((this.m_header.m_pixelFormat.m_bBitMask == 0xff) && (this.m_header.m_pixelFormat.m_aBitMask == 0))) { format = DdsFileFormat.DDS_FORMAT_R8G8B8; } else { if ((((this.m_header.m_pixelFormat.m_flags != 0x40) || (this.m_header.m_pixelFormat.m_rgbBitCount != 0x10)) || ((this.m_header.m_pixelFormat.m_rBitMask != 0xf800) || (this.m_header.m_pixelFormat.m_gBitMask != 0x7e0))) || ((this.m_header.m_pixelFormat.m_bBitMask != 0x1f) || (this.m_header.m_pixelFormat.m_aBitMask != 0))) { throw new FormatException("File is not a supported DDS format"); } format = DdsFileFormat.DDS_FORMAT_R5G6B5; } int num6 = (int)(this.m_header.m_pixelFormat.m_rgbBitCount / 8); int pitchOrLinearSize = 0; if ((this.m_header.m_headerFlags & 8) != 0) { pitchOrLinearSize = (int)this.m_header.m_pitchOrLinearSize; } else if ((this.m_header.m_headerFlags & 0x80000) != 0) { pitchOrLinearSize = (int)(this.m_header.m_pitchOrLinearSize / this.m_header.m_height); } else { pitchOrLinearSize = (int)(this.m_header.m_width * num6); } byte[] buffer2 = new byte[pitchOrLinearSize * this.m_header.m_height]; input.Read(buffer2, 0, buffer2.GetLength(0)); this.m_pixelData = new byte[(this.m_header.m_width * this.m_header.m_height) * 4]; for (int i = 0; i < this.m_header.m_height; i++) { for (int j = 0; j < this.m_header.m_width; j++) { int num10 = (i * pitchOrLinearSize) + (j * num6); uint num11 = 0; uint num12 = 0; uint num13 = 0; uint num14 = 0; uint num15 = 0; for (int k = 0; k < num6; k++) { num11 |= (uint)(buffer2[num10 + k] << (8 * k)); } switch (format) { case DdsFileFormat.DDS_FORMAT_A8R8G8B8: num15 = (num11 >> 0x18) & 0xff; num12 = (num11 >> 0x10) & 0xff; num13 = (num11 >> 8) & 0xff; num14 = num11 & 0xff; break; case DdsFileFormat.DDS_FORMAT_X8R8G8B8: num15 = 0xff; num12 = (num11 >> 0x10) & 0xff; num13 = (num11 >> 8) & 0xff; num14 = num11 & 0xff; break; case DdsFileFormat.DDS_FORMAT_A8B8G8R8: num15 = (num11 >> 0x18) & 0xff; num12 = num11 & 0xff; num13 = (num11 >> 8) & 0xff; num14 = (num11 >> 0x10) & 0xff; break; case DdsFileFormat.DDS_FORMAT_X8B8G8R8: num15 = 0xff; num12 = num11 & 0xff; num13 = (num11 >> 8) & 0xff; num14 = (num11 >> 0x10) & 0xff; break; case DdsFileFormat.DDS_FORMAT_A1R5G5B5: num15 = (num11 >> 15) * 0xff; num12 = (num11 >> 10) & 0x1f; num13 = (num11 >> 5) & 0x1f; num14 = num11 & 0x1f; num12 = (num12 << 3) | (num12 >> 2); num13 = (num13 << 3) | (num13 >> 2); num14 = (num14 << 3) | (num14 >> 2); break; case DdsFileFormat.DDS_FORMAT_A4R4G4B4: num15 = (num11 >> 12) & 0xff; num12 = (num11 >> 8) & 15; num13 = (num11 >> 4) & 15; num14 = num11 & 15; num15 = (num15 << 4) | num15; num12 = (num12 << 4) | num12; num13 = (num13 << 4) | num13; num14 = (num14 << 4) | num14; break; case DdsFileFormat.DDS_FORMAT_R8G8B8: num15 = 0xff; num12 = (num11 >> 0x10) & 0xff; num13 = (num11 >> 8) & 0xff; num14 = num11 & 0xff; break; case DdsFileFormat.DDS_FORMAT_R5G6B5: num15 = 0xff; num12 = (num11 >> 11) & 0x1f; num13 = (num11 >> 5) & 0x3f; num14 = num11 & 0x1f; num12 = (num12 << 3) | (num12 >> 2); num13 = (num13 << 2) | (num13 >> 4); num14 = (num14 << 3) | (num14 >> 2); break; } int index = ((int)((i * this.m_header.m_width) * 4)) + (j * 4); this.m_pixelData[index] = (byte)num12; this.m_pixelData[index + 1] = (byte)num13; this.m_pixelData[index + 2] = (byte)num14; this.m_pixelData[index + 3] = (byte)num15; } } } else { int flags = 0; switch (this.m_header.m_pixelFormat.m_fourCC) { case 0x31545844: flags = 1; break; case 0x33545844: flags = 2; break; case 0x35545844: flags = 4; break; default: throw new FormatException("File is not a supported DDS format"); } int num3 = ((this.GetWidth() + 3) / 4) * ((this.GetHeight() + 3) / 4); int num4 = ((flags & 1) != 0) ? 8 : 0x10; byte[] buffer = new byte[num3 * num4]; input.Read(buffer, 0, buffer.GetLength(0)); this.m_pixelData = DdsSquish.DecompressImage(buffer, this.GetWidth(), this.GetHeight(), flags); } }
public void Save(Stream output, Surface surface, DdsFileFormat fileFormat, DdsCompressorType compressorType, DdsErrorMetric errorMetric, bool generateMipMaps, ResamplingAlgorithm mipMapResamplingAlgorithm, bool weightColorByAlpha, ProgressEventHandler progressCallback) { int num21; int num = 0; bool flag = ((fileFormat == DdsFileFormat.DDS_FORMAT_DXT1) || (fileFormat == DdsFileFormat.DDS_FORMAT_DXT3)) || (fileFormat == DdsFileFormat.DDS_FORMAT_DXT5); int num2 = 1; int mipWidth = surface.Width; int height = surface.Height; if (generateMipMaps) { while ((mipWidth > 1) || (height > 1)) { num2++; mipWidth /= 2; height /= 2; } } this.m_header.m_size = this.m_header.Size(); this.m_header.m_headerFlags = 0x1007; if (flag) { this.m_header.m_headerFlags |= 0x80000; } else { this.m_header.m_headerFlags |= 8; } if (num2 > 1) { this.m_header.m_headerFlags |= 0x20000; } this.m_header.m_height = (uint)surface.Height; this.m_header.m_width = (uint)surface.Width; if (flag) { int num5 = ((surface.Width + 3) / 4) * ((surface.Height + 3) / 4); int num6 = (fileFormat == DdsFileFormat.DDS_FORMAT_DXT1) ? 8 : 0x10; this.m_header.m_pitchOrLinearSize = (uint)(num5 * num6); } else { switch (fileFormat) { case DdsFileFormat.DDS_FORMAT_A8R8G8B8: case DdsFileFormat.DDS_FORMAT_X8R8G8B8: case DdsFileFormat.DDS_FORMAT_A8B8G8R8: case DdsFileFormat.DDS_FORMAT_X8B8G8R8: num = 4; break; case DdsFileFormat.DDS_FORMAT_A1R5G5B5: case DdsFileFormat.DDS_FORMAT_A4R4G4B4: case DdsFileFormat.DDS_FORMAT_R5G6B5: num = 2; break; case DdsFileFormat.DDS_FORMAT_R8G8B8: num = 3; break; } this.m_header.m_pitchOrLinearSize = (uint)(this.m_header.m_width * num); } this.m_header.m_depth = 0; this.m_header.m_mipMapCount = (num2 == 1) ? 0 : ((uint)num2); this.m_header.m_reserved1_0 = 0; this.m_header.m_reserved1_1 = 0; this.m_header.m_reserved1_2 = 0; this.m_header.m_reserved1_3 = 0; this.m_header.m_reserved1_4 = 0; this.m_header.m_reserved1_5 = 0; this.m_header.m_reserved1_6 = 0; this.m_header.m_reserved1_7 = 0; this.m_header.m_reserved1_8 = 0; this.m_header.m_reserved1_9 = 0; this.m_header.m_reserved1_10 = 0; this.m_header.m_pixelFormat.Initialise(fileFormat); this.m_header.m_surfaceFlags = 0x1000; if (num2 > 1) { this.m_header.m_surfaceFlags |= 0x400008; } this.m_header.m_cubemapFlags = 0; this.m_header.m_reserved2_0 = 0; this.m_header.m_reserved2_1 = 0; this.m_header.m_reserved2_2 = 0; output.WriteUInt32(0x20534444); this.m_header.Write(output); int squishFlags = this.GetSquishFlags(fileFormat, compressorType, errorMetric, weightColorByAlpha); mipWidth = surface.Width; height = surface.Height; SizeInt32[] numArray = new SizeInt32[num2]; int[] numArray2 = new int[num2]; int[] pixelsCompleted = new int[num2]; long totalPixels = 0L; for (int i = 0; i < num2; i++) { SizeInt32 num8 = new SizeInt32((mipWidth > 0) ? mipWidth : 1, (height > 0) ? height : 1); numArray[i] = num8; int num9 = num8.Width * num8.Height; numArray2[i] = num9; if (i == 0) { pixelsCompleted[i] = 0; } else { pixelsCompleted[i] = pixelsCompleted[i - 1] + numArray2[i - 1]; } totalPixels += num9; mipWidth /= 2; height /= 2; } mipWidth = surface.Width; height = surface.Height; for (int mipLoop = 0; mipLoop < num2; mipLoop = num21 + 1) { byte[] buffer; SizeInt32 size = numArray[mipLoop]; Surface surface2 = new Surface(size); if (mipLoop == 0) { surface2 = surface; } else { IRenderer <ColorBgra> renderer; SizeInt32 newSize = surface2.Size <ColorBgra>(); switch (mipMapResamplingAlgorithm) { case ResamplingAlgorithm.NearestNeighbor: renderer = surface.ResizeNearestNeighbor(newSize); break; case ResamplingAlgorithm.Bilinear: renderer = surface.ResizeBilinear(newSize); break; case ResamplingAlgorithm.Bicubic: renderer = surface.ResizeBicubic(newSize); break; case ResamplingAlgorithm.SuperSampling: renderer = surface.ResizeSuperSampling(newSize); break; case ResamplingAlgorithm.Fant: renderer = surface.ResizeFant(newSize); break; default: throw ExceptionUtil.InvalidEnumArgumentException <ResamplingAlgorithm>(mipMapResamplingAlgorithm, "mipMapResamplingAlgorithm"); } renderer.Render <ColorBgra>(surface2); } DdsSquish.ProgressFn fn = delegate(int workDone, int workTotal) { long num = workDone * mipWidth; long num2 = pixelsCompleted[mipLoop]; double num3 = (num + num2) / ((double)totalPixels); progressCallback(this, new ProgressEventArgs(DoubleUtil.Clamp(100.0 * num3, 0.0, 100.0))); }; if ((fileFormat >= DdsFileFormat.DDS_FORMAT_DXT1) && (fileFormat <= DdsFileFormat.DDS_FORMAT_DXT5)) { buffer = DdsSquish.CompressImage(surface2, squishFlags, (progressCallback == null) ? null : fn); } else { int num12 = num * surface2.Width; buffer = new byte[num12 * surface2.Height]; buffer.Initialize(); for (int j = 0; j < surface2.Height; j++) { for (int k = 0; k < surface2.Width; k++) { ColorBgra point = surface2.GetPoint(k, j); uint num15 = 0; switch (fileFormat) { case DdsFileFormat.DDS_FORMAT_A8R8G8B8: num15 = (uint)((((point.A << 0x18) | (point.R << 0x10)) | (point.G << 8)) | point.B); break; case DdsFileFormat.DDS_FORMAT_X8R8G8B8: num15 = (uint)(((point.R << 0x10) | (point.G << 8)) | point.B); break; case DdsFileFormat.DDS_FORMAT_A8B8G8R8: num15 = (uint)((((point.A << 0x18) | (point.B << 0x10)) | (point.G << 8)) | point.R); break; case DdsFileFormat.DDS_FORMAT_X8B8G8R8: num15 = (uint)(((point.B << 0x10) | (point.G << 8)) | point.R); break; case DdsFileFormat.DDS_FORMAT_A1R5G5B5: num15 = (uint)((((((point.A != null) ? 1 : 0) << 15) | ((point.R >> 3) << 10)) | ((point.G >> 3) << 5)) | (point.B >> 3)); break; case DdsFileFormat.DDS_FORMAT_A4R4G4B4: num15 = (uint)(((((point.A >> 4) << 12) | ((point.R >> 4) << 8)) | ((point.G >> 4) << 4)) | (point.B >> 4)); break; case DdsFileFormat.DDS_FORMAT_R8G8B8: num15 = (uint)(((point.R << 0x10) | (point.G << 8)) | point.B); break; case DdsFileFormat.DDS_FORMAT_R5G6B5: num15 = (uint)((((point.R >> 3) << 11) | ((point.G >> 2) << 5)) | (point.B >> 3)); break; } int num16 = (j * num12) + (k * num); for (int m = 0; m < num; m++) { buffer[num16 + m] = (byte)((num15 >> (8 * m)) & 0xff); } } if (progressCallback != null) { long num18 = (j + 1) * mipWidth; long num19 = pixelsCompleted[mipLoop]; double num20 = (num18 + num19) / ((double)totalPixels); progressCallback(this, new ProgressEventArgs(100.0 * num20)); } } } output.Write(buffer, 0, buffer.GetLength(0)); mipWidth /= 2; height /= 2; num21 = mipLoop; } }