예제 #1
0
        private void LoadHyruleTextures(List<byte> romData)
        {
            _palettes.Clear();
            _textures.Clear();
            cbTextures.Items.Clear();

            Palette palette = null;
            Texture texture = null;
            byte[] paletteData = new byte[0x20];
            byte[] textureData6464 = new byte[64 * 64 / 2]; //All textures are CI4, so we can calc the size like this
            byte[] textureData6432 = new byte[64 * 32 / 2];
            byte[] textureData3232 = new byte[32 * 32 / 2];
            byte[] textureData1616 = new byte[16 * 16 / 2];

            for (int i = 0; i < HyrulePaletteLocations.Length; i++)
            {
                romData.CopyTo(HyrulePaletteLocations[i], paletteData, 0, 0x20);//All are 16 colors
                palette = new Palette(HyrulePaletteLocations[i], paletteData);
                switch (i)
                {
                    case 0:
                    case 3:
                    case 6:
                        //64x64
                        romData.CopyTo(HyruleTextureLocations[i], textureData6464, 0, textureData6464.Length);
                        texture = new Texture(HyruleTextureLocations[i], textureData6464, Texture.ImageFormat.CI, Texture.PixelInfo.Size_4b,
                            64, 64, palette, 0);
                        break;
                    case 1:
                    case 4:
                        //64x32
                        romData.CopyTo(HyruleTextureLocations[i], textureData6432, 0, textureData6432.Length);
                        texture = new Texture(HyruleTextureLocations[i], textureData6432, Texture.ImageFormat.CI, Texture.PixelInfo.Size_4b,
                            64, 32, palette, 0);
                        break;
                    case 2:
                    case 5:
                    case 7:
                    case 9:
                    case 10:
                    case 11:
                        //32x32
                        romData.CopyTo(HyruleTextureLocations[i], textureData3232, 0, textureData3232.Length);
                        texture = new Texture(HyruleTextureLocations[i], textureData3232, Texture.ImageFormat.CI, Texture.PixelInfo.Size_4b,
                            32, 32, palette, 0);
                        break;
                    case 8:
                        //16x16
                        romData.CopyTo(HyruleTextureLocations[i], textureData1616, 0, textureData1616.Length);
                        texture = new Texture(HyruleTextureLocations[i], textureData1616, Texture.ImageFormat.CI, Texture.PixelInfo.Size_4b,
                            16, 16, palette, 0);
                        break;
                    case 12:
                        //64x16
                        romData.CopyTo(HyruleTextureLocations[i], textureData3232, 0, textureData3232.Length);
                        texture = new Texture(HyruleTextureLocations[i], textureData3232, Texture.ImageFormat.CI, Texture.PixelInfo.Size_4b,
                            64, 16, palette, 0);
                        break;
                }

                _palettes.Add(palette);
                _textures.Add(texture);

            }

            foreach (Texture text in _textures)
            {
                if (text.IsValidFormat)
                {
                    cbTextures.Items.Add(new TextureWrapper(cbTextures.Items.Count + 1, text));
                }
            }

            if(cbTextures.Items.Count > 0)
                cbTextures.SelectedIndex = 0;
            /*Combos: (Palette/Texture, all in 16 color-CI4 format)
                        8, 30 (64x64)
                        838, 860 (64x32)
                        C68, C90 (32x32)
                        E98, EC0 (64x64)
                        16C8, 16F0 (64x32)
                        1AF8, 1B20 (32x32)
                        1D28, 1D50 (64x64)
                        2558, 2580 (32x32)
                        2788, 27B0 (16x16)
                        2838, 2860 (32x32)
                        2A68, 2A90 (32x32)
                        2C98, 2CC0 (32x32)
                        2EC8, 2EF0 (64x16)
             */
        }
예제 #2
0
        public static byte[] CI8ToBinary(Bitmap bmp, Palette palette)
        {
            //Pixel size is 1 byte

            if (bmp == null)
                return null;

            if (palette == null || palette.Colors.Length < 256)
                return null;

            byte[] imgData = new byte[bmp.Width * bmp.Height];

            int[] paletteIDs = new int[256];
            for (int k = 0; k < 256; k++)
            {
                paletteIDs[k] = palette.Colors[k].ToArgb();
            }

            for (int i = 0; i < bmp.Width; i++)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    int index = i + j * bmp.Width;

                    Color pixel = bmp.GetPixel(i, j);
                    int pixelID = pixel.ToArgb();

                    byte palIndex = 0x00;
                    for (byte p = 0; p < paletteIDs.Length; p++)
                    {
                        if (paletteIDs[p] == pixelID)
                        {
                            palIndex = p;
                            break;
                        }
                    }

                    ByteHelper.WriteByte(palIndex, imgData, index);
                }
            }

            return imgData;
        }
예제 #3
0
        private static void GenerateNewPalette(Palette palette, Bitmap image, int colorCount)
        {
            //This can take a long time (not optimized), so be careful
            List<Color> colors = new List<Color>();

            for (int j = 0; j < image.Height; j++)
            {
                for (int i = 0; i < image.Width; i++)
                {
                    if (!colors.Contains(image.GetPixel(i, j)))
                        colors.Add(image.GetPixel(i, j));
                }
            }

            //Now that we have a huge list of colors, let's start going through them rapidly
            //List<double> minDist = new List<double>();
            //foreach (Color color in colors)
            //    minDist.Add(double.MaxValue);

            //while (colors.Count > colorCount)
            //{
            //    for (int i = 0; i < colors.Count; i++)
            //    {
            //        for (int j = i + 1; j < colors.Count; j++)
            //        {
            //            double dist = colors[i].ColorDistanceFrom(colors[j]);
            //            if (dist < minDist[i])
            //                minDist[i] = dist;
            //        }
            //    }

            //    //Find smallest one, clear it out
            //    double minvalue = minDist.Min();
            //    int removeIndex = minDist.IndexOf(minvalue);
            //    colors.RemoveAt(removeIndex);
            //    minDist.RemoveAt(removeIndex);

            //    //start over
            //    for (int i = 0; i < minDist.Count; i++)
            //        minDist[i] = double.MaxValue;
            //}

            PaletteMedianCutAnalyzer analyzer = new PaletteMedianCutAnalyzer();
            foreach (Color color in colors)
                analyzer.AddColor(color);

            //Now make the new palette
            byte[] newData = PaletteToBinary(analyzer.GetPalette(16));

            palette.RawData = newData;
        }
예제 #4
0
        public static byte[] CI4ToBinary(Bitmap bmp, Palette palette, int paletteIndex, bool generateNewPalette = false)
        {
            //Pixel size is 1/2 bytes
            if (bmp == null)
                return null;

            if (palette == null || palette.Colors.Length < 16)
                return null;

            if (generateNewPalette)
                GenerateNewPalette(palette, bmp, 16);

            byte[] imgData = new byte[bmp.Width * bmp.Height / 2];

            int[] paletteIDs = new int[16];
            for(int k = 0; k < 16; k++)
            {
                paletteIDs[k] = palette.Colors[k + 16 * paletteIndex].ToArgb();
            }

            for (int i = 0; i < bmp.Width; i+=2)
            {
                for (int j = 0; j < bmp.Height; j++)
                {
                    int index = (i + j * bmp.Width) / 2;

                    Color pixel = bmp.GetPixel(i, j);
                    int pixelID = pixel.ToArgb();

                    int index1 = -1;
                    byte closestIndex = 0;
                    double closestDist = double.MaxValue;
                    for (byte p = 0; p < paletteIDs.Length; p++)
                    {
                        if (paletteIDs[p] == pixelID)
                        {
                            index1 = p;
                            break;
                        }
                        else
                        {
                            //Get the dist to the color, and keep track of which is the best representation
                            double dist = pixel.ColorDistanceFrom(palette.Colors[p + 16 * paletteIndex]);

                            if (dist < closestDist)
                            {
                                closestDist = dist;
                                closestIndex = p;
                            }
                        }
                    }
                    if (index1 == -1)
                        index1 = closestIndex;

                    pixel = bmp.GetPixel(i + 1, j);
                    pixelID = pixel.ToArgb();

                    int index2 = -1;
                    closestIndex = 0;
                    closestDist = double.MaxValue;
                    for (byte p = 0; p < paletteIDs.Length; p++)
                    {
                        
                        if (paletteIDs[p] == pixelID)
                        {
                            index2 = p;
                            break;
                        }
                        else
                        {
                            //Get the dist to the color, and keep track of which is the best representation
                            double dist = pixel.ColorDistanceFrom(palette.Colors[p + 16 * paletteIndex]);

                            if (dist < closestDist)
                            {
                                closestDist = dist;
                                closestIndex = p;
                            }
                        }
                    }
                    if (index2 == -1)
                        index2 = closestIndex;

                    ByteHelper.WriteByte((byte)((index1 << 4) | index2), imgData, index);
                }
            }

            return imgData;
        }
예제 #5
0
        public static Bitmap BinaryToCI8(byte[] imgData, Palette palette, int width, int height)
        {
            //Pixel size is 1 byte
            if (width * height != imgData.Length)
                return null;

            if (palette == null || palette.Colors.Length < 256)
                return null;

            Bitmap bmp = new Bitmap(width, height);

            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    int index = (i + j * width);

                    byte CI = ByteHelper.ReadByte(imgData, index);

                    bmp.SetPixel(i, j, palette.Colors[CI]);
                }
            }

            return bmp;
        }
예제 #6
0
        //16b

        #endregion

        #region CI

        //4b, 8b
        public static Bitmap BinaryToCI4(byte[] imgData, Palette palette, int paletteIndex, int width, int height)
        {
            //Pixel size is 1/2 byte
            if (width / 2 * height != imgData.Length)
                return null;

            if (palette == null || palette.Colors.Length < 16)
                return null;
            
            Bitmap bmp = new Bitmap(width, height);

            for (int i = 0; i < width; i += 2)
            {
                for (int j = 0; j < height; j++)
                {
                    int index = (i + j * width) / 2;

                    byte CI = ByteHelper.ReadByte(imgData, index);
                    byte CI1 = (byte)(CI >> 4);
                    byte CI2 = (byte)(CI & 0x0F);

                    bmp.SetPixel(i, j, palette.Colors[CI1 + 16 * paletteIndex]);
                    bmp.SetPixel(i + 1, j, palette.Colors[CI2 + 16 * paletteIndex]);

                }
            }

            return bmp;
        }
예제 #7
0
        private static Texture ReadTextureFromTMem(TileDescriptor tile, Palette palette = null)
        {
            Texture newTexture;

            if (!TMEM.LoadedData.ContainsKey(tile.TMem))
                return null;

            //if (!tile.On)   //Not sure if used??
            //    return null;

            int offset = TMEM.LoadedData[tile.TMem].FileOffset;
            int sizeOfData = TMEM.LoadedData[tile.TMem].Size;

            int widthInBytes = 8 * tile.Line;

            double texelSize = 1;
            switch (tile.PixelSize)
            {
                case Texture.PixelInfo.Size_4b:
                    texelSize = 0.5;
                    break;
                case Texture.PixelInfo.Size_16b:
                    texelSize = 2;
                    break;
                case Texture.PixelInfo.Size_32b:
                    texelSize = 4;
                    break;
            }

            int widthInTexels = (int)Math.Round(widthInBytes / texelSize);
            int heightInTexels = sizeOfData / widthInTexels;

            byte[] data = new byte[sizeOfData];
            Array.Copy(TMEM.Data, tile.TMemInBytes, data, 0, sizeOfData);
            
            if(tile.ImageFormat == Texture.ImageFormat.CI)
                newTexture = new Texture(offset, data, tile.ImageFormat, tile.PixelSize,
                    widthInTexels, heightInTexels, palette, tile.Palette);
            else
                newTexture = new Texture(offset, data, tile.ImageFormat, tile.PixelSize,
                    widthInTexels, heightInTexels, null);

            tile.SettingsChanged = false;

            return newTexture;
        }
예제 #8
0
        private const int PALETTE_TMEM_OFFSET_IN_BYTES = 0x800; //offset * 8

        private static Palette ReadPaletteFromTMem()
        {
            Palette newPalette;

            if (!TMEM.LoadedData.ContainsKey(PALETTE_TMEM_OFFSET))
                return null;

            int offset = TMEM.LoadedData[PALETTE_TMEM_OFFSET].FileOffset;
            int sizeOfData = TMEM.LoadedData[PALETTE_TMEM_OFFSET].Size;

            byte[] data = new byte[sizeOfData];
            Array.Copy(TMEM.Data, PALETTE_TMEM_OFFSET_IN_BYTES, data, 0, sizeOfData);

            newPalette = new Palette(offset, data);

            return newPalette;
        }
예제 #9
0
        private static bool TryLoadExistingPalette(out Palette palette)
        {
            palette = null;

            if (TMEM.LoadedElements.ContainsKey(PALETTE_TMEM_OFFSET))
            {
                palette = (TMEM.LoadedElements[PALETTE_TMEM_OFFSET] as Palette);
                return true;
            }

            if (!TMEM.LoadedData.ContainsKey(PALETTE_TMEM_OFFSET))
                return false;

            LoadedTMemData tmemInfo = TMEM.LoadedData[PALETTE_TMEM_OFFSET];

            if (tmemInfo.SourceFile == null || !_foundPalettes.ContainsKey(tmemInfo.SourceFile))
                return false;

            for (int i = 0; i < _foundPalettes[tmemInfo.SourceFile].Count; i++)
            {
                if (_foundPalettes[tmemInfo.SourceFile][i].FileOffset == tmemInfo.FileOffset)
                {
                    palette = _foundPalettes[tmemInfo.SourceFile][i];
                    return true;
                }
            }

            return false;
        }
예제 #10
0
        public Texture(int index, byte[] bytes, ImageFormat format = ImageFormat.RGBA,
            PixelInfo pixel = PixelInfo.Size_32b, int width = 0, int height = 0, Palette palette = null,
            int paletteIndex = 0)
            : base(index, bytes)
        {
            Format = format;
            PixelSize = pixel;
            Width = width;
            Height = height;

            ImagePalette = palette;
            PaletteIndex = paletteIndex;
            
            //generate image
            _initializing = false;
            RawData = bytes;
        }