static Channel getSourceForChannel(Channel channel, ChannelMapping mapping) { if (mapping.R == channel) { return(Channel.R); } else if (mapping.G == channel) { return(Channel.G); } else if (mapping.B == channel) { return(Channel.B); } else { return(Channel.A); } }
//TODO: generate mipmaps static int Main(string[] args) { if (args.Length < 4) { Console.WriteLine("syntax: ImageConverter {(int)dxgi_format} {(source rgba),(dest rgba) input fullpath}[1-4] {output fullpath}"); return(1); } //for now, width/height will use the values from the first image //pitch/bitsperpixel will come dxgi_format parameter DXGI_FORMAT dxgiFormat = (DXGI_FORMAT)Enum.Parse(typeof(DXGI_FORMAT), args[0]); uint bitsPerPixel = getBitsPerPixel(dxgiFormat); uint pitch = getPitch(bitsPerPixel); int channelCount = getChannels(dxgiFormat); uint width = 0, height = 0; var images = new List <Tuple <ChannelMapping, Image> >(); for (int i = 1; i < args.Length - 1; i += 2) { var channels = args[i]; var path = args[i + 1]; Image image = null; if (path == "null") { image = new Image(); image.bytes = new byte[bitsPerPixel / 8 / channelCount * width * height]; image.bitsPerPixel = bitsPerPixel / (uint)channelCount; image.channels = 1; } else { image = loadImage(path); } if (i == 1) { width = (uint)image.width; height = (uint)image.height; } var mapping = new ChannelMapping(); var split = channels.Split(','); var sourceName = split[0]; var destinationName = split[1]; if (sourceName.Length != destinationName.Length) { throw new Exception("invalid channel mapping"); } for (int c = 0; c < sourceName.Length; c++) { var source = (Channel)Enum.Parse(typeof(Channel), sourceName[c].ToString(), true); var destination = (Channel)Enum.Parse(typeof(Channel), destinationName[c].ToString(), true); switch (source) { case Channel.R: { mapping.R = destination; break; } case Channel.G: { mapping.G = destination; break; } case Channel.B: { mapping.B = destination; break; } case Channel.A: { mapping.A = destination; break; } } } images.Add(Tuple.Create(mapping, image)); } uint totalTextureSize = width * height * pitch; uint totalPixels = width * height; var packedTexture = packImages(images, totalTextureSize, totalPixels, bitsPerPixel / 8, channelCount); const int DDS_MAGIC_NUMBER = 0x20534444; Header header = new Header(); header.size = 124; header.flags = (uint)(HeaderFlags.CAPS | HeaderFlags.WIDTH | HeaderFlags.HEIGHT | HeaderFlags.PIXELFORMAT); header.width = width; header.height = height; header.pitchOrLinearSize = pitch; header.pixelFormat = new PixelFormat(); header.pixelFormat.size = 32; header.pixelFormat.flags = (uint)PixelFormatFlags.FOUR_CC; header.pixelFormat.fourCC = ('D') | ('X' << 8) | ('1' << 16) | ('0' << 24); header.pixelFormat.rgbBitCount = bitsPerPixel; header.caps = (uint)Caps.TEXTURE; header.caps2 = 0; header.caps3 = 0; header.caps4 = 0; HeaderDXT10 dxtHeader = new HeaderDXT10(); dxtHeader.dxgiFormat = (int)dxgiFormat; dxtHeader.resourceDimension = (int)D3D10_RESOURCE_DIMENSION.D3D10_RESOURCE_DIMENSION_TEXTURE2D; dxtHeader.miscFlag = 0; dxtHeader.arraySize = 1; dxtHeader.miscFlags2 = 0; var buffer = new byte[4 + 124 + 20 + totalTextureSize]; using (var stream = new MemoryStream(buffer)) { using (var writer = new BinaryWriter(stream)) { writer.Write(DDS_MAGIC_NUMBER); writer.Write(header.size); writer.Write(header.flags); writer.Write(header.height); writer.Write(header.width); writer.Write(header.pitchOrLinearSize); writer.Write(header.depth); writer.Write(header.mipMapCount); //write out dwReserved1[11] for (int i = 0; i < 11; i++) { writer.Write((uint)0); } writer.Write(header.pixelFormat.size); writer.Write(header.pixelFormat.flags); writer.Write(header.pixelFormat.fourCC); writer.Write(header.pixelFormat.rgbBitCount); writer.Write(header.pixelFormat.rBitMask); writer.Write(header.pixelFormat.gBitMask); writer.Write(header.pixelFormat.bBitMask); writer.Write(header.pixelFormat.aBitMask); writer.Write(header.caps); writer.Write(header.caps2); writer.Write(header.caps3); writer.Write(header.caps4); writer.Write(header.reserved2); writer.Write(dxtHeader.dxgiFormat); writer.Write(dxtHeader.resourceDimension); writer.Write(dxtHeader.miscFlag); writer.Write(dxtHeader.arraySize); writer.Write(dxtHeader.miscFlags2); writer.Write(packedTexture); } } var output = args[args.Length - 1]; File.WriteAllBytes(output, buffer); return(0); }