예제 #1
0
        private void WriteImage(IImage image)
        {
            if (characterMarshal.HasMarshalled(image))
            {
                /* Been there, done that. */
                return;
            }

            ImageBlob blob = image as ImageBlob;

            if (blob == null)
            {
                throw new SWFModellerException(SWFModellerError.Internal, "Can't write " + image.ToString());
            }

            switch (blob.DataFormat)
            {
            case Tag.DefineBitsJPEG2:
            case Tag.DefineBitsLossless:
            case Tag.DefineBitsLossless2:
                WriteBuffer blobBuffer = OpenTag(blob.DataFormat);
                blobBuffer.WriteUI16((uint)characterMarshal.GetIDFor(image));
                blobBuffer.WriteBytes(blob.FormattedBytes);
                CloseTag();
                break;

            case Tag.DefineBits:
                if (blob.JPEGTable != null)
                {
                    if (writtenJPEGTable != null && writtenJPEGTable != blob.JPEGTable)
                    {
                        /* ISSUE 16 */
                        throw new SWFModellerException(SWFModellerError.UnimplementedFeature,
                                                       "Can't process multiple JPEG encoding tables yet.");
                    }

                    WriteBuffer tables = OpenTag(Tag.JPEGTables);
                    tables.WriteBytes(blob.JPEGTable.TableData);
                    CloseTag();

                    writtenJPEGTable = blob.JPEGTable;
                }

                WriteBuffer bits = OpenTag(Tag.DefineBits);
                bits.WriteUI16((uint)characterMarshal.GetIDFor(image));
                bits.WriteBytes(blob.FormattedBytes);
                CloseTag();
                break;

            default:
                throw new SWFModellerException(SWFModellerError.Internal, "Can't write image format " + blob.DataFormat.ToString());;
            }
        }
예제 #2
0
        /// <summary>
        /// Takes a SWF object and turns it into a .swf binary file. It might seem nicer to
        /// write it to a stream, but the stream has a file length at the start which we only
        /// know once we've written it all out to a byte array anyway. Returning it as a
        /// chunk of data is simply more honest; an output stream would promise streaminess behind
        /// the scenes that we cannot deliver.
        /// </summary>
        /// <returns>The .swf data is returned as a byte array.</returns>
        public byte[] ToByteArray()
        {
            /* We start writing things mid-way through the header, at the point
             * where compression comes into effect. Once we've created and perhaps
             * compressed the data, we can write the first part of the header and
             * concatenate the rest. */

            writtenJPEGTable = null;

            /* The file contains tags, which can contain tags, each of which is prefixed with a length.
             * To track all this, we use a stack of writers, each with its own buffer. The first on the
             * stack is the buffer that will contain the file itself. */
            this.writers = new Stack <WriteBuffer>();
            this.swfOut  = new WriteBuffer(Tag.None, "swf");
            this.writers.Push(this.swfOut);

            this.swfOut.WriteRect(new Rect(0, this.swf.FrameWidth, 0, this.swf.FrameHeight));

            this.swfOut.WriteFIXED8(this.swf.Fps);
            this.swfOut.WriteUI16(this.swf.FrameCount);

            this.WriteTags();

            /* Ok, we basically have a SWF now. All we need to do is compress it and
             * stick a header on at the front... */

            byte[] body    = this.swfOut.Data;
            uint   fileLen = (uint)(body.Length + 8); /* Add the 8 bytes of header we haven't done yet. */

            if (this.options.Compressed)
            {
                MemoryStream         zbytes = new MemoryStream();
                DeflaterOutputStream zos    = new DeflaterOutputStream(zbytes);
                zos.Write(body, 0, body.Length);
                zos.Close();
                body = zbytes.ToArray();
            }

            MemoryStream      final       = new MemoryStream();
            SWFDataTypeWriter finalWriter = new SWFDataTypeWriter(final);

            finalWriter.WriteUI24(this.options.Compressed ? SIG_COMPRESSED : SIG_UNCOMPRESSED);

            /* ISSUE 27: Hard-coded SWF version 10. Technically this should be an option but
             * for now we don't want the headache of version-specific code. */
            finalWriter.WriteUI8(SWF_VERSION);

            finalWriter.WriteUI32(fileLen);

            finalWriter.Write(body, 0, body.Length);

            return(final.ToArray());
        }
예제 #3
0
        private bool ReadTag()
        {
            int  type;
            uint followingOffset;

            this.sdtr.ReadRECORDHEADER(out type, out followingOffset);
            uint startOffset = this.sdtr.Offset;

#if DEBUG
            Tag  _tag     = (Tag)type;
            bool isDefine = _tag == Tag.DefineShape ||
                            _tag == Tag.DefineShape3 ||
                            _tag == Tag.DefineShape4 ||
                            _tag == Tag.DefineSprite;
            this.MarkDumpOffset(
                "Body of " + _tag + " (" + type + ") len=" + (followingOffset - this.sdtr.Offset),
                isDefine);
            this.binaryDumpNest++;
            this.taglog.Add(_tag.ToString());
#endif

            switch ((Tag)type)
            {
            case Tag.End:
#if DEBUG
                this.binaryDumpNest--;
#endif
                return(false);

            case Tag.ShowFrame:
#if DEBUG
                this.MarkDumpOffset("");
#endif
                this.frameCursor++;
                break;

            case Tag.Protect:
                this.sdtr.Align8();
                if (followingOffset > this.sdtr.Offset)
                {
                    /*(void)*/ this.sdtr.ReadUI16();    /* Reserved. Assumed 0. */
                    this.swf.ProtectHash = this.sdtr.ReadString();
#if DEBUG
                    this.Log("Protect hash = " + this.swf.ProtectHash);
#endif
                }
                break;

            case Tag.SetBackgroundColor:
                this.swf.BackgroundColor = this.sdtr.ReadRGB();
                break;

            case Tag.PlaceObject:
                this.currentTimeline.GetFrame(this.frameCursor).AddTag(this.ReadPlaceObject(followingOffset));
                break;

            case Tag.PlaceObject2:
                this.currentTimeline.GetFrame(this.frameCursor).AddTag(this.ReadPlaceObject2());
                break;

            case Tag.RemoveObject2:
                this.currentTimeline.GetFrame(this.frameCursor).AddTag(this.ReadRemoveObject2());
                break;

            case Tag.DefineBits:
            case Tag.DefineBitsJPEG2:
            case Tag.DefineBitsLossless:
            case Tag.DefineBitsLossless2:
                this.ReadImageBlob((Tag)type, followingOffset);
                break;

            case Tag.JPEGTables:
                jpegTable = new JPEGTable(this.sdtr.ReadByteBlock((int)(followingOffset - this.sdtr.Offset)));
                break;

            case Tag.DefineSprite:
                this.ReadSprite();
                break;

            case Tag.DefineShape:
            case Tag.DefineShape2:
            case Tag.DefineShape3:
            case Tag.DefineShape4:
                this.ReadDefineShapeN((Tag)type, followingOffset);
                break;

            case Tag.DefineMorphShape:
            case Tag.DefineMorphShape2:
                this.ReadDefineMorphShape((Tag)type, followingOffset);
                break;

            case Tag.DefineSceneAndFrameLabelData:
                this.ReadSceneAndFrameLabelData();
                break;

            case Tag.DoABC:
                this.ReadDoABC(followingOffset);
                break;

            case Tag.SymbolClass:
                this.ReadSymbolClass();
                break;

            case Tag.Metadata:
                this.ReadXMLMetadata();
                break;

            case Tag.EnableDebugger2:
                this.ReadEnableDebugger2();
                break;

            case Tag.FrameLabel:
                this.currentTimeline.GetFrame(this.frameCursor).Label = this.sdtr.ReadString();
#if DEBUG
                this.Log("Frame label = " + this.currentTimeline.GetFrame(this.frameCursor).Label);
#endif

                break;

            case Tag.DefineFont3:
                this.ReadFont((Tag)type);
                break;

            case Tag.DefineFontAlignZones:
                this.ReadFontAlignZones();
                break;

            case Tag.DefineFontName:
                this.ReadFontName();
                break;

            case Tag.DefineText:
            case Tag.DefineText2:
                this.ReadText((Tag)type);
                break;

            case Tag.DefineEditText:
                this.ReadEditText();
                break;

            default:
                /* ISSUE 73 */
                throw new SWFModellerException(
                          SWFModellerError.UnimplementedFeature,
                          @"Unsupported tag type: " + type, swf.Context);
            }

            this.FinishTag(followingOffset);
#if DEBUG
            this.binaryDumpNest--;
#endif

            return(true);
        }
예제 #4
0
        /// <summary>
        /// Reads a SWF from the stream.
        /// </summary>
        /// <returns>A parsed SWF object</returns>
        public SWF ReadSWF(SWFContext ctx)
        {
#if DEBUG
            this.MarkDumpOffset("Start of file");
#endif

            this.jpegTable = null;

            this.sceneNotes      = new List <FrameNote>();
            this.frameLabelNotes = new List <FrameNote>();

            this.ReadHeader(ctx);

            this.fontDict = new Dictionary <int, SWFFont>();

            this.frameCursor = 1;

            bool as3 = false;
            if (this.version >= 8)
            {
#if DEBUG
                this.MarkDumpOffset("Start of file attributes tag");
#endif
                this.ReadFileAttributesTag(out as3);
            }

            if (!as3)
            {
                throw new SWFModellerException(
                          SWFModellerError.SWFParsing,
                          @"AS2 and under is not supported.", ctx);
            }

            this.swf             = new SWF(ctx, false);
            this.swf.FrameWidth  = this.frameSize.Width;
            this.swf.FrameHeight = this.frameSize.Height;
            this.swf.Fps         = this.fps;
            this.swf.FrameCount  = this.frameCount;

            this.currentTimeline = this.swf;

            bool hasMore = true;
            do
            {
                hasMore = this.ReadTag();
            }while (hasMore);

            foreach (FrameNote note in this.sceneNotes)
            {
                this.swf.GetFrame((int)note.frame).SceneName = note.note;
            }

            foreach (FrameNote note in this.frameLabelNotes)
            {
                this.swf.GetFrame((int)note.frame).Label = note.note;
            }

            foreach (string className in this.LateClassResolutions.Keys)
            {
                swf.MapClassnameToClip(className, this.LateClassResolutions[className]);
            }

            return(this.swf);
        }