static private byte[] convertToFormat(PixelFormat srcFormat, byte[] src, int w, int h, PixelFormat dstFormat, bool dxt1HasAlpha = false, byte dxt1Threshold = 128) { byte[] tempData; switch (dstFormat) { case PixelFormat.DXT1: case PixelFormat.DXT3: case PixelFormat.DXT5: case PixelFormat.ATI2: tempData = convertRawToARGB(src, w, h, srcFormat); if (dstFormat == PixelFormat.ATI2 && (w < 4 || h < 4)) { tempData = new byte[MipMap.getBufferSize(w, h, dstFormat)]; } else if (w < 4 || h < 4) { if (w < 4) { w = 4; } if (h < 4) { h = 4; } tempData = new byte[MipMap.getBufferSize(w, h, dstFormat)]; } else { tempData = compressMipmap(dstFormat, tempData, w, h, dxt1HasAlpha, dxt1Threshold); } break; case PixelFormat.ARGB: tempData = convertRawToARGB(src, w, h, srcFormat); break; case PixelFormat.RGB: tempData = convertRawToRGB(src, w, h, srcFormat); break; case PixelFormat.V8U8: tempData = convertRawToARGB(src, w, h, srcFormat); tempData = ARGBtoV8U8(tempData, w, h); break; case PixelFormat.G8: tempData = convertRawToARGB(src, w, h, srcFormat); tempData = ARGBtoG8(tempData, w, h); break; default: throw new Exception("not supported format"); } return(tempData); }
public void StoreImageToDDS(Stream stream, PixelFormat format = PixelFormat.Unknown) { stream.WriteUInt32(DDS_TAG); stream.WriteInt32(DDS_HEADER_dwSize); stream.WriteUInt32(DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_MIPMAPCOUNT | DDSD_PIXELFORMAT | DDSD_LINEARSIZE); stream.WriteInt32(mipMaps[0].height); stream.WriteInt32(mipMaps[0].width); int dataSize = 0; for (int i = 0; i < mipMaps.Count; i++) { dataSize += MipMap.getBufferSize(mipMaps[i].width, mipMaps[i].height, format == PixelFormat.Unknown ? pixelFormat : format); } stream.WriteInt32(dataSize); stream.WriteUInt32(0); // dwDepth stream.WriteInt32(mipMaps.Count); stream.WriteZeros(44); // dwReserved1 stream.WriteInt32(DDS_PIXELFORMAT_dwSize); DDS_PF pixfmt = getDDSPixelFormat(format == PixelFormat.Unknown ? pixelFormat: format); stream.WriteUInt32(pixfmt.flags); stream.WriteUInt32(pixfmt.fourCC); stream.WriteUInt32(pixfmt.bits); stream.WriteUInt32(pixfmt.Rmask); stream.WriteUInt32(pixfmt.Gmask); stream.WriteUInt32(pixfmt.Bmask); stream.WriteUInt32(pixfmt.Amask); stream.WriteInt32(DDSCAPS_COMPLEX | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE); stream.WriteUInt32(0); // dwCaps2 stream.WriteUInt32(0); // dwCaps3 stream.WriteUInt32(0); // dwCaps4 stream.WriteUInt32(0); // dwReserved2 for (int i = 0; i < mipMaps.Count; i++) { stream.WriteFromBuffer(mipMaps[i].data); } }
public void correctMips(PixelFormat dstFormat, bool dxt1HasAlpha = false, byte dxt1Threshold = 128) { byte[] tempData; if (pixelFormat != PixelFormat.ARGB) { tempData = convertRawToARGB(mipMaps[0].data, mipMaps[0].width, mipMaps[0].height, pixelFormat); } else { tempData = mipMaps[0].data; } int width = mipMaps[0].origWidth; int height = mipMaps[0].origHeight; if (mipMaps.Count > 1) { mipMaps.RemoveRange(1, mipMaps.Count - 1); } if (dstFormat != pixelFormat || (dstFormat == PixelFormat.DXT1 && !dxt1HasAlpha)) { byte[] top = convertToFormat(PixelFormat.ARGB, tempData, width, height, dstFormat, dxt1HasAlpha, dxt1Threshold); mipMaps.RemoveAt(0); mipMaps.Add(new MipMap(top, width, height, dstFormat)); pixelFormat = dstFormat; } int prevW, prevH; int origW = width; int origH = height; for (;;) { prevW = width; prevH = height; origW >>= 1; origH >>= 1; if (origW == 0 && origH == 0) { break; } if (origW == 0) { origW = 1; } if (origH == 0) { origH = 1; } width = origW; height = origH; if (pixelFormat == PixelFormat.ATI2 && (width < 4 || height < 4)) { tempData = new byte[MipMap.getBufferSize(width, height, dstFormat)]; mipMaps.Add(new MipMap(tempData, width, height, pixelFormat)); continue; } if (pixelFormat == PixelFormat.DXT1 || pixelFormat == PixelFormat.DXT3 || pixelFormat == PixelFormat.DXT5) { if (width < 4 || height < 4) { if (width < 4) { width = 4; } if (height < 4) { height = 4; } tempData = new byte[MipMap.getBufferSize(width, height, dstFormat)]; mipMaps.Add(new MipMap(tempData, origW, origH, pixelFormat)); continue; } } tempData = downscaleARGB(tempData, prevW, prevH); if (pixelFormat != PixelFormat.ARGB) { byte[] converted = convertToFormat(PixelFormat.ARGB, tempData, origW, origH, pixelFormat, dxt1HasAlpha, dxt1Threshold); mipMaps.Add(new MipMap(converted, origW, origH, pixelFormat)); } else { mipMaps.Add(new MipMap(tempData, origW, origH, pixelFormat)); } } }
private void LoadImageDDS(MemoryStream stream, ImageFormat format) { if (stream.ReadUInt32() != DDS_TAG) { throw new Exception("not DDS tag"); } if (stream.ReadInt32() != DDS_HEADER_dwSize) { throw new Exception("wrong DDS header dwSize"); } DDSflags = stream.ReadUInt32(); int dwHeight = stream.ReadInt32(); int dwWidth = stream.ReadInt32(); if (!checkPowerOfTwo(dwWidth) || !checkPowerOfTwo(dwHeight)) { throw new Exception("dimensions not power of two"); } stream.Skip(8); // dwPitchOrLinearSize, dwDepth int dwMipMapCount = stream.ReadInt32(); if (dwMipMapCount == 0) { dwMipMapCount = 1; } stream.Skip(11 * 4); // dwReserved1 stream.SkipInt32(); // ppf.dwSize ddsPixelFormat.flags = stream.ReadUInt32(); ddsPixelFormat.fourCC = stream.ReadUInt32(); if ((ddsPixelFormat.flags & DDPF_FOURCC) != 0 && ddsPixelFormat.fourCC == FOURCC_DX10_TAG) { throw new Exception("DX10 DDS format not supported"); } ddsPixelFormat.bits = stream.ReadUInt32(); ddsPixelFormat.Rmask = stream.ReadUInt32(); ddsPixelFormat.Gmask = stream.ReadUInt32(); ddsPixelFormat.Bmask = stream.ReadUInt32(); ddsPixelFormat.Amask = stream.ReadUInt32(); switch (ddsPixelFormat.fourCC) { case 0: if (ddsPixelFormat.bits == 32 && (ddsPixelFormat.flags & DDPF_ALPHAPIXELS) != 0 && ddsPixelFormat.Rmask == 0xFF0000 && ddsPixelFormat.Gmask == 0xFF00 && ddsPixelFormat.Bmask == 0xFF && ddsPixelFormat.Amask == 0xFF000000) { pixelFormat = PixelFormat.ARGB; break; } if (ddsPixelFormat.bits == 24 && ddsPixelFormat.Rmask == 0xFF0000 && ddsPixelFormat.Gmask == 0xFF00 && ddsPixelFormat.Bmask == 0xFF) { pixelFormat = PixelFormat.RGB; break; } if (ddsPixelFormat.bits == 16 && ddsPixelFormat.Rmask == 0xFF && ddsPixelFormat.Gmask == 0xFF00 && ddsPixelFormat.Bmask == 0x00) { pixelFormat = PixelFormat.V8U8; break; } if (ddsPixelFormat.bits == 8 && ddsPixelFormat.Rmask == 0xFF && ddsPixelFormat.Gmask == 0x00 && ddsPixelFormat.Bmask == 0x00) { pixelFormat = PixelFormat.G8; break; } throw new Exception("Not supported DDS format"); case 21: pixelFormat = PixelFormat.ARGB; break; case 20: pixelFormat = PixelFormat.RGB; break; case 60: pixelFormat = PixelFormat.V8U8; break; case 50: pixelFormat = PixelFormat.G8; break; case FOURCC_DXT1_TAG: pixelFormat = PixelFormat.DXT1; break; case FOURCC_DXT3_TAG: pixelFormat = PixelFormat.DXT3; break; case FOURCC_DXT5_TAG: pixelFormat = PixelFormat.DXT5; break; case FOURCC_ATI2_TAG: pixelFormat = PixelFormat.ATI2; break; default: throw new Exception("Not supported DDS format"); } stream.Skip(5 * 4); // dwCaps, dwCaps2, dwCaps3, dwCaps4, dwReserved2 byte[] tempData; for (int i = 0; i < dwMipMapCount; i++) { int w = dwWidth >> i; int h = dwHeight >> i; int origW = w; int origH = h; if (origW == 0 && origH != 0) { origW = 1; } if (origH == 0 && origW != 0) { origH = 1; } w = origW; h = origH; if (pixelFormat == PixelFormat.DXT1 || pixelFormat == PixelFormat.DXT3 || pixelFormat == PixelFormat.DXT5) { if (w < 4) { w = 4; } if (h < 4) { h = 4; } } try { tempData = stream.ReadToBuffer(MipMap.getBufferSize(w, h, pixelFormat)); } catch { throw new Exception("not enough data in stream"); } mipMaps.Add(new MipMap(tempData, origW, origH, pixelFormat)); } }