This chunk type holds a color palette.
Inheritance: IffChunk
Exemple #1
0
 public void SetPalt(PALT p)
 {
     if (this.PaletteID != 0)
     {
         var old = Parent.ChunkParent.Get <PALT>(this.PaletteID);
         if (old != null)
         {
             old.References--;
         }
     }
     PaletteID = p.ChunkID;
     p.References++;
 }
        private void ReplaceSprite(Bitmap[] bmps, int frame)
        {
            var pixel = bmps[0];
            //first search pixel for the bounding rectangle.
            var plock = pixel.LockBits(new Rectangle(0, 0, pixel.Width, pixel.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            var pdat = new byte[plock.Stride * plock.Height];

            Marshal.Copy(plock.Scan0, pdat, 0, pdat.Length);
            int maxX = int.MinValue, maxY = int.MinValue,
                minX = int.MaxValue, minY = int.MaxValue;

            int index = 0;
            for (int y = 0; y < pixel.Height; y++)
            {
                for (int x = 0; x < pixel.Width; x++)
                {
                    if (!(pdat[index] == 0 && pdat[index+1] == 255 && pdat[index+2] == 255))
                    {
                        if (x < minX) minX = x;
                        if (x > maxX) maxX = x;
                        if (y < minY) minY = y;
                        if (y > maxY) maxY = y;
                    }
                    index += 4;
                }
            }

            pixel.UnlockBits(plock);

            var rect = (minX == int.MaxValue) ? new Rectangle() : new Rectangle(minX, minY, (maxX - minX) + 1, (maxY - minY) + 1);
            var px = rect.Width * rect.Height;

            var locks = new BitmapData[3];
            var data = new byte[3][];
            var pxOut = new Microsoft.Xna.Framework.Color[px];
            var depthOut = new byte[px];

            for (int i=0; i<3; i++)
            {
                locks[i] = bmps[i].LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                data[i] = new byte[locks[i].Stride * locks[i].Height];
                Marshal.Copy(locks[i].Scan0, data[i], 0, data[i].Length);
            }

            int scanStart = 0;
            int dstidx = 0;
            for (int y=0; y<locks[0].Height; y++)
            {
                int srcidx = scanStart;
                for (int j = 0; j < rect.Width; j++)
                {
                    pxOut[dstidx] = new Microsoft.Xna.Framework.Color(data[0][srcidx + 2], data[0][srcidx + 1], data[0][srcidx], data[1][srcidx]);
                    depthOut[dstidx] = data[2][srcidx];
                    srcidx += 4;
                    dstidx++;
                }
                scanStart += locks[0].Stride;
            }

            //set data first. we also want to get back the a palette we can change
            PALT targ = null;
            Microsoft.Xna.Framework.Color[] used;
            Content.Content.Get().Changes.BlockingResMod(new ResAction(() =>
            {
                var xnaRect = new Microsoft.Xna.Framework.Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
                used = GraphicChunk.Frames[frame].SetData(pxOut, depthOut, xnaRect);

                var ownPalt = GraphicChunk.ChunkParent.Get<PALT>(GraphicChunk.Frames[frame].PaletteID);
                ushort freePalt = GraphicChunk.ChunkID;
                if (GraphicChunk.Frames[frame].PaletteID != 0 && ownPalt != null && ownPalt.References == 1) targ = ownPalt;
                else
                {
                    var palts = GraphicChunk.ChunkParent.List<PALT>();
                    palts = (palts == null) ? new List<PALT>() : palts.OrderBy(x => x.ChunkID).ToList();
                    foreach (var palt in palts)
                    {
                        if (palt.ChunkID == freePalt) freePalt++;
                        if (palt.PalMatch(used) || palt.References == 0)
                        {
                            targ = palt;
                            break;
                        }
                    }
                }

                if (targ != null)
                {
                    //replace existing palt.
                    lock (targ)
                    {
                        if (targ.References == 0 || targ == ownPalt) targ.Colors = used;
                    }
                    Content.Content.Get().Changes.ChunkChanged(targ);
                    GraphicChunk.Frames[frame].SetPalt(targ);
                }
                else
                {
                    //we need to make a new PALT.
                    //a bit hacky for now
                    var nPalt = new PALT()
                    {
                        ChunkID = freePalt,
                        ChunkLabel = GraphicChunk.ChunkLabel + " Auto PALT",
                        AddedByPatch = true,
                        ChunkProcessed = true,
                        ChunkType = "PALT",
                        RuntimeInfo = ChunkRuntimeState.Modified,
                        Colors = used
                    };

                    GraphicChunk.ChunkParent.AddChunk(nPalt);
                    GraphicChunk.Frames[frame].SetPalt(nPalt);
                    Content.Content.Get().Changes.ChunkChanged(nPalt);
                }

            }, GraphicChunk));

            for (int i = 0; i < 3; i++)
                bmps[i].UnlockBits(locks[i]);
        }
Exemple #3
0
        /// <summary>
        /// Decodes this SPR2Frame.
        /// </summary>
        /// <param name="io">An IOBuffer instance used to read a SPR2Frame.</param>
        private void Decode(IoBuffer io)
        {
            var y = 0;
            var endmarker = false;

            var hasPixels = (this.Flags & 0x01) == 0x01;
            var hasZBuffer = (this.Flags & 0x02) == 0x02;
            var hasAlpha = (this.Flags & 0x04) == 0x04;

            var numPixels = this.Width * this.Height;
            if (hasPixels){
                this.PixelData = new Color[numPixels];
                this.PalData = new byte[numPixels];
            }
            if (hasZBuffer){
                this.ZBufferData = new byte[numPixels];
            }
            if (hasAlpha){
                this.AlphaData = new byte[numPixels];
            }

            var palette = Parent.ChunkParent.Get<PALT>(this.PaletteID);
            if (palette == null) palette = new PALT() { Colors = new Color[256] };
            palette.References++;
            var transparentPixel = palette.Colors[TransparentColorIndex];
            transparentPixel.A = 0;

            while (!endmarker)
            {
                var marker = io.ReadUInt16();
                var command = marker >> 13;
                var count = marker & 0x1FFF;

                switch (command)
                {
                    /** Fill with pixel data **/
                    case 0x00:
                        var bytes = count;
                        bytes -= 2;

                        var x = 0;

                        while (bytes > 0)
                        {
                            var pxMarker = io.ReadUInt16();
                            var pxCommand = pxMarker >> 13;
                            var pxCount = pxMarker & 0x1FFF;
                            bytes -= 2;

                            switch (pxCommand)
                            {
                                case 0x01:
                                case 0x02:
                                    var pxWithAlpha = pxCommand == 0x02;
                                    for (var col = 0; col < pxCount; col++)
                                    {
                                        var zValue = io.ReadByte();
                                        var pxValue = io.ReadByte();
                                        bytes -= 2;

                                        var pxColor = palette.Colors[pxValue];
                                        if (pxWithAlpha)
                                        {
                                            var alpha = io.ReadByte();
                                            pxColor.A = (byte)(alpha * 8.2258064516129032258064516129032);
                                            bytes--;
                                        }
                                        //this mode draws the transparent colour as solid for some reason.
                                        //fixes backdrop theater
                                        var offset = (y * Width) + x;
                                        this.PixelData[offset] = pxColor;
                                        this.PalData[offset] = pxValue;
                                        this.ZBufferData[offset] = zValue;
                                        x++;
                                    }
                                    if (pxWithAlpha)
                                    {
                                        /** Padding? **/
                                        if ((pxCount * 3) % 2 != 0){
                                            bytes--;
                                            io.ReadByte();
                                        }
                                    }
                                    break;
                                case 0x03:
                                    for (var col = 0; col < pxCount; col++)
                                    {
                                        var offset = (y * Width) + x;
                                        this.PixelData[offset] = transparentPixel;
                                        this.PalData[offset] = (byte)TransparentColorIndex;
                                        this.PixelData[offset].A = 0;
                                        if (hasZBuffer){
                                            this.ZBufferData[offset] = 255;
                                        }
                                        x++;
                                    }
                                    break;
                                case 0x06:
                                    for (var col = 0; col < pxCount; col++)
                                    {
                                        var pxIndex = io.ReadByte();
                                        bytes--;
                                        var offset = (y * Width) + x;
                                        var pxColor = palette.Colors[pxIndex];
                                        byte z = 0;

                                        //not sure if this should happen
                                        /*if (pxIndex == TransparentColorIndex)
                                        {
                                            pxColor.A = 0;
                                            z = 255;
                                        }*/
                                        this.PixelData[offset] = pxColor;
                                        this.PalData[offset] = pxIndex;
                                        if (hasZBuffer)
                                        {
                                            this.ZBufferData[offset] = z;
                                        }
                                        x++;
                                    }
                                    if (pxCount % 2 != 0)
                                    {
                                        bytes--;
                                        io.ReadByte();
                                    }
                                    break;
                            }
                        }

                        /** If row isnt filled in, the rest is transparent **/
                        while (x < Width)
                        {
                            var offset = (y * Width) + x;
                            if (hasZBuffer)
                            {
                                this.ZBufferData[offset] = 255;
                            }
                            x++;
                        }
                        break;
                    /**  Leave the next count rows in the color channel filled with the transparent color,
                     * in the z-buffer channel filled with 255, and in the alpha channel filled with 0. **/
                    case 0x04:
                        for (var row = 0; row < count; row++)
                        {
                            for (var col = 0; col < Width; col++)
                            {
                                var offset = ((y+row) * Width) + col;
                                if (hasPixels)
                                {
                                    this.PixelData[offset] = transparentPixel;
                                    this.PalData[offset] = (byte)TransparentColorIndex;
                                }
                                if (hasAlpha)
                                {
                                    this.PixelData[offset].A = 0;
                                }
                                if (hasZBuffer)
                                {
                                    ZBufferData[offset] = 255;
                                }
                            }
                        }
                        y += count - 1;
                        break;
                    case 0x05:
                        endmarker = true;
                        break;
                }
                y++;
            }
        }
Exemple #4
0
        /// <summary>
        /// Decodes this SPR2Frame.
        /// </summary>
        /// <param name="io">An IOBuffer instance used to read a SPR2Frame.</param>
        private void Decode(IoBuffer io)
        {
            var y         = 0;
            var endmarker = false;

            var hasPixels  = (this.Flags & 0x01) == 0x01;
            var hasZBuffer = (this.Flags & 0x02) == 0x02;
            var hasAlpha   = (this.Flags & 0x04) == 0x04;

            var numPixels = this.Width * this.Height;

            if (hasPixels)
            {
                this.PixelData = new Color[numPixels];
                this.PalData   = new byte[numPixels];
            }
            if (hasZBuffer)
            {
                this.ZBufferData = new byte[numPixels];
            }
            if (hasAlpha)
            {
                this.AlphaData = new byte[numPixels];
            }

            var palette = Parent.ChunkParent.Get <PALT>(this.PaletteID);

            if (palette == null)
            {
                palette = new PALT()
                {
                    Colors = new Color[256]
                }
            }
            ;
            palette.References++;
            var transparentPixel = palette.Colors[TransparentColorIndex];

            transparentPixel.A = 0;

            while (!endmarker)
            {
                var marker  = io.ReadUInt16();
                var command = marker >> 13;
                var count   = marker & 0x1FFF;

                switch (command)
                {
                /** Fill with pixel data **/
                case 0x00:
                    var bytes = count;
                    bytes -= 2;

                    var x = 0;

                    while (bytes > 0)
                    {
                        var pxMarker  = io.ReadUInt16();
                        var pxCommand = pxMarker >> 13;
                        var pxCount   = pxMarker & 0x1FFF;
                        bytes -= 2;

                        switch (pxCommand)
                        {
                        case 0x01:
                        case 0x02:
                            var pxWithAlpha = pxCommand == 0x02;
                            for (var col = 0; col < pxCount; col++)
                            {
                                var zValue  = io.ReadByte();
                                var pxValue = io.ReadByte();
                                bytes -= 2;

                                var pxColor = palette.Colors[pxValue];
                                if (pxWithAlpha)
                                {
                                    var alpha = io.ReadByte();
                                    pxColor.A = (byte)(alpha * 8.2258064516129032258064516129032);
                                    bytes--;
                                }
                                //this mode draws the transparent colour as solid for some reason.
                                //fixes backdrop theater
                                var offset = (y * Width) + x;
                                this.PixelData[offset]   = pxColor;
                                this.PalData[offset]     = pxValue;
                                this.ZBufferData[offset] = zValue;
                                x++;
                            }
                            if (pxWithAlpha)
                            {
                                /** Padding? **/
                                if ((pxCount * 3) % 2 != 0)
                                {
                                    bytes--;
                                    io.ReadByte();
                                }
                            }
                            break;

                        case 0x03:
                            for (var col = 0; col < pxCount; col++)
                            {
                                var offset = (y * Width) + x;
                                this.PixelData[offset]   = transparentPixel;
                                this.PalData[offset]     = (byte)TransparentColorIndex;
                                this.PixelData[offset].A = 0;
                                if (hasZBuffer)
                                {
                                    this.ZBufferData[offset] = 255;
                                }
                                x++;
                            }
                            break;

                        case 0x06:
                            for (var col = 0; col < pxCount; col++)
                            {
                                var pxIndex = io.ReadByte();
                                bytes--;
                                var  offset  = (y * Width) + x;
                                var  pxColor = palette.Colors[pxIndex];
                                byte z       = 0;

                                //not sure if this should happen

                                /*if (pxIndex == TransparentColorIndex)
                                 * {
                                 *  pxColor.A = 0;
                                 *  z = 255;
                                 * }*/
                                this.PixelData[offset] = pxColor;
                                this.PalData[offset]   = pxIndex;
                                if (hasZBuffer)
                                {
                                    this.ZBufferData[offset] = z;
                                }
                                x++;
                            }
                            if (pxCount % 2 != 0)
                            {
                                bytes--;
                                io.ReadByte();
                            }
                            break;
                        }
                    }

                    /** If row isnt filled in, the rest is transparent **/
                    while (x < Width)
                    {
                        var offset = (y * Width) + x;
                        if (hasZBuffer)
                        {
                            this.ZBufferData[offset] = 255;
                        }
                        x++;
                    }
                    break;

                /**  Leave the next count rows in the color channel filled with the transparent color,
                * in the z-buffer channel filled with 255, and in the alpha channel filled with 0. **/
                case 0x04:
                    for (var row = 0; row < count; row++)
                    {
                        for (var col = 0; col < Width; col++)
                        {
                            var offset = ((y + row) * Width) + col;
                            if (hasPixels)
                            {
                                this.PixelData[offset] = transparentPixel;
                                this.PalData[offset]   = (byte)TransparentColorIndex;
                            }
                            if (hasAlpha)
                            {
                                this.PixelData[offset].A = 0;
                            }
                            if (hasZBuffer)
                            {
                                ZBufferData[offset] = 255;
                            }
                        }
                    }
                    y += count - 1;
                    break;

                case 0x05:
                    endmarker = true;
                    break;
                }
                y++;
            }
        }
Exemple #5
0
 public void SetPalt(PALT p)
 {
     if (this.PaletteID != 0)
     {
         var old = Parent.ChunkParent.Get<PALT>(this.PaletteID);
         if (old != null) old.References--;
     }
     PaletteID = p.ChunkID;
     p.References++;
 }