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); }
private void LoadImage(MemoryStream stream, ImageFormat format) { mipMaps = new List <MipMap>(); switch (format) { case ImageFormat.DDS: { LoadImageDDS(stream); break; } case ImageFormat.TGA: { LoadImageTGA(stream); break; } case ImageFormat.BMP: { LoadImageBMP(stream); break; } case ImageFormat.PNG: case ImageFormat.JPEG: { BitmapSource frame = format == ImageFormat.PNG ? new PngBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.Default).Frames[0] : new JpegBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.Default).Frames[0]; if (!IsPowerOfTwo(frame.PixelWidth) || !IsPowerOfTwo(frame.PixelHeight)) { throw new TextureSizeNotPowerOf2Exception(); } FormatConvertedBitmap srcBitmap = new FormatConvertedBitmap(); srcBitmap.BeginInit(); srcBitmap.Source = frame; srcBitmap.DestinationFormat = PixelFormats.Bgra32; srcBitmap.EndInit(); var pixels = new byte[srcBitmap.PixelWidth * srcBitmap.PixelHeight * 4]; frame.CopyPixels(pixels, srcBitmap.PixelWidth * 4, 0); pixelFormat = PixelFormat.ARGB; MipMap mipmap = new MipMap(pixels, srcBitmap.PixelWidth, srcBitmap.PixelHeight, PixelFormat.ARGB); mipMaps.Add(mipmap); break; } default: throw new Exception(); } }
public Image convertToRGB() { for (int i = 0; i < mipMaps.Count; i++) { mipMaps[i] = new MipMap(convertRawToRGB(mipMaps[i].data, mipMaps[i].width, mipMaps[i].height, pixelFormat), mipMaps[i].width, mipMaps[i].height, PixelFormat.RGB); } pixelFormat = PixelFormat.RGB; return(this); }
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); } }
private void LoadImageBMP(MemoryStream stream) { ushort tag = stream.ReadUInt16(); if (tag != BMP_TAG) { throw new Exception("not BMP header"); } stream.Skip(8); uint offsetData = stream.ReadUInt32(); int headerSize = stream.ReadInt32(); int imageWidth = stream.ReadInt32(); int imageHeight = stream.ReadInt32(); bool downToTop = true; if (imageHeight < 0) { imageHeight = -imageHeight; downToTop = false; } if (!IsPowerOfTwo(imageWidth) || !IsPowerOfTwo(imageHeight)) { throw new TextureSizeNotPowerOf2Exception(); } stream.Skip(2); int bits = stream.ReadUInt16(); if (bits != 32 && bits != 24) { throw new Exception("only 24 and 32 bits BMP supported!"); } bool hasAlphaMask = false; uint Rmask = 0xFF0000, Gmask = 0xFF00, Bmask = 0xFF, Amask = 0xFF000000; if (headerSize >= 40) { int compression = stream.ReadInt32(); if (compression == 1 || compression == 2) { throw new Exception("compression not supported in BMP!"); } if (compression == 3) { stream.Skip(20); Rmask = stream.ReadUInt32(); Gmask = stream.ReadUInt32(); Bmask = stream.ReadUInt32(); if (headerSize >= 56) { Amask = stream.ReadUInt32(); hasAlphaMask = true; } } stream.JumpTo(headerSize + 14); } int Rshift = getShiftFromMask(Rmask); int Gshift = getShiftFromMask(Gmask); int Bshift = getShiftFromMask(Bmask); int Ashift = getShiftFromMask(Amask); byte[] buffer = new byte[imageWidth * imageHeight * 4]; int pos = downToTop ? imageWidth * (imageHeight - 1) * 4 : 0; int delta = downToTop ? -imageWidth * 4 * 2 : 0; for (int h = 0; h < imageHeight; h++) { for (int i = 0; i < imageWidth; i++) { if (bits == 24) { buffer[pos++] = (byte)stream.ReadByte(); buffer[pos++] = (byte)stream.ReadByte(); buffer[pos++] = (byte)stream.ReadByte(); buffer[pos++] = 255; } else if (bits == 32) { uint p1 = (uint)stream.ReadByte(); uint p2 = (uint)stream.ReadByte(); uint p3 = (uint)stream.ReadByte(); uint p4 = (uint)stream.ReadByte(); uint pixel = p4 << 24 | p3 << 16 | p2 << 8 | p1; buffer[pos++] = (byte)((pixel & Bmask) >> Bshift); buffer[pos++] = (byte)((pixel & Gmask) >> Gshift); buffer[pos++] = (byte)((pixel & Rmask) >> Rshift); buffer[pos++] = (byte)((pixel & Amask) >> Ashift); } } if (imageWidth % 4 != 0) { stream.Skip(4 - (imageWidth % 4)); } pos += delta; } if (bits == 32 && !hasAlphaMask) { bool hasAlpha = false; for (int i = 0; i < imageWidth * imageHeight; i++) { if (buffer[4 * i + 3] != 0) { hasAlpha = true; break; } } if (!hasAlpha) { for (int i = 0; i < imageWidth * imageHeight; i++) { buffer[4 * i + 3] = 255; } } } pixelFormat = PixelFormat.ARGB; MipMap mipmap = new MipMap(buffer, imageWidth, imageHeight, PixelFormat.ARGB); mipMaps.Add(mipmap); }
private void LoadImageDDS(MemoryStream stream) { 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 (!IsPowerOfTwo(dwWidth) || !IsPowerOfTwo(dwHeight)) { throw new TextureSizeNotPowerOf2Exception(); } 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 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; } } byte[] tempData; 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)); } }
private void LoadImageTGA(MemoryStream stream) { int idLength = stream.ReadByte(); int colorMapType = stream.ReadByte(); if (colorMapType != 0) { throw new Exception("indexed TGA not supported!"); } int imageType = stream.ReadByte(); if (imageType != 2 && imageType != 10) { throw new Exception("only RGB TGA supported!"); } bool compressed = imageType == 10; stream.SkipInt16(); // color map first entry index stream.SkipInt16(); // color map length stream.Skip(1); // color map entry size stream.SkipInt16(); // x origin stream.SkipInt16(); // y origin int imageWidth = stream.ReadInt16(); int imageHeight = stream.ReadInt16(); if (!IsPowerOfTwo(imageWidth) || !IsPowerOfTwo(imageHeight)) { throw new TextureSizeNotPowerOf2Exception(); } int imageDepth = stream.ReadByte(); if (imageDepth != 32 && imageDepth != 24) { throw new Exception("only 24 and 32 bits TGA supported!"); } int imageDesc = stream.ReadByte(); if ((imageDesc & 0x10) != 0) { throw new Exception("origin right not supported in TGA!"); } bool downToTop = (imageDesc & 0x20) == 0; stream.Skip(idLength); byte[] buffer = new byte[imageWidth * imageHeight * 4]; int pos = downToTop ? imageWidth * (imageHeight - 1) * 4 : 0; int delta = downToTop ? -imageWidth * 4 * 2 : 0; if (compressed) { int count = 0, repeat = 0, w = 0, h = 0; for (; ;) { if (count == 0 && repeat == 0) { byte code = (byte)stream.ReadByte(); if ((code & 0x80) != 0) { repeat = (code & 0x7F) + 1; } else { count = code + 1; } } else { if (repeat != 0) { byte pixelR = (byte)stream.ReadByte(); byte pixelG = (byte)stream.ReadByte(); byte pixelB = (byte)stream.ReadByte(); byte pixelA; if (imageDepth == 32) { pixelA = (byte)stream.ReadByte(); } else { pixelA = 0xFF; } for (; w < imageWidth && repeat > 0; w++, repeat--) { buffer[pos++] = pixelR; buffer[pos++] = pixelG; buffer[pos++] = pixelB; buffer[pos++] = pixelA; } } else { for (; w < imageWidth && count > 0; w++, count--) { buffer[pos++] = (byte)stream.ReadByte(); buffer[pos++] = (byte)stream.ReadByte(); buffer[pos++] = (byte)stream.ReadByte(); if (imageDepth == 32) { buffer[pos++] = (byte)stream.ReadByte(); } else { buffer[pos++] = 0xFF; } } } } if (w == imageWidth) { w = 0; pos += delta; if (++h == imageHeight) { break; } } } } else { for (int h = 0; h < imageHeight; h++, pos += delta) { for (int w = 0; w < imageWidth; w++) { buffer[pos++] = (byte)stream.ReadByte(); buffer[pos++] = (byte)stream.ReadByte(); buffer[pos++] = (byte)stream.ReadByte(); if (imageDepth == 32) { buffer[pos++] = (byte)stream.ReadByte(); } else { buffer[pos++] = 0xFF; } } } } pixelFormat = PixelFormat.ARGB; MipMap mipmap = new MipMap(buffer, imageWidth, imageHeight, PixelFormat.ARGB); mipMaps.Add(mipmap); }