Beispiel #1
0
        // Expand the filespec into a list of filenames and pass them to the real Import()

        static public bool Import(AnimSet anis, string strFileSpec)
        {
            string strDir = Path.GetDirectoryName(strFileSpec);

            if (strDir == "")
            {
                strDir = ".";
            }
            string[] astrFiles = Directory.GetFiles(strDir, Path.GetFileName(strFileSpec));

            return(Import(anis, astrFiles));
        }
Beispiel #2
0
        // Write the .ani file and create a _ani subdirectory populated with one
        // .png for each frame

        public static bool SaveAs(AnimSet anis, string strFileName)
        {
            if (strFileName == null)
            {
                strFileName = anis.Name + ".ani";
            }
            XmlTextWriter xwtr = new XmlTextWriter(strFileName, null);

            xwtr.Formatting = Formatting.Indented;
            anis.Serialize(xwtr);
            xwtr.Close();

            // Delete/create _ani subdirectory

            string strDir = strFileName.Replace(".ani", "_ani");

            if (Directory.Exists(strDir))
            {
                Directory.Delete(strDir, true);
            }
            Directory.CreateDirectory(strDir);

            // Write all the frames as .png files into the _ani subdir

            foreach (DictionaryEntry deAnimSet in anis.Items)
            {
                Anim ani = (Anim)deAnimSet.Value;
                foreach (DictionaryEntry deAnim in ani.Items)
                {
                    FrameSet frms = (FrameSet)deAnim.Value;
                    foreach (Frame frm in frms)
                    {
                        frm.Bitmap.Save(strDir + @"\" + anis.Name + "_" + ani.Name + "_" + frms.Name + "_" + frm.Index + ".png",
                                        ImageFormat.Png);
                    }
                }
            }

            return(true);
        }
Beispiel #3
0
        /// <summary>
        /// 
        /// </summary>
        public Gui(AnimSet anis)
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            // Non-Designer initialization

            m_strAedDir = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
            try {
                // UNDONE: problems with this approach to settings:
                // 1. proper location of .config file? Documents and Settings?
                // 2. default values
                // 3. maintenance of Settings class
                // 4. what happens if member isn't present?
                // 5. order-dependent?
                // 6. XML file less readable than .ini
                // 7. more code/maintenance than ini.write(m_nScale), etc w/ overloads
                // 8. doesn't handle Color and other types
                TextReader trdr = new StreamReader(m_strAedDir + @"\AED.config");
                XmlSerializer xser = new XmlSerializer(typeof(Settings));
                Settings settings = (Settings)xser.Deserialize(trdr);

                m_nScale = settings.nPreviewSize;
                m_fShowOrigin = settings.fShowOrigin;
                m_fShowGrid = settings.fShowGrid;
                m_fShowBOverA = settings.fShowBOverA;
                m_clrBackground = Color.FromArgb(settings.nArgbBackground);
                m_fMapSideColors = settings.fMapSideColors;
                // UNDONE: default frame rate
                trdr.Close();
            } catch {
            }

            // Initialize frame rate dependent components

            SetFrameRate(80);

            // UNDONE: doesn't work because panel1 can't accept Focus
            panel1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.panel1_MouseWheel);
            trackBar1.Value = m_nScale;
            SetPreviewPanelBackColor(m_clrBackground);

            if (anis != null) {
                m_anis = anis;
                ResetTreeView();
                ShowFirstFrame();
            }

            // Script stuff

            m_se = new ScriptEngine();
            m_se.ScriptDone += new EventHandler(OnScriptDone);
            m_se.AddGlobal("AED", this);
        }
Beispiel #4
0
        private void mniImport_Click(object sender, System.EventArgs e)
        {
            if (importFileDialog.ShowDialog() != DialogResult.OK)
                return;

            string[] astrFileNames = importFileDialog.FileNames;
            if (astrFileNames == null)
                return;

            m_ts = new ToggleableState();

            m_anis = new AnimSet();
            if (!AED.Import(m_anis, astrFileNames))
                return;

            rbtnA.Checked = true;
            //			rbtnB.Checked = false;

            ResetTreeView();
            UpdateFrameList();
            ShowFirstFrame();
        }
Beispiel #5
0
 static bool Load(AnimSet anis, string strFileName)
 {
     Console.WriteLine("Loading not implemented yet.");
     return true;
 }
Beispiel #6
0
        // Write the .ani file and create a _ani subdirectory populated with one
        // .png for each frame
        public static bool SaveAs(AnimSet anis, string strFileName)
        {
            if (strFileName == null)
                strFileName = anis.Name + ".ani";
            XmlTextWriter xwtr = new XmlTextWriter(strFileName, null);
            xwtr.Formatting = Formatting.Indented;
            anis.Serialize(xwtr);
            xwtr.Close();

            // Delete/create _ani subdirectory

            string strDir = strFileName.Replace(".ani", "_ani");
            if (Directory.Exists(strDir))
                Directory.Delete(strDir, true);
            Directory.CreateDirectory(strDir);

            // Write all the frames as .png files into the _ani subdir

            foreach (DictionaryEntry deAnimSet in anis.Items) {
                Anim ani = (Anim)deAnimSet.Value;
                foreach (DictionaryEntry deAnim in ani.Items) {
                    FrameSet frms = (FrameSet)deAnim.Value;
                    foreach (Frame frm in frms) {
                        frm.Bitmap.Save(strDir + @"\" + anis.Name + "_" + ani.Name + "_" + frms.Name + "_" + frm.Index + ".png",
                            ImageFormat.Png);
                    }
                }
            }

            return true;
        }
Beispiel #7
0
        // Write the .anir file and .bmps or .tbms, depending on fCrunch
        public static bool Export(AnimSet anis, string strExportPath, Palette pal, bool fCrunch, bool fValidateColors)
        {
            Color clrTransparent = Color.FromArgb(0xff, 0, 0xff);
            SolidBrush brTransparent = new SolidBrush(clrTransparent);

            if (strExportPath == null)
                strExportPath = ".";

            ASCIIEncoding enc = new ASCIIEncoding();

            FileStream stm = new FileStream(strExportPath + @"\" + anis.Name + ".anir", FileMode.Create, FileAccess.Write);
            BinaryWriter stmw = new BinaryWriter(stm);

            // Count the number of FrameSets (aka Strips)

            ushort cstpd = 0;
            foreach (DictionaryEntry deAnimSet in anis.Items) {
                Anim ani = (Anim)deAnimSet.Value;
                cstpd += (ushort)ani.Items.Count;
            }

            // Write AnimationFileHeader.cstpd

            stmw.Write(Misc.SwapUShort(cstpd));

            // Write array of offsets to StripDatas (AnimationFileHeader.aoffStpd)

            ushort offStpd = (ushort)(2 + (2 * cstpd));
            byte ibm = 0;
            ArrayList albm = new ArrayList();

            foreach (DictionaryEntry deAnimSet in anis.Items) {
                Anim ani = (Anim)deAnimSet.Value;
                foreach (DictionaryEntry deAnim in ani.Items) {
                    FrameSet frms = (FrameSet)deAnim.Value;
                    stmw.Write(Misc.SwapUShort(offStpd));

                    // Advance offset to where the next StripData will be

                    offStpd += (ushort)((26+1+1+2) /* sizeof(StripData) - sizeof(FrameData) */ +
                            ((1+1+1+1+1+1) /* sizeof(FrameData) */ * frms.Count));
                }
            }

            // Write array of StripDatas

            foreach (DictionaryEntry deAnimSet in anis.Items) {
                Anim ani = (Anim)deAnimSet.Value;
                foreach (DictionaryEntry deAnim in ani.Items) {
                    FrameSet frms = (FrameSet)deAnim.Value;

                    // Write StripData.Name

                    string strName = ani.Name + " " + frms.Name;
                    byte[] abT = new byte[26];
                    enc.GetBytes(strName, 0, Math.Min(strName.Length, 25), abT, 0);
                    abT[25] = 0;
                    stmw.Write(abT);

                    // Write StripData.cDelay

                    stmw.Write((byte)0);

                    // Write StripData.bfFlags

                    stmw.Write((byte)0);

                    // Write StripData.cfrmd

                    ushort cfrmd = (ushort)frms.Count;
                    stmw.Write(Misc.SwapUShort(cfrmd));

                    // Write array of FrameDatas

                    foreach (Frame frm in frms) {

                        // Write FrameData.ibm (the index of the Bitmap as it will be in the Bitmap array)

                        stmw.Write((byte)ibm);
                        ibm++;

                        // Add the Frame's Bitmap for output

                        Bitmap bm = frm.Bitmap;
                        if (fCrunch) {
                            albm.Add(bm);
                        } else {
                            // If not crunching then we need to go through some special work to preserve
                            // the origin point. Since the origin point is determined by finding the center
                            // of the imported bitmap we preserve it at export by creating a new bitmap
                            // sized so that he origin will be in its center.

                            // The '+2' at the end gives us a pixel of transparent space padding the left
                            // and right sides of the bitmap. We don't require this for any particular
                            // reason but it comes in handy.

                            int cxNew = (Math.Max(frm.OriginX, bm.Width - frm.OriginX) * 2) + 2;

                            // The '+2' at the end is to ensure a single blank scanline at the top
                            // which Import relies on to determine the transparent color.

                            int cyNew = (Math.Max(frm.OriginY, bm.Height - frm.OriginY) * 2) + 2;

                            using (Bitmap bmNew = new Bitmap(cxNew, cyNew, bm.PixelFormat)) {
                                using (Graphics g = Graphics.FromImage(bmNew)) {
                                    g.FillRectangle(brTransparent, 0, 0, cxNew, cyNew);
                                    g.DrawImage(bm, cxNew / 2 - frm.OriginX, cyNew / 2 - frm.OriginY);
                                }
                                strName = anis.Name + "_" + ani.Name + "_" + frms.Name + "_" + frm.Index.ToString();
                                bmNew.Save(strExportPath + @"\" + strName + ".png", ImageFormat.Png);
                            }
                        }

                        // Write FrameData.xOrigin, FrameData.yOrigin

                        stmw.Write((byte)frm.OriginX);
                        stmw.Write((byte)frm.OriginY);

                        // Write FrameData.bCustomData1, FrameData.bCustomData2, FrameData.bCustomData3

                        stmw.Write((byte)0);
                        stmw.Write((byte)0);
                        stmw.Write((byte)0);
                    }
                }
            }

            stmw.Close();

            // Write out .tbm

            if (albm.Count != 0) {
                string strFileName = strExportPath + @"\" + anis.Name + ".tbm";
                if (gfSuperVerbose)
                    Console.WriteLine("Crunching and writing " + strFileName);
                TBitmap.Save((Bitmap[])albm.ToArray(typeof(Bitmap)), pal, strFileName);
            }

            return true;
        }
Beispiel #8
0
        public static int Main(string[] astrArgs)
        {
            bool fGui, fLoad = false, fImport = false, fSaveAs = false, fExport = false;
            bool fCrunch = false, fPalette = false, fValidateColors = false;
            string strLoadFileName = null, strImportFileSpec = null, strSaveAsFileName = null, strExportPath = null;
            string strPaletteFileName = null;

            fGui = astrArgs.Length == 0;

            // Parse command line arguments. Commands can be in any order.

            for (int i = 0; i < astrArgs.Length; i++) {
                switch (astrArgs[i]) {
                case "-g":
                    fGui = true;
                    break;

                case "-p":
                    fPalette = true;
                    if (i + 1 >= astrArgs.Length) {
                        Console.WriteLine("Error: -p command requires a filename argument");
                        return -1;
                    }
                    strPaletteFileName = astrArgs[++i];
                    break;

                case "-v":
                    gfVerbose = true;
                    break;

                case "-v2":
                    gfVerbose = true;
                    gfSuperVerbose = true;
                    break;

                case "-validatecolors":
                    fValidateColors = true;
                    break;

                case "-c":
                    fCrunch = true;
                    break;

                case "-l":
                    fLoad = true;
                    if (i + 1 >= astrArgs.Length) {
                        Console.WriteLine("Error: -f command requires a filename argument");
                        return -1;
                    }
                    strLoadFileName = astrArgs[++i];
                    break;

                case "-i":
                    fImport = true;
                    if (i + 1 >= astrArgs.Length) {
                        Console.WriteLine("Error: -i command requires a filespec argument");
                        return -1;
                    }
                    strImportFileSpec = astrArgs[++i];
                    break;

                case "-s":
                    fSaveAs = true;
                    if (i + 1 < astrArgs.Length && !astrArgs[i + 1].StartsWith("-"))
                        strSaveAsFileName = astrArgs[++i];
                    break;

                case "-x":
                    fExport = true;
                    if (i + 1 < astrArgs.Length && !astrArgs[i + 1].StartsWith("-"))
                        strExportPath = astrArgs[++i];
                    break;

                case "-?":
                case "-help":
                case "/?":
                case "/help":
                    Console.WriteLine(
                            "Usage:\nAED [-v] [-c] [-p palette.pal] <-l <filename> | -i <filespec>> [-s [filename]] [-x [dir]]\n" +
                            "-v: verbose\n" +
                            "-v2: super verbose!\n" +
                            "-c: crunch (compile to runtime format) when exporting\n" +
                            "-p palette.pal: specify the palette to be matched to when crunching to 8-bpp\n" +
                            "-l filename: load a .ani animation\n" +
                            "-s filename: save a .ani animation\n" +
                            "-i filespec: import a set of bitmaps\n" +
                            "-x dir: export a set of bitmaps to the specified directory\n" +
                            "-validatecolors: during crunch, validate that all pixel colors are in\n" +
                            "   the specified palette\n");
                    return 0;

                default:
                    Console.WriteLine("Error: Unknown command line argument \"{0}\"", astrArgs[i]);
                    return -1;
                }
            }

            // Additional command validation

            if (fLoad && fImport) {
                Console.WriteLine("Error: Can't use -l and -i commands together, they're ambiguous");
                return -1;
            }

            if (!fGui && !fLoad && !fImport) {
                Console.WriteLine("Error: Must specify either -l or -i command so AED has something to work with");
                return -1;
            }

            // Execute the specified commands

            AnimSet anis = new AnimSet();

            if (fLoad) {
                if (gfVerbose)
                    Console.WriteLine("Loading {0}...", strLoadFileName);
                if (!Load(anis, strLoadFileName))
                    return -1;
            }

            if (fImport) {
                if (gfVerbose)
                    Console.WriteLine("Importing {0}...", strImportFileSpec);
                if (!Import(anis, strImportFileSpec))
                    return -1;
            }

            if (fGui) {
                // This is modal and won't return until the MainForm is closed

                Application.Run(new Gui(anis.Items.Count != 0 ? anis : null));
            }

            if (fSaveAs) {
                if (gfVerbose)
                    Console.WriteLine("Saving {0}...", strSaveAsFileName);
                if (!SaveAs(anis, strSaveAsFileName))
                    return -1;
            }

            if (fExport) {
                if (gfVerbose)
                    Console.WriteLine("Exporting {1} to {0}...", strExportPath, anis.Name);
                Palette pal = null;
                if (fPalette)
                    pal = new Palette(strPaletteFileName);
                if (!Export(anis, strExportPath, pal, fCrunch, fValidateColors))
                    return -1;
            }

            return 0;
        }
Beispiel #9
0
        public static bool Import(AnimSet anis, string[] astrFileNames)
        {
            // By sorting the filenames we introduce a useful bit of determinism.

            Array.Sort(astrFileNames);

            // Enumerate all the filenames and for each one:

            Color clrTransparent = Color.FromArgb(0xff, 0, 0xff);
            SolidBrush brTransparent = new SolidBrush(clrTransparent);

            foreach (string strFile in astrFileNames) {

                // 1. Read the bitmap from it.

                Bitmap bm;
                try {
                    bm = new Bitmap(strFile);
                } catch {
                    Console.WriteLine("Error: Can't load \"{0}\"", strFile);
                    return false;
                }

                // 2. 'Normalize' the bitmap. Normalized bitmaps are 24-bit, 'tight',
                //    have the proper transparent color, and an origin.

                // All pixels the same color as the upper-left pixel get mapped to the
                // transparent color

                bm.MakeTransparent(bm.GetPixel(0, 0));

                Bitmap bmT = new Bitmap(bm.Width, bm.Height, PixelFormat.Format24bppRgb);
                using (Graphics g = Graphics.FromImage(bmT)) {

                    // Prep the new image by filling with the transparent color

                    g.FillRectangle(brTransparent, 0, 0, bm.Width, bm.Height);

                    // Convert the Bitmap to 24-bpp while leaving transparent pixels behind

                    g.DrawImageUnscaled(bm, 0, 0);
                }

                bm = bmT;

                // UNDONE: any color mapping

                // Find the tight boundary of the image and create a new Bitmap with just
                // that portion of the Bitmap
                // OPT: this could be made faster by doing four independent edge scans

                int xL = bm.Width;
                int xR = 0;
                int yT = bm.Height;
                int yB = 0;
                for (int y = 0; y < bm.Height; y++) {
                    for (int x = 0; x < bm.Width; x++) {
                        Color clr = bm.GetPixel(x, y);
                        if (clr != clrTransparent) {
                            xL = Math.Min(xL, x);
                            xR = Math.Max(xR, x);
                            yT = Math.Min(yT, y);
                            yB = Math.Max(yB, y);
                        }
                    }
                }
                int cx = xR - xL + 1;
                int cy = yB - yT + 1;
                int xOrigin = bm.Width / 2 - xL;
                int yOrigin = bm.Height / 2 - yT;

                bmT = new Bitmap(cx, cy, PixelFormat.Format24bppRgb);
                using (Graphics g = Graphics.FromImage(bmT)) {
                    Rectangle rcT = new Rectangle(xL, yT, cx, cy);
                    g.DrawImage(bm, 0, 0, rcT, GraphicsUnit.Pixel);
                }

                bm = bmT;

                // 3. Create a Frame object which references the normalized bitmap.

                Frame frm = new Frame(bm, xOrigin, yOrigin);

                // 4. Assign it to the proper Anim and FrameSet by using info parsed
                //    from the bitmap's original filename. If the proper Anim/FrameSet
                //    does not yet exist, create it.

                string[] astr = strFile.Substring(strFile.LastIndexOf('\\') + 1).Split('_', '.');
                if (astr.Length != 5) {
                    Console.WriteLine("Warning: file {0} does not match the requisite naming pattern", strFile);
                    continue;
                }
                string strAnimSet = astr[0];
                string strAnim = astr[1];
                string strFrameSet = astr[2];
                string strFrame = astr[3];

                anis.Name = strAnimSet;
                anis.AddFrame(strAnim, strFrameSet, strFrame, frm);
            }

            return true;
        }
Beispiel #10
0
        // Expand the filespec into a list of filenames and pass them to the real Import()
        public static bool Import(AnimSet anis, string strFileSpec)
        {
            string strDir = Path.GetDirectoryName(strFileSpec);
            if (strDir == "")
                strDir = ".";
            string[] astrFiles = Directory.GetFiles(strDir, Path.GetFileName(strFileSpec));

            return Import(anis, astrFiles);
        }
Beispiel #11
0
        // Write the .anir file and .bmps or .tbms, depending on fCrunch

        public static bool Export(AnimSet anis, string strExportPath, Palette pal, bool fCrunch, bool fValidateColors)
        {
            Color      clrTransparent = Color.FromArgb(0xff, 0, 0xff);
            SolidBrush brTransparent  = new SolidBrush(clrTransparent);

            if (strExportPath == null)
            {
                strExportPath = ".";
            }

            ASCIIEncoding enc = new ASCIIEncoding();

            FileStream   stm  = new FileStream(strExportPath + @"\" + anis.Name + ".anir", FileMode.Create, FileAccess.Write);
            BinaryWriter stmw = new BinaryWriter(stm);

            // Count the number of FrameSets (aka Strips)

            ushort cstpd = 0;

            foreach (DictionaryEntry deAnimSet in anis.Items)
            {
                Anim ani = (Anim)deAnimSet.Value;
                cstpd += (ushort)ani.Items.Count;
            }

            // Write AnimationFileHeader.cstpd

            stmw.Write(Misc.SwapUShort(cstpd));

            // Write array of offsets to StripDatas (AnimationFileHeader.aoffStpd)

            ushort    offStpd = (ushort)(2 + (2 * cstpd));
            byte      ibm     = 0;
            ArrayList albm    = new ArrayList();

            foreach (DictionaryEntry deAnimSet in anis.Items)
            {
                Anim ani = (Anim)deAnimSet.Value;
                foreach (DictionaryEntry deAnim in ani.Items)
                {
                    FrameSet frms = (FrameSet)deAnim.Value;
                    stmw.Write(Misc.SwapUShort(offStpd));

                    // Advance offset to where the next StripData will be

                    offStpd += (ushort)((26 + 1 + 1 + 2) /* sizeof(StripData) - sizeof(FrameData) */ +
                                        ((1 + 1 + 1 + 1 + 1 + 1) /* sizeof(FrameData) */ * frms.Count));
                }
            }

            // Write array of StripDatas

            foreach (DictionaryEntry deAnimSet in anis.Items)
            {
                Anim ani = (Anim)deAnimSet.Value;
                foreach (DictionaryEntry deAnim in ani.Items)
                {
                    FrameSet frms = (FrameSet)deAnim.Value;

                    // Write StripData.Name

                    string strName = ani.Name + " " + frms.Name;
                    byte[] abT     = new byte[26];
                    enc.GetBytes(strName, 0, Math.Min(strName.Length, 25), abT, 0);
                    abT[25] = 0;
                    stmw.Write(abT);

                    // Write StripData.cDelay

                    stmw.Write((byte)0);

                    // Write StripData.bfFlags

                    stmw.Write((byte)0);

                    // Write StripData.cfrmd

                    ushort cfrmd = (ushort)frms.Count;
                    stmw.Write(Misc.SwapUShort(cfrmd));

                    // Write array of FrameDatas

                    foreach (Frame frm in frms)
                    {
                        // Write FrameData.ibm (the index of the Bitmap as it will be in the Bitmap array)

                        stmw.Write((byte)ibm);
                        ibm++;

                        // Add the Frame's Bitmap for output

                        Bitmap bm = frm.Bitmap;
                        if (fCrunch)
                        {
                            albm.Add(bm);
                        }
                        else
                        {
                            // If not crunching then we need to go through some special work to preserve
                            // the origin point. Since the origin point is determined by finding the center
                            // of the imported bitmap we preserve it at export by creating a new bitmap
                            // sized so that he origin will be in its center.


                            // The '+2' at the end gives us a pixel of transparent space padding the left
                            // and right sides of the bitmap. We don't require this for any particular
                            // reason but it comes in handy.

                            int cxNew = (Math.Max(frm.OriginX, bm.Width - frm.OriginX) * 2) + 2;

                            // The '+2' at the end is to ensure a single blank scanline at the top
                            // which Import relies on to determine the transparent color.

                            int cyNew = (Math.Max(frm.OriginY, bm.Height - frm.OriginY) * 2) + 2;

                            using (Bitmap bmNew = new Bitmap(cxNew, cyNew, bm.PixelFormat)) {
                                using (Graphics g = Graphics.FromImage(bmNew)) {
                                    g.FillRectangle(brTransparent, 0, 0, cxNew, cyNew);
                                    g.DrawImage(bm, cxNew / 2 - frm.OriginX, cyNew / 2 - frm.OriginY);
                                }
                                strName = anis.Name + "_" + ani.Name + "_" + frms.Name + "_" + frm.Index.ToString();
                                bmNew.Save(strExportPath + @"\" + strName + ".png", ImageFormat.Png);
                            }
                        }

                        // Write FrameData.xOrigin, FrameData.yOrigin

                        stmw.Write((byte)frm.OriginX);
                        stmw.Write((byte)frm.OriginY);

                        // Write FrameData.bCustomData1, FrameData.bCustomData2, FrameData.bCustomData3

                        stmw.Write((byte)0);
                        stmw.Write((byte)0);
                        stmw.Write((byte)0);
                    }
                }
            }

            stmw.Close();

            // Write out .tbm

            if (albm.Count != 0)
            {
                string strFileName = strExportPath + @"\" + anis.Name + ".tbm";
                if (gfSuperVerbose)
                {
                    Console.WriteLine("Crunching and writing " + strFileName);
                }
                TBitmap.Save((Bitmap[])albm.ToArray(typeof(Bitmap)), pal, strFileName);
            }

            return(true);
        }
Beispiel #12
0
 static bool Load(AnimSet anis, string strFileName)
 {
     Console.WriteLine("Loading not implemented yet.");
     return(true);
 }
Beispiel #13
0
        public static int Main(string[] astrArgs)
        {
            bool   fGui, fLoad = false, fImport = false, fSaveAs = false, fExport = false;
            bool   fCrunch = false, fPalette = false, fValidateColors = false;
            string strLoadFileName = null, strImportFileSpec = null, strSaveAsFileName = null, strExportPath = null;
            string strPaletteFileName = null;

            fGui = astrArgs.Length == 0;

            // Parse command line arguments. Commands can be in any order.

            for (int i = 0; i < astrArgs.Length; i++)
            {
                switch (astrArgs[i])
                {
                case "-g":
                    fGui = true;
                    break;

                case "-p":
                    fPalette = true;
                    if (i + 1 >= astrArgs.Length)
                    {
                        Console.WriteLine("Error: -p command requires a filename argument");
                        return(-1);
                    }
                    strPaletteFileName = astrArgs[++i];
                    break;

                case "-v":
                    gfVerbose = true;
                    break;

                case "-v2":
                    gfVerbose      = true;
                    gfSuperVerbose = true;
                    break;

                case "-validatecolors":
                    fValidateColors = true;
                    break;

                case "-c":
                    fCrunch = true;
                    break;

                case "-l":
                    fLoad = true;
                    if (i + 1 >= astrArgs.Length)
                    {
                        Console.WriteLine("Error: -f command requires a filename argument");
                        return(-1);
                    }
                    strLoadFileName = astrArgs[++i];
                    break;

                case "-i":
                    fImport = true;
                    if (i + 1 >= astrArgs.Length)
                    {
                        Console.WriteLine("Error: -i command requires a filespec argument");
                        return(-1);
                    }
                    strImportFileSpec = astrArgs[++i];
                    break;

                case "-s":
                    fSaveAs = true;
                    if (i + 1 < astrArgs.Length && !astrArgs[i + 1].StartsWith("-"))
                    {
                        strSaveAsFileName = astrArgs[++i];
                    }
                    break;

                case "-x":
                    fExport = true;
                    if (i + 1 < astrArgs.Length && !astrArgs[i + 1].StartsWith("-"))
                    {
                        strExportPath = astrArgs[++i];
                    }
                    break;

                case "-?":
                case "-help":
                case "/?":
                case "/help":
                    Console.WriteLine(
                        "Usage:\nAED [-v] [-c] [-p palette.pal] <-l <filename> | -i <filespec>> [-s [filename]] [-x [dir]]\n" +
                        "-v: verbose\n" +
                        "-v2: super verbose!\n" +
                        "-c: crunch (compile to runtime format) when exporting\n" +
                        "-p palette.pal: specify the palette to be matched to when crunching to 8-bpp\n" +
                        "-l filename: load a .ani animation\n" +
                        "-s filename: save a .ani animation\n" +
                        "-i filespec: import a set of bitmaps\n" +
                        "-x dir: export a set of bitmaps to the specified directory\n" +
                        "-validatecolors: during crunch, validate that all pixel colors are in\n" +
                        "   the specified palette\n");
                    return(0);

                default:
                    Console.WriteLine("Error: Unknown command line argument \"{0}\"", astrArgs[i]);
                    return(-1);
                }
            }

            // Additional command validation

            if (fLoad && fImport)
            {
                Console.WriteLine("Error: Can't use -l and -i commands together, they're ambiguous");
                return(-1);
            }

            if (!fGui && !fLoad && !fImport)
            {
                Console.WriteLine("Error: Must specify either -l or -i command so AED has something to work with");
                return(-1);
            }

            // Execute the specified commands

            AnimSet anis = new AnimSet();

            if (fLoad)
            {
                if (gfVerbose)
                {
                    Console.WriteLine("Loading {0}...", strLoadFileName);
                }
                if (!Load(anis, strLoadFileName))
                {
                    return(-1);
                }
            }

            if (fImport)
            {
                if (gfVerbose)
                {
                    Console.WriteLine("Importing {0}...", strImportFileSpec);
                }
                if (!Import(anis, strImportFileSpec))
                {
                    return(-1);
                }
            }

            if (fGui)
            {
                // This is modal and won't return until the MainForm is closed

                Application.Run(new Gui(anis.Items.Count != 0 ? anis : null));
            }

            if (fSaveAs)
            {
                if (gfVerbose)
                {
                    Console.WriteLine("Saving {0}...", strSaveAsFileName);
                }
                if (!SaveAs(anis, strSaveAsFileName))
                {
                    return(-1);
                }
            }

            if (fExport)
            {
                if (gfVerbose)
                {
                    Console.WriteLine("Exporting {1} to {0}...", strExportPath, anis.Name);
                }
                Palette pal = null;
                if (fPalette)
                {
                    pal = new Palette(strPaletteFileName);
                }
                if (!Export(anis, strExportPath, pal, fCrunch, fValidateColors))
                {
                    return(-1);
                }
            }

            return(0);
        }
Beispiel #14
0
        static public bool Import(AnimSet anis, string[] astrFileNames)
        {
            // By sorting the filenames we introduce a useful bit of determinism.

            Array.Sort(astrFileNames);

            // Enumerate all the filenames and for each one:

            Color      clrTransparent = Color.FromArgb(0xff, 0, 0xff);
            SolidBrush brTransparent  = new SolidBrush(clrTransparent);

            foreach (string strFile in astrFileNames)
            {
                // 1. Read the bitmap from it.

                Bitmap bm;
                try {
                    bm = new Bitmap(strFile);
                } catch {
                    Console.WriteLine("Error: Can't load \"{0}\"", strFile);
                    return(false);
                }

                // 2. 'Normalize' the bitmap. Normalized bitmaps are 24-bit, 'tight',
                //    have the proper transparent color, and an origin.

                // All pixels the same color as the upper-left pixel get mapped to the
                // transparent color

                bm.MakeTransparent(bm.GetPixel(0, 0));

                Bitmap bmT = new Bitmap(bm.Width, bm.Height, PixelFormat.Format24bppRgb);
                using (Graphics g = Graphics.FromImage(bmT)) {
                    // Prep the new image by filling with the transparent color

                    g.FillRectangle(brTransparent, 0, 0, bm.Width, bm.Height);

                    // Convert the Bitmap to 24-bpp while leaving transparent pixels behind

                    g.DrawImageUnscaled(bm, 0, 0);
                }

                bm = bmT;

                // UNDONE: any color mapping

                // Find the tight boundary of the image and create a new Bitmap with just
                // that portion of the Bitmap
                // OPT: this could be made faster by doing four independent edge scans

                int xL = bm.Width;
                int xR = 0;
                int yT = bm.Height;
                int yB = 0;
                for (int y = 0; y < bm.Height; y++)
                {
                    for (int x = 0; x < bm.Width; x++)
                    {
                        Color clr = bm.GetPixel(x, y);
                        if (clr != clrTransparent)
                        {
                            xL = Math.Min(xL, x);
                            xR = Math.Max(xR, x);
                            yT = Math.Min(yT, y);
                            yB = Math.Max(yB, y);
                        }
                    }
                }
                int cx      = xR - xL + 1;
                int cy      = yB - yT + 1;
                int xOrigin = bm.Width / 2 - xL;
                int yOrigin = bm.Height / 2 - yT;

                bmT = new Bitmap(cx, cy, PixelFormat.Format24bppRgb);
                using (Graphics g = Graphics.FromImage(bmT)) {
                    Rectangle rcT = new Rectangle(xL, yT, cx, cy);
                    g.DrawImage(bm, 0, 0, rcT, GraphicsUnit.Pixel);
                }

                bm = bmT;

                // 3. Create a Frame object which references the normalized bitmap.

                Frame frm = new Frame(bm, xOrigin, yOrigin);

                // 4. Assign it to the proper Anim and FrameSet by using info parsed
                //    from the bitmap's original filename. If the proper Anim/FrameSet
                //    does not yet exist, create it.

                string[] astr = strFile.Substring(strFile.LastIndexOf('\\') + 1).Split('_', '.');
                if (astr.Length != 5)
                {
                    Console.WriteLine("Warning: file {0} does not match the requisite naming pattern", strFile);
                    continue;
                }
                string strAnimSet  = astr[0];
                string strAnim     = astr[1];
                string strFrameSet = astr[2];
                string strFrame    = astr[3];

                anis.Name = strAnimSet;
                anis.AddFrame(strAnim, strFrameSet, strFrame, frm);
            }

            return(true);
        }