Example #1
0
        public WTPFile(string filename, ChunkyStructureCollection col) : base(filename, col)
        {
            ChunkyFolder       folder   = (ChunkyFolder)col[0].RootChunks[0];
            int                children = folder.Children.Count;
            ChunkyChunk        chunk    = null;
            ChunkyDataINFOTPAT info     = null;

            for (int i = 0; i < children; i++)
            {
                chunk = folder.Children[i];

                if (chunk is ChunkyDataINFOTPAT)
                {
                    info   = (ChunkyDataINFOTPAT)chunk;
                    width  = info.Width;
                    height = info.Height;
                }
            }
        }
Example #2
0
        public ChunkyFolder(string ID_in, int version_in, string name_in, byte[] innerData) : base(ChunkyChunkType.Folder, ID_in, version_in, name_in)
        {
            children = new ChunkyCollection(this);
            MemoryStream ms = new MemoryStream(innerData, false);
            BinaryReader br = new BinaryReader(ms);

            ChunkyChunk        chunk = null;
            ChunkyDataATTR     attr  = null;
            ChunkyDataINFOTPAT info  = null;

            int pos = 0;

            while (pos < innerData.Length)
            {
                br.BaseStream.Seek(pos, SeekOrigin.Begin);
                chunk = RelicChunkReader.ReadChunkyChunk(br.ReadBytes(innerData.Length - pos), ID_in);
                children.Add(chunk);

                if (chunk is ChunkyDataATTR)
                {
                    attr = (ChunkyDataATTR)chunk;
                }
                else if (chunk is ChunkyDataINFOTPAT)
                {
                    info = (ChunkyDataINFOTPAT)chunk;
                }
                else if (attr != null && chunk is ChunkyDataDATA)
                {
                    ((ChunkyDataDATA)chunk).Attributes = attr;
                }
                else if (info != null && chunk is ChunkyDataLayer)
                {
                    ((ChunkyDataLayer)chunk).Info = info;
                }

                pos += chunk.Length;
            }
        }
Example #3
0
        public byte[] CreateCompositeTGABytes(LayerCollection colours, string badgePath, string bannerPath)
        {
            if (colours[PTLD_Layers.Dirt].Length != 3)
            {
                throw new InvalidOperationException("LayerCollection 'colours' must contain RGB colour data in a 3-byte array");
            }

            FileInfo     file = null;
            BinaryReader br   = null;

            byte[] badge  = new byte[64 * 64 * 4];
            byte[] banner = new byte[64 * 96 * 4];
            byte[] temp;

            CompilationEvent("Loading badge");
            if (File.Exists(badgePath))
            {
                file = new FileInfo(badgePath);
                br   = new BinaryReader(file.OpenRead());
                temp = br.ReadBytes((int)file.Length);
                br.Close();

                if ((temp[12] + (temp[13] << 8)) != 64 || (temp[14] + (temp[15] << 8)) != 64)
                {
                    CompilationEvent("Invalid badge image - badge must be a 64x64 pixel 24/32-bit TGA image", true);
                }
                else if (!((temp[16] == 32 || temp[16] == 24) && temp[2] == 2))
                {
                    CompilationEvent("Invalid badge image - badge must be a 64x64 pixel 24/32-bit TGA image", true);
                }
                else
                {
                    Buffer.BlockCopy(ImageConverter.TGAto32bitTGA(temp), 18, badge, 0, badge.Length);
                }
            }
            else
            {
                CompilationEvent("Invalid badge path - file must exist. Using blank badge.", true);
            }

            CompilationEvent("Loading banner");
            if (File.Exists(bannerPath))
            {
                file = new FileInfo(bannerPath);
                br   = new BinaryReader(file.OpenRead());
                temp = br.ReadBytes((int)file.Length);
                br.Close();


                if ((temp[12] + (temp[13] << 8)) != 64 || (temp[14] + (temp[15] << 8)) != 96)
                {
                    CompilationEvent("Invalid banner image - banner must be a 64x96 pixel 24/32-bit TGA image", true);
                }
                else if (!((temp[16] == 32 || temp[16] == 24) && temp[2] == 2))
                {
                    CompilationEvent("Invalid banner image - banner must be a 64x64 pixel 24/32-bit TGA image", true);
                }
                else
                {
                    Buffer.BlockCopy(ImageConverter.TGAto32bitTGA(temp), 18, banner, 0, banner.Length);
                }
            }
            else
            {
                CompilationEvent("Invalid banner path - file must exist. Using blank badge.", true);
            }

            ChunkyFolder root = (ChunkyFolder)this.ChunkyStructures[0].RootChunks[0];

            ChunkyChunk        chunk       = null;
            ChunkyDataPTLD     ptld        = null;
            ChunkyDataPTBN     bannerLayer = null;
            ChunkyDataPTBD     badgeLayer  = null;
            ChunkyDataINFOTPAT info        = (ChunkyDataINFOTPAT)root.Children[0];
            LayerCollection    layers      = new LayerCollection(info.Width * info.Height);

            byte[] mainImage = new byte[info.Width * info.Height];

            int badge_bottom = int.MaxValue;
            int badge_top    = int.MaxValue;
            int badge_left   = int.MaxValue;
            int badge_right  = int.MaxValue;

            int banner_bottom = int.MaxValue;
            int banner_top    = int.MaxValue;
            int banner_left   = int.MaxValue;
            int banner_right  = int.MaxValue;

            CompilationEvent("Loading colour layers");
            for (int i = 0; i < root.Children.Count; i++)
            {
                chunk = root.Children[i];

                if (chunk is ChunkyDataPTLD)
                {
                    ptld = (ChunkyDataPTLD)root.Children[i];
                    layers[(int)ptld.Layer] = ptld.GetColourBytes();
                }
                else if (chunk is ChunkyDataPTBD)
                {
                    badgeLayer   = (ChunkyDataPTBD)chunk;
                    badge_bottom = (int)badgeLayer.Pos_y;
                    badge_top    = badge_bottom + (int)badgeLayer.Height;
                    badge_left   = (int)badgeLayer.Pos_x;
                    badge_right  = badge_left + (int)badgeLayer.Width;
                }
                else if (chunk is ChunkyDataPTBN)
                {
                    bannerLayer   = (ChunkyDataPTBN)chunk;
                    banner_bottom = (int)bannerLayer.Pos_y;
                    banner_top    = banner_bottom + (int)bannerLayer.Height;
                    banner_left   = (int)bannerLayer.Pos_x;
                    banner_right  = banner_left + (int)bannerLayer.Width;
                }
                else if (chunk is ChunkyFolder)
                {
                    mainImage = ((ChunkyData)((ChunkyFolder)chunk).Children[1]).GetDataBytes();
                }
            }

            int bytePos       = 0;
            int bytePos32bit  = 0;
            int bytePosBadge  = 0;
            int bytePosBanner = 0;

            byte[] badgeByte;
            byte[] bannerByte;
            double ratio;
            double ratio2;
            double ratio3;
            double ratioTC;
            double tempByte    = 0;
            double extra       = 0;
            int    badge_width = 0;

            if (badgeLayer != null)
            {
                badge_width = (int)badgeLayer.Width;
            }

            int banner_width = 0;

            if (bannerLayer != null)
            {
                banner_width = (int)bannerLayer.Width;
            }

            CompilationEvent("Compiling TGA");
            for (int i = 0; i < info.Height; i++)
            {
                for (int j = 0; j < info.Width; j++)
                {
                    bytePos      = (i * info.Width) + j;
                    bytePos32bit = bytePos * 4;
                    ratio        = layers[PTLD_Layers.Dirt][bytePos] / 255.0;

                    if (badge_left <= j && badge_right > j && badge_bottom <= i && badge_top > i)
                    {
                        bytePosBadge = ((i - badge_bottom) * badge_width + (j - badge_left)) * 4;

                        ratio2    = (badge[bytePosBadge + 3] / 255.0);
                        badgeByte = new byte[] { badge[bytePosBadge], badge[bytePosBadge + 1], badge[bytePosBadge + 2] };
                    }
                    else
                    {
                        ratio2    = 0;
                        badgeByte = new byte[3];
                    }

                    if (banner_left <= j && banner_right > j && banner_bottom <= i && banner_top > i)
                    {
                        bytePosBanner = ((i - banner_bottom) * banner_width + (j - banner_left)) * 4;

                        ratio3     = (banner[bytePosBanner + 3] / 255.0);
                        bannerByte = new byte[] { banner[bytePosBanner], banner[bytePosBanner + 1], banner[bytePosBanner + 2] };
                    }
                    else
                    {
                        ratio3     = 0;
                        bannerByte = new byte[3];
                    }

                    ratioTC = 1 - ratio;

                    ratio2  = ratioTC * ratio2;
                    ratio3  = ratioTC * ratio3;
                    ratioTC = (ratioTC - ratio2 - ratio3) * 2;
                    extra   = 0;

                    //TGA files run in reverse - little-endian ARGB, which ends up as BGRA in the file

                    //red
                    tempByte = (ratio * mainImage[bytePos32bit + 2]) + (ratioTC) * ((colours[PTLD_Layers.Primary][0] * layers[PTLD_Layers.Primary][bytePos] / 255.0) +
                                                                                    (colours[PTLD_Layers.Secondary][0] * layers[PTLD_Layers.Secondary][bytePos] / 255.0) +
                                                                                    (colours[PTLD_Layers.Weapon][0] * layers[PTLD_Layers.Weapon][bytePos] / 255.0) +
                                                                                    (colours[PTLD_Layers.Trim][0] * layers[PTLD_Layers.Trim][bytePos] / 255.0) +
                                                                                    (colours[PTLD_Layers.Eyes][0] * layers[PTLD_Layers.Eyes][bytePos] / 255.0)) + ratio2 * badgeByte[2] + ratio3 * bannerByte[2];

                    if (tempByte > byte.MaxValue)
                    {
                        //CompilationEvent("Colour overflow at X:"+j.ToString()+", Y:"+i.ToString()+". Colour will show as Magenta or other bright colour with some colour schemes.", true);
                        mainImage[bytePos32bit + 2] = byte.MaxValue;
                        extra = (tempByte - byte.MaxValue);
                    }
                    else
                    {
                        mainImage[bytePos32bit + 2] = (byte)tempByte;
                    }

                    //green
                    tempByte = (ratio * mainImage[bytePos32bit + 1]) + (ratioTC) * ((colours[PTLD_Layers.Primary][1] * layers[PTLD_Layers.Primary][bytePos] / 255.0) +
                                                                                    (colours[PTLD_Layers.Secondary][1] * layers[PTLD_Layers.Secondary][bytePos] / 255.0) +
                                                                                    (colours[PTLD_Layers.Weapon][1] * layers[PTLD_Layers.Weapon][bytePos] / 255.0) +
                                                                                    (colours[PTLD_Layers.Trim][1] * layers[PTLD_Layers.Trim][bytePos] / 255.0) +
                                                                                    (colours[PTLD_Layers.Eyes][1] * layers[PTLD_Layers.Eyes][bytePos] / 255.0)) + extra + ratio2 * badgeByte[1] + ratio3 * bannerByte[1];

                    if (tempByte > byte.MaxValue)
                    {
                        //CompilationEvent("Colour overflow at X:"+j.ToString()+", Y:"+i.ToString()+". Colour will show as Magenta or other bright colour with some colour schemes.", true);
                        mainImage[bytePos32bit + 1] = byte.MaxValue;
                        extra    = extra + tempByte - byte.MaxValue;
                        tempByte = mainImage[bytePos32bit + 2] + extra;
                        if (tempByte > byte.MaxValue)
                        {
                            tempByte = byte.MaxValue;
                        }
                        mainImage[bytePos32bit + 2] = (byte)tempByte;
                    }
                    else
                    {
                        mainImage[bytePos32bit + 1] = (byte)tempByte;
                    }

                    //blue
                    tempByte = (ratio * mainImage[bytePos32bit]) + (ratioTC) * ((colours[PTLD_Layers.Primary][2] * layers[PTLD_Layers.Primary][bytePos] / 255.0) +
                                                                                (colours[PTLD_Layers.Secondary][2] * layers[PTLD_Layers.Secondary][bytePos] / 255.0) +
                                                                                (colours[PTLD_Layers.Weapon][2] * layers[PTLD_Layers.Weapon][bytePos] / 255.0) +
                                                                                (colours[PTLD_Layers.Trim][2] * layers[PTLD_Layers.Trim][bytePos] / 255.0) +
                                                                                (colours[PTLD_Layers.Eyes][2] * layers[PTLD_Layers.Eyes][bytePos] / 255.0)) + extra + ratio2 * badgeByte[0] + ratio3 * bannerByte[0];

                    if (tempByte > byte.MaxValue)
                    {
                        //CompilationEvent("Colour overflow at X:"+j.ToString()+", Y:"+i.ToString()+". Colour will show as Magenta or other bright colour with some colour schemes.", true);
                        mainImage[bytePos32bit] = byte.MaxValue;
                        extra    = extra + tempByte - byte.MaxValue;
                        tempByte = mainImage[bytePos32bit + 2] + extra;
                        if (tempByte > byte.MaxValue)
                        {
                            tempByte = byte.MaxValue;
                        }
                        mainImage[bytePos32bit + 2] = (byte)tempByte;
                        tempByte = mainImage[bytePos32bit + 1] + extra;
                        if (tempByte > byte.MaxValue)
                        {
                            tempByte = byte.MaxValue;
                        }
                        mainImage[bytePos32bit + 1] = (byte)tempByte;
                    }
                    else
                    {
                        mainImage[bytePos32bit] = (byte)tempByte;
                    }
                }
            }

            return(mainImage);
        }