Beispiel #1
0
        private void btnApply_Click(object sender, EventArgs e)
        {
            bool hasChanges = false;

            for (int i = 0; i < lbBefore.Items.Count; i++)
            {
                if (lbBefore.Items[i] != lbAfter.Items[i])
                {
                    hasChanges = true;
                    break;
                }
            }

            if (!hasChanges) //Quit out if no changes
            {
                this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
                return;
            }

            //if the mode is texture, then do something new.
            //if the mode is palette, then generate the palette BEFORE making the image

            if (Mode == SharedMode.Texture)
            {
                //IDEA: AVERAGE ALL THE IMAGES TOGETHER, THEN MAKE A CI PALETTE/TEXTURE FROM THAT. THEN WE HAVE OUR TEXTURE.
                //       AFTER THAT, WE NEED TO ASSIGN PALETTES TO IT. I GUESS WE CAN AVERAGE ALL COLORS THAT HIT EACH POINT
                //       FOR EACH IMAGE

                //Slow process
                Bitmap refImage = new Bitmap(Images[0].Image);

                int width      = Images[0].Image.Width;
                int height     = Images[0].Height;
                int pixelCount = width * height;
                int imageCount = lbAfter.Items.Count;
                int colorCount = Images[0].ImageReference.BasePalettes[0].Colors.Length;

                int[] redCount   = new int[pixelCount];
                int[] blueCount  = new int[pixelCount];
                int[] greenCount = new int[pixelCount];
                int[] alphaCount = new int[pixelCount];

                foreach (BitmapWrapper wrapper in lbAfter.Items)
                {
                    for (int j = 0; j < width; j++)
                    {
                        for (int i = 0; i < height; i++)
                        {
                            Color pixel = wrapper.BMP.GetPixel(i, j);
                            redCount[i + j * wrapper.BMP.Width]   += pixel.R;
                            greenCount[i + j * wrapper.BMP.Width] += pixel.G;
                            blueCount[i + j * wrapper.BMP.Width]  += pixel.B;
                            alphaCount[i + j * wrapper.BMP.Width] += pixel.A;
                        }
                    }
                }

                for (int j = 0; j < height; j++)
                {
                    for (int i = 0; i < width; i++)
                    {
                        refImage.SetPixel(i, j,
                                          Color.FromArgb(alphaCount[i + j * width] / imageCount,
                                                         redCount[i + j * width] / imageCount,
                                                         greenCount[i + j * width] / imageCount,
                                                         blueCount[i + j * width] / imageCount));
                    }
                }

                //Now do the set-texture palette search method
                Palette tempPalette      = new Palette(-1, new byte[colorCount * 2]);
                byte[]  finalTextureData = TextureConversion.ImageToBinary(Images[0].Format, Images[0].PixelSize, refImage, ref tempPalette, true);
                Images[0].ImageReference.Texture.RawData = finalTextureData;

                //Now take this and do some stupid shit
                for (int k = 0; k < imageCount; k++)
                {
                    redCount   = new int[colorCount];
                    greenCount = new int[colorCount];
                    blueCount  = new int[colorCount];
                    alphaCount = new int[colorCount];

                    Bitmap img = (Bitmap)lbAfter.Items[k];

                    for (int j = 0; j < height; j++)
                    {
                        for (int i = 0; i < width; i++)
                        {
                            Color color = img.GetPixel(i, j);

                            int textureNum = 0;
                            if (Images[k].PixelSize == Texture.PixelInfo.Size_8b)
                            {
                                textureNum = finalTextureData[i + j * height];
                            }
                            else
                            {
                                byte val = finalTextureData[(i + j * height) / 2];
                                if ((i + j * height) % 2 == 0)
                                {
                                    textureNum = val >> 4;
                                }
                                else
                                {
                                    textureNum = val & 0xF;
                                }
                            }

                            redCount[textureNum]   += color.R;
                            greenCount[textureNum] += color.G;
                            blueCount[textureNum]  += color.B;
                            alphaCount[textureNum] += color.A;
                        }
                    }

                    //Now that we have the colors added up, we calculate the new colors and that's our new palette!
                    Color[] colors = new Color[colorCount];

                    for (int i = 0; i < colorCount; i++)
                    {
                        colors[i] = Color.FromArgb(alphaCount[i] / imageCount,
                                                   redCount[i] / imageCount,
                                                   greenCount[i] / imageCount,
                                                   blueCount[i] / imageCount);
                    }

                    byte[] newPaletteData = TextureConversion.PaletteToBinary(colors);
                    Images[k].ImageReference.BasePalettes[0].RawData = newPaletteData;
                }
            }
            else
            {
                PaletteMedianCutAnalyzer paletteMaker = new PaletteMedianCutAnalyzer();
                foreach (BitmapWrapper wrapper in lbAfter.Items)
                {
                    for (int i = 0; i < wrapper.BMP.Width; i++)
                    {
                        for (int j = 0; j < wrapper.BMP.Height; j++)
                        {
                            paletteMaker.AddColor(wrapper.BMP.GetPixel(i, j));
                        }
                    }
                }

                Color[] colors         = paletteMaker.GetPalette(Images[0].ImageReference.BasePalettes[0].Colors.Length);
                byte[]  paletteData    = TextureConversion.PaletteToBinary(colors);
                Palette palette        = new Palette(-1, paletteData);
                byte[]  newPaletteData = palette.RawData;
                Images[0].ImageReference.BasePalettes[0].RawData = newPaletteData;

                if (Images[0].PaletteEncoding[0] == MK64Image.MK64ImageEncoding.MIO0)
                {
                    N64DataElement element;
                    if (!RomProject.Instance.Files[0].HasElementExactlyAt(Images[0].PaletteOffset[0], out element))
                    {
                        throw new Exception();
                    }
                    MIO0Block block       = (MIO0Block)element;
                    byte[]    oldMIO0Data = block.DecodedData;

                    Array.Copy(newPaletteData, 0, oldMIO0Data, Images[0].PaletteBlockOffset[0], newPaletteData.Length);

                    byte[] compressedNewMIO0 = MIO0.Encode(oldMIO0Data);

                    block.RawData = compressedNewMIO0;
                }

                //Now generate the images
                for (int i = 0; i < Images.Count; i++)
                {
                    MK64Image image   = Images[i];
                    Bitmap    bmp     = ((BitmapWrapper)lbAfter.Items[i]).BMP;
                    byte[]    newData = TextureConversion.ImageToBinary(image.Format, image.PixelSize, bmp, ref palette, false);

                    if (newData == null || newData.Length == 0)
                    {
                        MessageBox.Show("Error: Couldn't convert image file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }

                    image.ImageReference.Texture.RawData = newData;
                    image.ImageReference.UpdateImage();

                    if (image.TextureEncoding == MK64Image.MK64ImageEncoding.MIO0)
                    {
                        N64DataElement element;
                        if (!RomProject.Instance.Files[0].HasElementExactlyAt(image.TextureOffset, out element))
                        {
                            throw new Exception();
                        }
                        MIO0Block block = (MIO0Block)element;

                        byte[] MIO0Data = block.DecodedData;

                        Array.Copy(newData, 0, MIO0Data, image.TextureBlockOffset, newData.Length);

                        byte[] compressedNewMIO0 = MIO0.Encode(MIO0Data);

                        block.RawData = compressedNewMIO0;
                    }
                }
            }
        }
        private void ReplaceMIO0()
        {
            //Attempt to load in a new texture and replace. Will not work if the texture size is larger than the one it's replacing
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                Bitmap bmp = (Bitmap)Bitmap.FromFile(openFileDialog.FileName);
                if (bmp == null)
                {
                    MessageBox.Show("Error: Couldn't load image file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                if (bmp.Height != _image.Height ||
                    bmp.Width != _image.Width)
                {
                    MessageBox.Show("Error: New image must be same size!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                //Think hard about this. If you're compressing the image and/or palette into MIO0, you need to test against that.
                // Also a form if there's more than one image being affected by this change? Before/afters?


                //So we need some way to change an F3DEXImage to a new bitmap. but it needs to change texture and palette appropriately,
                // and most importantly it needs to be able to stop halfway to see how it will affect other images. But if we want to change
                // the lakitu images, which will change the palette, you'd have to change all of the images at once, right? So how the hell
                // is this going to work out??

                //Also palette editing

                byte[] newData;
                byte[] newPaletteData = null;
                if (_image.Format == Texture.ImageFormat.CI)
                {
                    Palette palette = new Palette(-1, new byte[(_image.ImageReference.WorkingPalette.Colors.Length * 2) - 200]);
                    newData        = TextureConversion.ImageToBinary(_image.Format, _image.PixelSize, bmp, ref palette);
                    newPaletteData = palette.RawData;
                    if (newPaletteData.Length < (_image.ImageReference.WorkingPalette.Colors.Length * 2))
                    {
                        newPaletteData = Cereal64.Common.Utils.ByteHelper.CombineIntoBytes(newPaletteData, new byte[(_image.ImageReference.WorkingPalette.Colors.Length * 2) - newPaletteData.Length]);
                    }
                }
                else
                {
                    newData = TextureConversion.ImageToBinary(_image.Format, _image.PixelSize, bmp);
                }

                if (newData == null || newData.Length == 0)
                {
                    MessageBox.Show("Error: Couldn't convert image file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                byte[] oldData        = _image.ImageReference.Texture.RawData;
                byte[] oldPaletteData = null;
                if (_image.Format == Texture.ImageFormat.CI)
                {
                    oldPaletteData = _image.ImageReference.BasePalettes[0].RawData;
                }

                _image.ImageReference.Texture.RawData = newData;
                if (_image.Format == Texture.ImageFormat.CI)
                {
                    _image.ImageReference.BasePalettes[0].RawData = newPaletteData;
                }

                _image.ImageReference.UpdateImage();

                if (!_image.IsValidImage)
                {
                    _image.ImageReference.Texture.RawData = oldData;
                    _image.ImageReference.UpdateImage();

                    MessageBox.Show("Error: Couldn't set image file! File might be too large to load in", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                byte[] oldMIO0RefData = null;

                N64DataElement el;

                if (_image.TextureEncoding == MK64Image.MK64ImageEncoding.MIO0)
                {
                    if (!RomProject.Instance.Files[0].HasElementAt(_image.TextureOffset, out el))
                    {
                        MessageBox.Show("Error: Couldn't set image file! Could not find MIO0 block.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                    MIO0Block block = (MIO0Block)el;

                    byte[] oldMIO0Data = block.DecodedData;
                    oldMIO0RefData = oldMIO0Data;

                    if (_specialMIO0Length == -1 && block.FileOffset == 0x132B50)
                    {
                        _specialMIO0Length = block.RawDataSize;
                    }

                    Array.Copy(newData, 0, oldMIO0Data, _image.TextureBlockOffset, newData.Length);

                    byte[] compressedNewMIO0 = MIO0.Encode(oldMIO0Data);

                    int sizeCompare = (_specialMIO0Length != -1 && block.FileOffset == 0x132B50 ? _specialMIO0Length : block.RawDataSize);

                    if (compressedNewMIO0.Length > sizeCompare)
                    {
                        _image.ImageReference.Texture.RawData = oldData;
                        if (_image.Format == Texture.ImageFormat.CI)
                        {
                            _image.ImageReference.BasePalettes[0].RawData = oldPaletteData;
                        }
                        _image.ImageReference.UpdateImage();

                        MessageBox.Show("Error: Couldn't set image file! File might be too large to load in", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }

                    block.RawData = compressedNewMIO0;
                }

                if (_image.Format == Texture.ImageFormat.CI && _image.PaletteEncoding[0] == MK64Image.MK64ImageEncoding.MIO0)
                {
                    if (!RomProject.Instance.Files[0].HasElementAt(_image.TextureOffset, out el))
                    {
                        MessageBox.Show("Error: Couldn't set image file! Could not find MIO0 block.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                    MIO0Block block = (MIO0Block)el;

                    byte[] oldMIO0Data = block.DecodedData;

                    Array.Copy(newPaletteData, 0, oldMIO0Data, _image.PaletteBlockOffset[0], newPaletteData.Length);

                    byte[] compressedNewMIO0 = MIO0.Encode(oldMIO0Data);

                    int sizeCompare = (_specialMIO0Length != -1 && block.FileOffset == 0x132B50 ? _specialMIO0Length : block.RawDataSize);

                    if (compressedNewMIO0.Length > sizeCompare)
                    {
                        _image.ImageReference.Texture.RawData = oldData;
                        if (_image.Format == Texture.ImageFormat.CI)
                        {
                            _image.ImageReference.BasePalettes[0].RawData = oldPaletteData;
                        }
                        _image.ImageReference.UpdateImage();

                        //Revert texture
                        if (_image.TextureEncoding == MK64Image.MK64ImageEncoding.MIO0)
                        {
                            N64DataElement element;
                            if (!RomProject.Instance.Files[0].HasElementExactlyAt(_image.TextureOffset, out element))
                            {
                                throw new Exception();
                            }
                            MIO0Block blockText = (MIO0Block)element;

                            blockText.RawData = oldMIO0RefData;
                        }

                        MessageBox.Show("Error: Couldn't set image file! File might be too large to load in", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }

                    block.RawData = compressedNewMIO0;
                }

                Image = _image; //Reset it
                ImageUpdated();
            }
        }
Beispiel #3
0
        private void btnAddImage_Click(object sender, EventArgs e)
        {
            if (_newImageForm == null)
            {
                _newImageForm = new NewMK64ImageForm();
            }

            if (_newImageForm.ShowDialog() == DialogResult.OK)
            {
                List <MK64Image> newImages = new List <MK64Image>();
                foreach (string FileName in _newImageForm.FileNames)
                {
                    //To do: make it load multiple at a time!
                    Bitmap bmp = (Bitmap)Bitmap.FromFile(FileName);

                    if (bmp == null)
                    {
                        MessageBox.Show("Could not load image:\n" + FileName, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        continue;
                    }

                    byte[] imageData;

                    Texture texture;
                    Palette palette = null;

                    if (_newImageForm.Format == Texture.ImageFormat.CI)
                    {
                        byte[] paletteData = new byte[2 * _newImageForm.PaletteColorCount];
                        palette   = new Palette(-1, paletteData);
                        imageData = TextureConversion.ImageToBinary(_newImageForm.Format, _newImageForm.PixelSize, bmp,
                                                                    ref palette, true);
                    }
                    else
                    {
                        imageData = TextureConversion.ImageToBinary(_newImageForm.Format, _newImageForm.PixelSize, bmp);
                    }

                    texture = new Texture(-1, imageData, _newImageForm.Format, _newImageForm.PixelSize,
                                          bmp.Width, bmp.Height);

                    //Now, if necessary, encode the texture!!
                    MIO0Block textureBlock = null, paletteBlock = null;
                    if (_newImageForm.EncodeTexture)
                    {
                        byte[] encodedData = MIO0.Encode(texture.RawData);
                        textureBlock = new MIO0Block(-1, encodedData);
                        textureBlock.AddElement(texture);
                        texture.FileOffset = 0;
                    }

                    if (palette != null && _newImageForm.EncodePalette)
                    {
                        byte[] encodedData = MIO0.Encode(palette.RawData);
                        paletteBlock = new MIO0Block(-1, encodedData);
                        paletteBlock.AddElement(palette);
                        palette.FileOffset = 0;
                    }

                    //Add in the texture/palette to the new data location
                    if (textureBlock != null)
                    {
                        textureBlock.FileOffset = MarioKart64ElementHub.Instance.NewElementOffset;
                        RomProject.Instance.Files[0].AddElement(textureBlock);
                        MarioKart64ElementHub.Instance.AdvanceNewElementOffset(textureBlock);
                    }
                    else
                    {
                        texture.FileOffset = MarioKart64ElementHub.Instance.NewElementOffset;
                        RomProject.Instance.Files[0].AddElement(texture);
                        MarioKart64ElementHub.Instance.AdvanceNewElementOffset(texture);
                    }

                    if (palette != null)
                    {
                        if (paletteBlock != null)
                        {
                            paletteBlock.FileOffset = MarioKart64ElementHub.Instance.NewElementOffset;
                            RomProject.Instance.Files[0].AddElement(paletteBlock);
                            MarioKart64ElementHub.Instance.AdvanceNewElementOffset(paletteBlock);
                        }
                        else
                        {
                            palette.FileOffset = MarioKart64ElementHub.Instance.NewElementOffset;
                            RomProject.Instance.Files[0].AddElement(palette);
                            MarioKart64ElementHub.Instance.AdvanceNewElementOffset(palette);
                        }
                    }

                    //Add in the new MK64Image
                    int tFileOffset = (textureBlock == null ? texture.FileOffset : textureBlock.FileOffset);
                    MK64Image.MK64ImageEncoding tEncoding = (textureBlock == null ? MK64Image.MK64ImageEncoding.Raw : MK64Image.MK64ImageEncoding.MIO0);
                    int        tBlockOffset  = (textureBlock == null ? -1 : texture.FileOffset);
                    List <int> PaletteOffset = new List <int>();
                    List <MK64Image.MK64ImageEncoding> PaletteEncodings = new List <MK64Image.MK64ImageEncoding>();
                    List <int> PaletteBlockOffset = new List <int>();
                    List <int> PaletteColorCount  = new List <int>();
                    List <int> PaletteColorOffset = new List <int>();
                    if (palette != null)
                    {
                        PaletteOffset.Add(paletteBlock == null ? palette.FileOffset : paletteBlock.FileOffset);
                        PaletteEncodings.Add(paletteBlock == null ? MK64Image.MK64ImageEncoding.Raw : MK64Image.MK64ImageEncoding.MIO0);
                        PaletteBlockOffset.Add(paletteBlock == null ? -1 : palette.FileOffset);
                        PaletteColorCount.Add(palette.Colors.Length);
                        PaletteColorOffset.Add(0);
                    }

                    MK64Image newImage = new MK64Image(tFileOffset,
                                                       tEncoding,
                                                       tBlockOffset,
                                                       _newImageForm.Format,
                                                       _newImageForm.PixelSize,
                                                       bmp.Width,
                                                       bmp.Height,
                                                       false,
                                                       PaletteOffset,
                                                       PaletteEncodings,
                                                       PaletteBlockOffset,
                                                       PaletteColorCount,
                                                       PaletteColorOffset,
                                                       0, 0, Path.GetFileNameWithoutExtension(FileName));

                    MarioKart64ElementHub.Instance.TextureHub.AddImage(newImage);
                    newImages.Add(newImage);
                }

                if (newImages.Count > 1)
                {
                    MessageBox.Show(string.Format("{0} images loaded!", newImages.Count), "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }

                if (newImages.Count > 0)
                {
                    int newSelectedIndex = lbImages.Items.Count;
                    lbImages.Items.AddRange(newImages.ToArray());

                    //Update the image count & selected
                    lbImages.SelectedIndex = newSelectedIndex;
                    UpdateImageCount();
                }
            }
        }