/// <summary>
 ///  Extracts the HG-3 image information from the KIFINT entry's open KIFINT archive stream and saves all
 ///  images to the output <paramref name="directory"/>.
 /// </summary>
 /// <param name="kifintStream">The stream to the open KIFINT archive.</param>
 /// <param name="entry">The KIFINT entry information used to extract the HG-3 file.</param>
 /// <param name="directory">The output directory to save the images to.</param>
 /// <param name="expand">True if the images are expanded to their full size when saving.</param>
 /// <returns>The extracted <see cref="Hg3"/> information.</returns>
 ///
 /// <exception cref="ArgumentNullException">
 ///  <paramref name="kifintStream"/>, <paramref name="entry"/>, or <paramref name="directory"/> is null.
 /// </exception>
 public static Hg3 ExtractHg3AndImages(KifintStream kifintStream, KifintEntry entry, string directory,
                                       bool expand)
 {
     if (directory == null)
     {
         throw new ArgumentNullException(nameof(directory));
     }
     byte[] buffer = Extract(kifintStream, entry);
     using (MemoryStream ms = new MemoryStream(buffer))
         return(Hg3.ExtractImages(ms, entry.FileName, directory, expand));
 }
Beispiel #2
0
        /// <summary>
        ///  Constructs an HG-3 image with the specified file name, image index, <see cref="Hg3.HG3STDINFO"/>, and
        ///  bitmap frames.
        /// </summary>
        /// <param name="imageIndex">The frame index of the image.</param>
        /// <param name="stdInfo">The HG3STDINFO struct containing image dimension information.</param>
        /// <param name="frameOffsets">The frame offsets for each frame entry in the HG-3 file.</param>
        /// <param name="hg3">The HG-3 containing this image set.</param>
        internal Hg3Image(int imageIndex, Hg3.HG3STDINFO stdInfo, long[] frameOffsets, Hg3 hg3)
        {
            Hg3          = hg3;
            ImageIndex   = imageIndex;
            FrameOffsets = Array.AsReadOnly(frameOffsets);
            FrameCount   = FrameOffsets.Count;           // Todo: Eliminate frame offsets

            Width           = stdInfo.Width;
            Height          = stdInfo.Height;
            TotalWidth      = stdInfo.TotalWidth;
            TotalHeight     = stdInfo.TotalHeight;
            OffsetX         = stdInfo.OffsetX;
            OffsetY         = stdInfo.OffsetY;
            DepthBits       = stdInfo.DepthBits;
            HasTransparency = stdInfo.HasTransparency;
            Center          = stdInfo.Center;
            Baseline        = stdInfo.Baseline;
        }
 /// <summary>
 ///  Extracts the HG-3 image information ONLY from open KIFINT archive stream and does not extract the actual
 ///  images.
 /// </summary>
 /// <param name="kifintStream">The stream to the open KIFINT archive.</param>
 /// <param name="entry">The KIFINT entry used to locate the file.</param>
 /// <returns>The extracted <see cref="Hg3"/> information.</returns>
 ///
 /// <exception cref="ArgumentNullException">
 ///  <paramref name="kifintStream"/> or <paramref name="entry"/> is null.
 /// </exception>
 public static Hg3 ExtractHg3(KifintStream kifintStream, KifintEntry entry)
 {
     byte[] buffer = Extract(kifintStream, entry);
     using (MemoryStream ms = new MemoryStream(buffer))
         return(Hg3.Extract(ms, entry.FileName));
 }
Beispiel #4
0
        private static Hg3 Extract(Stream stream, string fileName, string directory, bool saveFrames, bool expand)
        {
            BinaryReader reader = new BinaryReader(stream);
            HG3HDR       hdr    = reader.ReadUnmanaged <HG3HDR>();

            if (hdr.Signature != "HG-3")
            {
                throw new UnexpectedFileTypeException(fileName, "HG-3");
            }

            //int backtrack = Marshal.SizeOf<HG3TAG>() - 1;
            List <KeyValuePair <HG3STDINFO, List <long> > > imageOffsets = new List <KeyValuePair <HG3STDINFO, List <long> > >();

            for (int i = 0; ; i++)
            {
                // NEW-NEW METHOD: We now know the next offset ahead
                // of time from the HG3OFFSET we're going to read.
                // Usually skips 0 bytes, otherwise usually 1-7 bytes.
                long      startPosition = stream.Position;
                HG3OFFSET offset        = reader.ReadUnmanaged <HG3OFFSET>();

                HG3TAG tag = reader.ReadUnmanaged <HG3TAG>();
                if (!HG3STDINFO.HasTagSignature(tag.Signature))
                {
                    throw new Exception("Expected \"stdinfo\" tag!");
                }

                // NEW METHOD: Keep searching for the next stdinfo
                // This way we don't miss any images

                /*int offset = 0;
                 * while (!tag.Signature.StartsWith("stdinfo")) {
                 *      if (stream.IsEndOfStream())
                 *              break;
                 *      stream.Position -= backtrack;
                 *      tag = reader.ReadStruct<HG3TAG>();
                 *      offset++;
                 * }
                 * if (stream.IsEndOfStream())
                 *      break;*/

                // OLD METHOD: Missed entries in a few files
                //if (!tag.signature.StartsWith(StdInfoSignature))
                //	break;

                HG3STDINFO stdInfo = reader.ReadUnmanaged <HG3STDINFO>();

                List <long> frameOffsets = new List <long>();
                imageOffsets.Add(new KeyValuePair <HG3STDINFO, List <long> >(stdInfo, frameOffsets));

                while (tag.OffsetNext != 0)
                {
                    tag = reader.ReadUnmanaged <HG3TAG>();

                    string signature = tag.Signature;
                    if (HG3IMG.HasTagSignature(signature))                       // "img####"
                    {
                        frameOffsets.Add(stream.Position);
                        // Skip this tag
                        stream.Position += tag.Length;
                    }

                    /*else if (HG3ATS.HasTagSignature(signature)) { // "ats####"
                     *      // Skip this tag
                     *      stream.Position += tag.Length;
                     * }
                     * else if (HG3CPTYPE.HasTagSignature(signature)) { // "cptype"
                     *      // Skip this tag
                     *      stream.Position += tag.Length;
                     * }
                     * else if (HG3IMG_AL.HasTagSignature(signature)) { // "img_al"
                     *      // Skip this tag
                     *      stream.Position += tag.Length;
                     * }
                     * else if (HG3IMG_JPG.HasTagSignature(signature)) { // "img_jpg"
                     *      // Skip this tag
                     *      stream.Position += tag.Length;
                     * }
                     * else if (HG3IMGMODE.HasTagSignature(signature)) { // "imgmode"
                     *      // Skip this tag
                     *      stream.Position += tag.Length;
                     * }*/
                    else
                    {
                        // Skip this unknown tag
                        stream.Position += tag.Length;
                    }
                }

                if (offset.OffsetNext == 0)
                {
                    break;                     // End of stream
                }
                stream.Position = startPosition + offset.OffsetNext;
            }

            HG3STDINFO[] stdInfos        = imageOffsets.Select(p => p.Key).ToArray();
            long[][]     allFrameOffsets = imageOffsets.Select(p => p.Value.ToArray()).ToArray();
            Hg3          hg3             = new Hg3(Path.GetFileName(fileName), hdr, stdInfos, allFrameOffsets, saveFrames && expand);

            // Save any frames after we've located them all.
            // This way we truely know if something is an animation.
            if (saveFrames)
            {
                for (int imgIndex = 0; imgIndex < hg3.Count; imgIndex++)
                {
                    HG3STDINFO stdInfo  = stdInfos[imgIndex];
                    Hg3Image   hg3Image = hg3.Images[imgIndex];
                    for (int frmIndex = 0; frmIndex < hg3Image.FrameCount; frmIndex++)
                    {
                        stream.Position = hg3Image.FrameOffsets[frmIndex];
                        HG3IMG imghdr  = reader.ReadUnmanaged <HG3IMG>();
                        string pngFile = hg3.GetFrameFilePath(directory, imgIndex, frmIndex);
                        ExtractBitmap(reader, stdInfo, imghdr, expand, pngFile);
                    }
                }
            }

            return(hg3);
        }
Beispiel #5
0
 /// <summary>
 ///  Gets the file path for the PNG image with the specified image and frame indecies.
 /// </summary>
 /// <param name="directory">The directory of the <see cref="Hg3"/> images.</param>
 /// <param name="frmIndex">
 ///  The second index, which is associated to a frame inside an <see cref="Hg3Image"/>.
 /// </param>
 /// <returns>The file path of the frame.</returns>
 public string GetFrameFilePath(string directory, int frmIndex)
 {
     return(Hg3.GetFrameFilePath(directory, ImageIndex, frmIndex));
 }
Beispiel #6
0
 /// <summary>
 ///  Gets the file name for the PNG image with the specified image and frame indecies.
 /// </summary>
 /// <param name="frmIndex">
 ///  The second index, which is associated to a frame inside an <see cref="Hg3Image"/>.
 /// </param>
 /// <returns>The file name of the frame.</returns>
 public string GetFrameFileName(int frmIndex)
 {
     return(Hg3.GetFrameFileName(ImageIndex, frmIndex));
 }