/* * Copyright (C) 2011 pleoNeX * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Programador: pleoNeX * Programa utilizado: Microsoft Visual C# 2010 Express * Fecha: 18/02/2011 * */ using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Windows.Media.Imaging; namespace Tinke { public static class Convertir { #region Paleta /// /// A partir de un array de bytes devuelve un array de colores. /// /// Bytes para convertir /// Colores de la paleta. public static Color[] BGR555(byte[] bytes) { Color[] paleta = new Color[bytes.Length / 2]; for (int i = 0; i < bytes.Length / 2; i++) { paleta[i] = BGR555(bytes[i * 2], bytes[i * 2 + 1]); } return paleta; } /// /// Convierte dos bytes en un color. /// /// Primer byte /// Segundo byte /// Color convertido public static Color BGR555(byte byte1, byte byte2) { /*int r, b; double g; r = (byte1 % 0x20) * 0x8; g = (byte1 / 0x20 + ((byte2 % 0x4) * 7.96875)) * 0x8; b = byte2 / 0x4 * 0x8; try { return System.Drawing.Color.FromArgb(r, (int)g, b); } catch (Exception) { return Color.Black; }*/ return Color.FromArgb(decodeColor(BitConverter.ToInt16(new byte[] { byte1, byte2 }, 0), BGR555_)); } public static byte[][] BytesToTiles_NoChanged(byte[] bytes, int tilesX, int tilesY) { List tiles = new List(); List temp = new List(); for (int ht = 0; ht < tilesY; ht++) { for (int wt = 0; wt < tilesX; wt++) { // Get the tile data for (int h = 0; h < 8; h++) { for (int w = 0; w < 8; w++) { temp.Add(bytes[wt * 8 + ht * tilesX * 64 + (w + h * 8 * tilesX)]); } } // Set the tile data tiles.Add(temp.ToArray()); temp.Clear(); } } return tiles.ToArray(); } public static MKDS_Course_Editor.nclr_e.CColorFormat BGR555_ = new MKDS_Course_Editor.nclr_e.CColorFormat("BGR555", 10, 16, new int[] { 3, 2, 1, 5, 5, 5 }); public static int[][] shiftList = new int[][] { new int[] { 0, 0 }, new int[] { 1, 255 }, new int[] { 3, 85 }, new int[] { 7, 36 }, new int[] { 15, 17 }, new int[] { 31, 8 }, new int[] { 63, 4 }, new int[] { 127, 2 }, new int[] { 255, 1 } }; public static int decodeColor(int value, MKDS_Course_Editor.nclr_e.CColorFormat format) { int[] res = format.getResolution(); int rgb = Color.FromArgb(255, 0, 0, 0).ToArgb(); int shift = 0; int length = res.Length / 2; for (int i = 0; i < length; i++) { int mode = res[length - i - 1]; int nshift = res[length * 2 - i - 1]; int mult = shiftList[nshift][1]; int and = shiftList[nshift][0]; int n = (value >> shift & and) * mult; switch (mode) { case 0: // '\0' rgb |= n << 24; break; case 1: // '\001' rgb |= n << 16; break; case 2: // '\002' rgb |= n << 8; break; case 3: // '\003' rgb |= n; break; case 4: // '\004' rgb = n << 16 | n << 8 | n; break; } shift += nshift; } return rgb; } #endregion #region Tiles /// /// Convierte una array de Tiles en bytes /// /// Tiles para convertir /// Array de bytes public static byte[] TilesToBytes(byte[][] tiles) { List resul = new List(); for (int i = 0; i < tiles.Length; i++) for (int j = 0; j < 64; j++) resul.Add(tiles[i][j]); return resul.ToArray(); } /// /// Convierte una array de bytes en otra de tiles /// /// Bytes para convertir /// Array de tiles public static byte[][] BytesToTiles(byte[] bytes) { List resul = new List(); List temp = new List(); for (int i = 0; i < bytes.Length / 64; i++) { for (int j = 0; j < 64; j++) temp.Add(bytes[j + i * 64]); resul.Add(temp.ToArray()); temp.Clear(); } return resul.ToArray(); } #endregion /// /// Convierte una array de bytes en formato 4-bit a otro en formato 8-bit /// /// Datos de entrada en formato 4-bit (valor máximo 15 (0xF)) /// Devuelve una array de bytes en 8-bit public static Byte[] Bit4ToBit8(byte[] bits4) { List bits8 = new List(); for (int i = 0; i < bits4.Length; i += 2) { string nByte = String.Format("{0:X}", bits4[i]); nByte += String.Format("{0:X}", bits4[i + 1]); bits8.Add((byte)Convert.ToInt32(nByte, 16)); } return bits8.ToArray(); } /// /// Convierte una array de bytes en formato 8-bit a otro en formato 4-bit /// /// Datos de entrada en formato 8-bit /// Devuelve una array de bytes en 4-bit public static Byte[] Bit8ToBit4(byte[] bits8) { List bits4 = new List(); for (int i = 0; i < bits8.Length; i++) { string nByte = String.Format("{0:X}", bits8[i]); if (nByte.Length == 1) nByte = '0' + nByte; bits4.Add((byte)Convert.ToInt32(nByte[0].ToString(), 16)); bits4.Add((byte)Convert.ToInt32(nByte[1].ToString(), 16)); } return bits4.ToArray(); } /// /// Modifica algunas propiedades de un archivo gif /// /// Ruta donde se encuentra el archivo a modificar /// 1/100 segundos entre frames /// Número de repeticiones. 0 para infinito, -1 para ninguna public static void ModificarGif(string gif, int delay, int loops) { BinaryReader br = new BinaryReader(File.OpenRead(gif)); MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); // Cabecera por defecto bw.Write(br.ReadBytes(0xD)); // Añadimos campo de animación if (loops >= 0) { List bAni = new List(); byte[] rawData = new Byte[] { 0x21, 0xFF, 0x0B, 0x4E, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2E, 0x30, 0x03, 0x01 }; bAni.AddRange(rawData); bAni.Add(Convert.ToByte(loops & 0xff)); bAni.Add(Convert.ToByte((loops >> 8) & 0xff)); bAni.Add(0x00); // Terminator bw.Write(bAni.ToArray()); } // Buscamos cada campo de cada frame y le cambiamos el delay byte first, second; first = br.ReadByte(); bw.Write(first); while (br.BaseStream.Position + 1 != br.BaseStream.Length) { if (first == 0x21) { second = br.ReadByte(); bw.Write(second); if (second == 0xF9) { bw.Write(br.ReadBytes(2)); bw.Write(Convert.ToByte(delay & 0xff)); bw.Write(Convert.ToByte((delay >> 8) & 0xff)); br.ReadBytes(2); // Cambiamos esos dos bytes que son el valor del delay } else { first = second; continue; } } first = br.ReadByte(); bw.Write(first); } br.Close(); br.Dispose(); File.Delete(gif); FileStream fs = new FileStream(gif, FileMode.Create); fs.Write(ms.ToArray(), 0, (int)ms.Length); fs.Flush(); fs.Close(); fs.Dispose(); ms.Close(); ms.Dispose(); bw.Close(); bw.Dispose(); } /// /// Crea un archivos animado gif apartir de varios archivos bitmap /// /// Ruta de salida del archivo /// Cada uno de los frames /// 1/100 seg entre frame /// Número de repeticiones. 0 para infinito, -1 para ninguna public static void CrearGif(string fout, Image[] frames, int delay, int loops) { // ¡¡No funciona con mono!! GifBitmapEncoder encoder = new GifBitmapEncoder(); for (int i = 0; i < frames.Length; i++) { MemoryStream ms = new MemoryStream(); frames[i].Save(ms, System.Drawing.Imaging.ImageFormat.Png); BitmapFrame bf = BitmapFrame.Create(ms); encoder.Frames.Add(bf); } FileStream fs = new FileStream(fout, FileMode.Create); encoder.Save(fs); fs.Close(); fs.Dispose(); ModificarGif(fout, delay, loops); } } }