Exemplo n.º 1
0
        static void PrintSimisAce(int indent, SimisAce ace)
        {
            var indentString = new String(' ', 2 * indent);

            Console.WriteLine("{0}Format:        0x{1:X}", indentString, ace.Format);
            Console.WriteLine("{0}Width:         {1}", indentString, ace.Width);
            Console.WriteLine("{0}Height:        {1}", indentString, ace.Height);
            Console.WriteLine("{0}Unk4:          0x{1:X}", indentString, ace.Unknown4);
            Console.WriteLine("{0}Unk6:          0x{1:X}", indentString, ace.Unknown6);
            Console.WriteLine("{0}Unk7:          {1}", indentString, ace.Unknown7);
            Console.WriteLine("{0}Creator:       {1}", indentString, ace.Creator);
            for (var i = 0; i < 11; i++)
            {
                Console.WriteLine("{0}Unk9.{2:X}:        {1}", indentString, String.Join(" ", ace.Unknown9.Skip(i * 4).Take(4).Select(b => b.ToString("X2")).ToArray()), i);
            }
            Console.WriteLine("{0}Channels:      {1}", indentString, String.Join(", ", ace.Channel.Select(c => String.Format("{0} ({1} bits)", c.Type, c.Size)).ToArray()));
            Console.WriteLine("{0}Images:        {1}", indentString, String.Join(", ", ace.Image.Select(i => String.Format("{0}x{1}{2}{3}", i.Width, i.Height, i.ImageColor != null ? " Color" : "", i.ImageMask != null ? " Mask" : "")).ToArray()));
        }
Exemplo n.º 2
0
 static void PrintSimisAce(SimisAce ace)
 {
     Console.WriteLine("Ace {");
     PrintSimisAce(1, ace);
     Console.WriteLine("}");
 }
Exemplo n.º 3
0
        static void DoConversion(IEnumerable <ConversionFile> files, bool verbose, int threading, bool convertRoundtrip, bool convertTexture, bool convertDXT1, bool convertZLIB)
        {
            if (!files.Any())
            {
                throw new OperationCanceledException("Must specify files for conversion.");
            }

            SimisProvider provider;

            try {
                provider = new SimisProvider(Path.GetDirectoryName(Application.ExecutablePath) + @"\Resources");
            } catch (FileException ex) {
                Console.WriteLine(ex.ToString());
                return;
            }

            Action <ConversionFile> ConvertFile = (file) => {
                if (verbose)
                {
                    lock (files) {
                        if (threading > 1)
                        {
                            Console.WriteLine("[Thread {0}] {1} -> {2}", Thread.CurrentThread.ManagedThreadId, file.Input, file.Output);
                        }
                        else
                        {
                            Console.WriteLine("{0} -> {1}", file.Input, file.Output);
                        }
                    }
                }

                try {
                    var inputExt  = Path.GetExtension(file.Input).ToUpperInvariant();
                    var outputExt = Path.GetExtension(file.Output).ToUpperInvariant();
                    if ((inputExt == ".ACE") && (outputExt == ".ACE"))
                    {
                        // ACE -> ACE
                        var inputAce  = new SimisFile(file.Input, provider);
                        var outputAce = new SimisFile(file.Output, true, convertZLIB, inputAce.Ace);
                        outputAce.Write();
                    }
                    else if (inputExt == ".ACE")
                    {
                        // ACE -> ***
                        var inputAce    = new SimisFile(file.Input, provider);
                        var width       = convertRoundtrip ? inputAce.Ace.Image.Max(i => i.Width) : inputAce.Ace.Image[0].Width;
                        var height      = convertRoundtrip ? inputAce.Ace.Image.Sum(i => i.Height) : inputAce.Ace.Image[0].Height;
                        var outputImage = new Bitmap(width * (convertRoundtrip ? 2 : 1), height, PixelFormat.Format32bppArgb);
                        using (var g = Graphics.FromImage(outputImage)) {
                            g.FillRectangle(Brushes.Transparent, 0, 0, outputImage.Width, outputImage.Height);
                            if (convertRoundtrip)
                            {
                                var y = 0;
                                foreach (var image in inputAce.Ace.Image)
                                {
                                    g.DrawImageUnscaled(image.ImageColor, 0, y);
                                    g.DrawImageUnscaled(image.ImageMask, width, y);
                                    y += image.Height;
                                }
                            }
                            else
                            {
                                g.DrawImageUnscaled(inputAce.Ace.Image[0].GetImage(inputAce.Ace.HasAlpha ? SimisAceImageType.ColorAndAlpha : inputAce.Ace.HasMask ? SimisAceImageType.ColorAndMask : SimisAceImageType.ColorOnly), 0, 0);
                            }
                        }
                        outputImage.Save(file.Output);
                    }
                    else if (outputExt == ".ACE")
                    {
                        // *** -> ACE
                        var inputImage = Image.FromFile(file.Input);
                        var width      = inputImage.Width;
                        var height     = inputImage.Height;

                        // Roundtripping or not, textures have special requirements of 2^n width and height.
                        if (convertTexture)
                        {
                            if (convertRoundtrip)
                            {
                                var expectedHeight = (int)Math.Pow(2, (int)(Math.Log(height + 1) / Math.Log(2))) - 1;
                                if (height != expectedHeight)
                                {
                                    throw new InvalidOperationException(String.Format("Image height {0} is not correct for round-tripping a texture. It must be 2^n-1.", height, expectedHeight));
                                }
                                height = (height + 1) / 2;
                                // Roundtripping always has two columns: color and mask.
                                width /= 2;
                            }
                            else
                            {
                                var expectedHeight = (int)Math.Pow(2, (int)(Math.Log(height) / Math.Log(2)));
                                if (height != expectedHeight)
                                {
                                    throw new InvalidOperationException(String.Format("Image height {0} is not correct for a texture. It must be 2^n.", height, expectedHeight));
                                }
                            }
                            var expectedWidth = (int)Math.Pow(2, (int)(Math.Log(width) / Math.Log(2)));
                            if (width != expectedWidth)
                            {
                                throw new InvalidOperationException(String.Format("Image width {0} is not correct for a texture. It must be 2^n.", width, expectedWidth));
                            }
                            if (width != height)
                            {
                                throw new InvalidOperationException(String.Format("Image width {0} and height {1} must be equal for a texture.", width, height));
                            }
                        }

                        if (convertRoundtrip || convertTexture)
                        {
                            var imageCount  = 1 + (int)(convertTexture ? Math.Log(height) / Math.Log(2) : 0);
                            var aceChannels = new[] {
                                new SimisAceChannel(8, SimisAceChannelId.Red),
                                new SimisAceChannel(8, SimisAceChannelId.Green),
                                new SimisAceChannel(8, SimisAceChannelId.Blue),
                                new SimisAceChannel(8, SimisAceChannelId.Alpha),
                                new SimisAceChannel(1, SimisAceChannelId.Mask),
                            };
                            // Remove the alpha channel for DXT1.
                            if (convertDXT1)
                            {
                                aceChannels = new[] { aceChannels[0], aceChannels[1], aceChannels[2], aceChannels[4] };
                            }
                            var aceImages = new SimisAceImage[imageCount];
                            var y         = 0;
                            for (var i = 0; i < imageCount; i++)
                            {
                                var scale      = (int)Math.Pow(2, i);
                                var colorImage = new Bitmap(width / scale, height / scale, PixelFormat.Format32bppArgb);
                                var maskImage  = new Bitmap(width / scale, height / scale, PixelFormat.Format32bppRgb);
                                var sourceRect = convertRoundtrip ? new Rectangle(0, y, width / scale, height / scale) : new Rectangle(0, 0, width, height);
                                using (var g = Graphics.FromImage(colorImage)) {
                                    g.DrawImage(inputImage, new Rectangle(Point.Empty, colorImage.Size), sourceRect, GraphicsUnit.Pixel);
                                }
                                sourceRect.X = width;
                                using (var g = Graphics.FromImage(maskImage)) {
                                    if (width < inputImage.Width)
                                    {
                                        g.DrawImage(inputImage, new Rectangle(Point.Empty, maskImage.Size), sourceRect, GraphicsUnit.Pixel);
                                    }
                                    else
                                    {
                                        g.FillRectangle(Brushes.White, new Rectangle(Point.Empty, maskImage.Size));
                                    }
                                }
                                aceImages[i] = new SimisAceImage(colorImage, maskImage);
                                y           += colorImage.Height;
                            }
                            var ace     = new SimisAce((convertDXT1 ? 0x10 : 0x00) + (convertTexture ? 0x05 : 0x00), width, height, convertDXT1 ? 0x12 : 0x00, 0, "Unknown", "JGR Image File", new byte[44], aceChannels, aceImages, new byte[0], new byte[0]);
                            var aceFile = new SimisFile(file.Output, true, convertZLIB, ace);
                            aceFile.Write();
                        }
                        else
                        {
                            // TODO: Handle the various alpha/mask fun here.
                            var aceChannels = new[] {
                                new SimisAceChannel(8, SimisAceChannelId.Red),
                                new SimisAceChannel(8, SimisAceChannelId.Green),
                                new SimisAceChannel(8, SimisAceChannelId.Blue),
                                new SimisAceChannel(8, SimisAceChannelId.Alpha),
                            };
                            // Replace the alpha channel with mask channel for DXT1.
                            if (convertDXT1)
                            {
                                aceChannels[3] = new SimisAceChannel(1, SimisAceChannelId.Mask);
                            }
                            var maskImage = new Bitmap(width, height, PixelFormat.Format32bppRgb);
                            using (var g = Graphics.FromImage(maskImage)) {
                                g.FillRectangle(Brushes.White, 0, 0, maskImage.Width, maskImage.Height);
                            }
                            var aceImages = new[] {
                                new SimisAceImage(new Bitmap(inputImage), maskImage),
                            };
                            var ace     = new SimisAce(convertDXT1 ? 0x10 : 0x00, width, height, convertDXT1 ? 0x12 : 0x00, 0, "Unknown", "JGR Image File", new byte[44], aceChannels, aceImages, new byte[0], new byte[0]);
                            var aceFile = new SimisFile(file.Output, true, convertZLIB, ace);
                            aceFile.Write();
                        }
                    }
                    else
                    {
                        // *** -> ***
                        Image.FromFile(file.Input).Save(file.Output);
                    }
                } catch (Exception ex) {
                    Console.Error.WriteLine(ex.ToString());
                }
            };

            if (threading > 1)
            {
                var filesEnumerator = files.GetEnumerator();
                var filesFinished   = false;
                var threads         = new List <Thread>(threading);
                for (var i = 0; i < threading; i++)
                {
                    threads.Add(new Thread(() => {
                        ConversionFile file;
                        while (true)
                        {
                            lock (filesEnumerator) {
                                if (filesFinished || !filesEnumerator.MoveNext())
                                {
                                    filesFinished = true;
                                    break;
                                }
                                file = filesEnumerator.Current;
                            }
                            ConvertFile(file);
                        }
                    }));
                }
                foreach (var thread in threads)
                {
                    thread.Start();
                }
                foreach (var thread in threads)
                {
                    thread.Join();
                }
            }
            else
            {
                foreach (var file in files)
                {
                    ConvertFile(file);
                }
            }
        }