private static void ExtractHg3ImageJpegAlpha(BinaryReader reader, Hg3FrameInfo frameInfo, HgxOptions options,
                                                     string pngFile)
        {
            HG3STDINFO std = frameInfo.StdInfo;
            HG3IMG_AL  img = frameInfo.ImgAl.Data;
            HG3TAG     tag = frameInfo.ImgJpg.Tag;

            reader.BaseStream.Position = frameInfo.ImgAl.Offset;

            // WGC handles bad alpha buffer errors gracefully, so we should too
            byte[] alphaBuffer;
            try {
                alphaBuffer = Zlib.Decompress(reader, img.CompressedLength, img.DecompressedLength);
            } catch (ZlibException ex) {
                if (ex.Result == ZResult.DataError || ex.Result == ZResult.BufferError)
                {
                    alphaBuffer = ex.OutputBuffer;
                }
                else
                {
                    throw;
                }
            }

            reader.BaseStream.Position = frameInfo.ImgJpg.Offset;

            byte[] buffer = reader.ReadBytes(tag.Length);

            if (!CatDebug.SpeedTestHgx)
            {
                WriteJpegAlphaMaskToPng(buffer, alphaBuffer, std, options, pngFile);
            }
        }
        private static void ExtractHg3ImageJpeg(BinaryReader reader, Hg3FrameInfo frameInfo, HgxOptions options,
                                                string pngFile)
        {
            HG3STDINFO std = frameInfo.StdInfo;
            HG3TAG     tag = frameInfo.ImgJpg.Tag;

            reader.BaseStream.Position = frameInfo.ImgJpg.Offset;

            byte[] buffer = reader.ReadBytes(tag.Length);

            if (!CatDebug.SpeedTestHgx)
            {
                WriteJpegToPng(buffer, std, options, pngFile);
            }
        }
示例#3
0
        public static string[] Run(Stream stream, string hg3File, string outputDir,
                                   string fileName, bool expand)
        {
            BinaryReader reader = new BinaryReader(stream);
            HG3HDR       hdr    = reader.ReadStruct <HG3HDR>();

            if (hdr.Signature != "HG-3")
            {
                throw new InvalidFileException(Path.GetFileName(hg3File), "HG3");
            }

            List <string> files     = new List <string>();
            int           backtrack = Marshal.SizeOf <HG3TAG>() - 1;

            for (int i = 0; true; i++)
            {
                HG3TAG tag = reader.ReadStruct <HG3TAG>();

                // NEW METHOD: Keep searching for the next stdinfo
                // This way we don't miss any images
                while (!tag.Signature.StartsWith("stdinfo"))
                {
                    if (stream.IsEndOfStream())
                    {
                        break;
                    }
                    stream.Position -= backtrack;
                    tag              = reader.ReadStruct <HG3TAG>();
                }
                if (stream.IsEndOfStream())
                {
                    break;
                }

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

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

                int imgIndex = 0;

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

                    string pngFile = Path.Combine(outputDir, MakeFileName(
                                                      fileName, i > 0 || hdr.EntryCount > 0, i, imgIndex++));

                    /*if (tag.Signature.StartsWith("img_al")) {
                     *      // Skip this tag
                     *      stream.Position += tag.Length;
                     *      HG3IMGAL imghdr = reader.ReadStruct<HG3IMGAL>();
                     *
                     *      int length = imghdr.length;
                     *      byte[] buffer = reader.ReadBytes(length);
                     *
                     *      int outLength = imghdr.original_length;
                     *      byte[] outBuffer = reader.ReadBytes(outLength);
                     *
                     *      Uncompress(outBuffer, ref outLength, buffer, length);
                     *
                     *      files.Add(pngFile);
                     *      WritePng(pngFile,
                     *              outBuffer,
                     *              stdInfo.width,
                     *              stdInfo.height,
                     *              1,
                     *              true);
                     * }
                     * else if (tag.Signature.StartsWith("img_jpg")) {
                     *      // Skip this tag
                     *      stream.Position += tag.Length;
                     * }
                     * else if (tag.Signature == "imgmode") {
                     *      // Skip this tag
                     *      stream.Position += tag.Length;
                     * }
                     * else */if (Regex.IsMatch(tag.Signature, @"img\d+"))
                    {
                        HG3IMG imghdr = reader.ReadStruct <HG3IMG>();

                        files.Add(pngFile);
                        ProcessImage(reader,
                                     pngFile,
                                     stdInfo,
                                     imghdr,
                                     expand);

                        /*stdInfo.Width,
                         * stdInfo.Height,
                         * stdInfo.DepthBits / 8,
                         * stdInfo.TotalWidth,
                         * stdInfo.TotalHeight,
                         * stdInfo.OffsetX,
                         * stdInfo.OffsetY,
                         * imghdr.DataLength,
                         * imghdr.OriginalDataLength,
                         * imghdr.CmdLength,
                         * imghdr.OriginalCmdLength);*/
                    }
                    else
                    {
                        // Skip this tag
                        stream.Position += tag.Length;
                    }
                }

                stream.Position += 8;
            }

            return(files.ToArray());
        }
        private static Hg3FrameInfo ReadHg3FrameInfo(BinaryReader reader, HGXHDR hdr, bool frameOnly)
        {
            Stream stream      = reader.BaseStream;
            long   frameOffset = stream.Position;

            HG3FRAMEHDR frameHdr = reader.ReadUnmanaged <HG3FRAMEHDR>();

            long   tagStartPosition = stream.Position;
            HG3TAG tag = reader.ReadUnmanaged <HG3TAG>();

            if (!HG3STDINFO.HasTagSignature(tag.Signature))
            {
                throw new Exception("Expected \"stdinfo\" tag!");
            }

            HG3STDINFO   stdInfo   = reader.ReadUnmanaged <HG3STDINFO>();
            Hg3FrameInfo frameInfo = new Hg3FrameInfo(frameHdr, stdInfo, frameOffset);

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

                string signature = tag.Signature;

                if (HG3IMG.HasTagSignature(signature, out int imdId))                   // "img####"
                {
                    HG3IMG img = reader.ReadUnmanaged <HG3IMG>();
                    frameInfo.AddTagImg(stream, tag, img, imdId);
                }
                else if (HG3IMG_AL.HasTagSignature(signature))                   // "img_al"
                {
                    HG3IMG_AL img = reader.ReadUnmanaged <HG3IMG_AL>();
                    frameInfo.AddTagImg(stream, tag, img, 0);
                }
                else if (HG3IMG_JPG.HasTagSignature(signature))                   // "img_jpg"
                // There is no image info, reading it would increment by one byte which we don't want
                {
                    frameInfo.AddTagImg(stream, tag, new HG3IMG_JPG(), 0);
                }
                else if (frameOnly)
                {
                    if (frameInfo.Type != Hg3ImageType.None)
                    {
                        return(frameInfo);
                    }
                }
                else if (HG3ATS.HasTagSignature(signature, out int atsId))                   // "ats####"
                {
                    HG3ATS ats = reader.ReadUnmanaged <HG3ATS>();
                    frameInfo.Ats.Add(atsId, ats);
                }
                else if (HG3CPTYPE.HasTagSignature(signature))                   // "cptype"
                {
                    HG3CPTYPE cpType = reader.ReadUnmanaged <HG3CPTYPE>();
                    frameInfo.CpType = cpType;
                }
                else if (HG3IMGMODE.HasTagSignature(signature))                   // "imgmode"
                {
                    HG3IMGMODE imgMode = reader.ReadUnmanaged <HG3IMGMODE>();
                    frameInfo.ImgMode = imgMode;
                }
                else
                {
                    Trace.WriteLine($"UNKNOWN TAG: \"{signature}\"");
                }
            }
            return(frameInfo);
        }
示例#5
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);
        }