Пример #1
0
        private static byte[] PixelBytesFromImage(Bitmap bmp, PsbPixelFormat pixelFormat = PsbPixelFormat.None)
        {
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                                              ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            int    stride    = bmpData.Stride;      // 扫描线的宽度
            int    offset    = stride - bmp.Width;  // 显示宽度与扫描线宽度的间隙
            IntPtr iptr      = bmpData.Scan0;       // 获取bmpData的内存起始位置
            int    scanBytes = stride * bmp.Height; // 用stride宽度,表示这是内存区域的大小

            var result = new byte[scanBytes];

            System.Runtime.InteropServices.Marshal.Copy(iptr, result, 0, scanBytes);
            bmp.UnlockBits(bmpData); // 解锁内存区域

            switch (pixelFormat)
            {
            case PsbPixelFormat.WinRGBA4444:
                result = Rgba428(result, false);
                break;

            case PsbPixelFormat.CommonRGBA8:
                Rgba2Argb(ref result);
                break;

            case PsbPixelFormat.DXT5:
                //Rgba2Argb(ref result);
                result = DxtUtil.Dxt5Encode(result, bmp.Width, bmp.Height);
                break;
            }
            return(result);
        }
Пример #2
0
 public static byte[] GetPixelBytesFromImage(Image image, PsbPixelFormat pixelFormat = PsbPixelFormat.None)
 {
     if (!(image is Bitmap bmp))
     {
         bmp = new Bitmap(image);
     }
     return(PixelBytesFromImage(bmp, pixelFormat));
 }
Пример #3
0
        /// <summary>
        /// Whether the <see cref="PsbPixelFormat"/> use palette
        /// </summary>
        /// <param name="format"></param>
        /// <returns></returns>
        public static bool UsePalette(this PsbPixelFormat format)
        {
            switch (format)
            {
            case PsbPixelFormat.CI8_SW:
                return(true);

            default:
                return(false);
            }
        }
Пример #4
0
        public static Bitmap ConvertToImage(byte[] data, byte[] palette, int height, int width,
                                            PsbPixelFormat colorFormat, PsbPixelFormat paletteColorFormat)
        {
            //Copy data & palette to avoid changing original Data (might be reused)
            if (palette != null && palette.Length > 0)
            {
                return(ConvertToImageWithPalette(data.ToArray(), palette.ToArray(), height, width, colorFormat, paletteColorFormat));
            }

            return(ConvertToImage(data.ToArray(), height, width, colorFormat));
        }
Пример #5
0
 public static Bitmap UncompressToImage(byte[] data, int height, int width, PsbPixelFormat colorFormat = PsbPixelFormat.None, int align = 4)
 {
     byte[] bytes;
     try
     {
         bytes = Uncompress(data, height, width, align);
     }
     catch (Exception e)
     {
         throw new BadImageFormatException("data incorrect", e);
     }
     return(ConvertToImage(bytes, height, width, colorFormat));
 }
Пример #6
0
        public static Bitmap ConvertToImageWithPalette(byte[] data, byte[] palette, int height, int width,
                                                       PsbPixelFormat colorFormat = PsbPixelFormat.None, PsbPixelFormat paletteColorFormat = PsbPixelFormat.None)
        {
            Bitmap     bmp;
            BitmapData bmpData;

            switch (paletteColorFormat)
            {
            case PsbPixelFormat.CommonRGBA8:
                Switch_0_2(ref palette);
                break;
            }

            switch (colorFormat)
            {
            case PsbPixelFormat.CI8_SW:
                bmp     = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
                bmpData = bmp.LockBits(new Rectangle(0, 0, width, height),
                                       ImageLockMode.WriteOnly, bmp.PixelFormat);
                ColorPalette pal = bmp.Palette;
                for (int i = 0; i < 256; i++)
                {
                    pal.Entries[i] = Color.FromArgb(BitConverter.ToInt32(palette, i * 4));
                }
                // Assign the edited palette to the bitmap.
                bmp.Palette = pal;

                data = PostProcessing.UnswizzleTexture(data, bmp.Width, bmp.Height, bmp.PixelFormat);
                //Switch_0_2(ref data);
                break;

            default:
                return(ConvertToImage(data, height, width, colorFormat));
            }

            int    stride    = bmpData.Stride;  // 扫描线的宽度
            int    offset    = stride - width;  // 显示宽度与扫描线宽度的间隙
            IntPtr iptr      = bmpData.Scan0;   // 获取bmpData的内存起始位置
            int    scanBytes = stride * height; // 用stride宽度,表示这是内存区域的大小

            if (scanBytes >= data.Length)
            {
                System.Runtime.InteropServices.Marshal.Copy(data, 0, iptr, data.Length);
                bmp.UnlockBits(bmpData); // 解锁内存区域
                return(bmp);
            }

            throw new BadImageFormatException("data may not corresponding");
        }
Пример #7
0
        public static void ConvertToImageFile(byte[] data, string path, int height, int width, PsbImageFormat format,
                                              PsbPixelFormat colorFormat = PsbPixelFormat.None, byte[] palette = null, PsbPixelFormat paletteColorFormat = PsbPixelFormat.None)
        {
            Bitmap bmp = ConvertToImage(data, palette, height, width, colorFormat, paletteColorFormat);

            switch (format)
            {
            case PsbImageFormat.bmp:
                bmp.Save(path, ImageFormat.Bmp);
                break;

            case PsbImageFormat.png:
                bmp.Save(path, ImageFormat.Png);
                break;
            }
        }
Пример #8
0
        public static void ConvertToImageFile(byte[] data, string path, int height, int width, PsbImageFormat format,
                                              PsbPixelFormat colorFormat = PsbPixelFormat.None)
        {
            var bmp = ConvertToImage(data, height, width, colorFormat);

            switch (format)
            {
            case PsbImageFormat.Bmp:
                bmp.Save(path, ImageFormat.Bmp);
                break;

            case PsbImageFormat.Png:
                bmp.Save(path, ImageFormat.Png);
                break;
            }
        }
Пример #9
0
        public static string ToStringForPsb(this PsbPixelFormat pixelFormat)
        {
            switch (pixelFormat)
            {
            case PsbPixelFormat.None:
            case PsbPixelFormat.WinRGBA8:
            case PsbPixelFormat.CommonRGBA8:
                return("RGBA8");

            case PsbPixelFormat.DXT5:
                return("DXT5");

            case PsbPixelFormat.WinRGBA4444:
                return("RGBA4444");

            default:
                throw new ArgumentOutOfRangeException(nameof(pixelFormat), pixelFormat, null);
            }
        }
Пример #10
0
        public static Bitmap ConvertToImage(byte[] data, int height, int width, PsbPixelFormat colorFormat = PsbPixelFormat.None)
        {
            Bitmap     bmp;
            BitmapData bmpData;

            {
                bmp     = new Bitmap(width, height, PixelFormat.Format32bppArgb);
                bmpData = bmp.LockBits(new Rectangle(0, 0, width, height),
                                       ImageLockMode.WriteOnly, bmp.PixelFormat);
            }
            switch (colorFormat)
            {
            case PsbPixelFormat.WinRGBA4444:
                data = Rgba428(data);
                break;

            case PsbPixelFormat.CommonRGBA8:
                Rgba2Argb(ref data);
                break;

            case PsbPixelFormat.DXT5:    //MARK: RL seems compatible to DXT5 compress?
                data = DxtUtil.DecompressDxt5(data, width, height);
                Rgba2Argb(ref data);     //DXT5(for win) need conversion
                break;
            }

            int    stride    = bmpData.Stride;  // 扫描线的宽度
            int    offset    = stride - width;  // 显示宽度与扫描线宽度的间隙
            IntPtr iptr      = bmpData.Scan0;   // 获取bmpData的内存起始位置
            int    scanBytes = stride * height; // 用stride宽度,表示这是内存区域的大小

            if (scanBytes >= data.Length)
            {
                System.Runtime.InteropServices.Marshal.Copy(data, 0, iptr, data.Length);
                bmp.UnlockBits(bmpData); // 解锁内存区域
                return(bmp);
            }
            throw new BadImageFormatException("data may not corresponding");
        }
Пример #11
0
        /// <summary>
        /// Get RGBA bytes from palette
        /// </summary>
        /// <param name="palette"></param>
        /// <param name="palettePixelFormat"></param>
        /// <returns></returns>
        public static byte[] GetPaletteBytes(this ColorPalette palette, PsbPixelFormat palettePixelFormat)
        {
            byte[] bytes = new byte[palette.Entries.Length * 4];
            for (var i = 0; i < palette.Entries.Length; i++)
            {
                //LE ARGB
                var color = palette.Entries[i];
                bytes[i * 4]     = color.B;
                bytes[i * 4 + 1] = color.G;
                bytes[i * 4 + 2] = color.R;
                bytes[i * 4 + 3] = color.A;
                var bt = BitConverter.GetBytes(color.ToArgb());
            }

            switch (palettePixelFormat)
            {
            case PsbPixelFormat.CommonRGBA8:
                RL.Switch_0_2(ref bytes);
                break;
            }

            return(bytes);
        }
Пример #12
0
        /// <summary>
        /// Split textures into parts and save to files
        /// </summary>
        /// <param name="psb">PSB</param>
        /// <param name="path">Save directory</param>
        /// <param name="option">Save option</param>
        /// <param name="imageFormat">Save format</param>
        /// <param name="pixelFormat">When save to PSB special formats, specific pixel format to use</param>
        public static void SplitTextureToFiles(this PSB psb, string path, PsbImageOption option = PsbImageOption.Extract, PsbImageFormat imageFormat = PsbImageFormat.Png, PsbPixelFormat pixelFormat = PsbPixelFormat.None)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            var source = (PsbDictionary)psb.Objects["source"];

            foreach (var texPair in source)
            {
                if (!(texPair.Value is PsbDictionary tex))
                {
                    continue;
                }
                var name = texPair.Key;
                if (!Directory.Exists(Path.Combine(path, name)))
                {
                    Directory.CreateDirectory(Path.Combine(path, name));
                }
                var icon    = (PsbDictionary)tex["icon"];
                var texture = (PsbDictionary)tex["texture"];

                //var mipmap = (PsbDictionary)texture["mipMap"]; //TODO: Mipmap?

                var md = PsbResCollector.GenerateMotionResMetadata(texture, (PsbResource)texture["pixel"]);
                md.Spec = psb.Platform; //Important
                Bitmap bmp = md.ToImage();

                foreach (var iconPair in icon)
                {
                    var    savePath = Path.Combine(path, name, iconPair.Key);
                    var    info     = (PsbDictionary)iconPair.Value;
                    var    width    = (int)(PsbNumber)info["width"];
                    var    height   = (int)(PsbNumber)info["height"];
                    var    top      = (int)(PsbNumber)info["top"];
                    var    left     = (int)(PsbNumber)info["left"];
                    var    attr     = (int)(PsbNumber)info["attr"];
                    Bitmap b        = new Bitmap(width, height, PixelFormat.Format32bppArgb);
#if USE_FASTBITMAP
                    using (FastBitmap f = b.FastLock())
                    {
                        f.CopyRegion(bmp, new Rectangle(left, top, width, height), new Rectangle(0, 0, b.Width, b.Height));
                    }
#else
                    Graphics g = Graphics.FromImage(b);
                    //g.InterpolationMode = InterpolationMode.NearestNeighbor;
                    //g.PixelOffsetMode = PixelOffsetMode.Half;
                    g.DrawImage(bmp, new Rectangle(0, 0, b.Width, b.Height), new Rectangle(left, top, width, height),
                                GraphicsUnit.Pixel);
                    g.Dispose();
#endif

                    switch (option)
                    {
                    case PsbImageOption.Decompress:
                        File.WriteAllBytes(savePath + ".raw", RL.GetPixelBytesFromImage(b, pixelFormat));
                        break;

                    case PsbImageOption.Compress:
                        File.WriteAllBytes(savePath + ".rl", RL.CompressImage(b, pixelFormat));
                        break;

                    case PsbImageOption.Original:
                    case PsbImageOption.Extract:
                    default:
                        switch (imageFormat)
                        {
                        case PsbImageFormat.Bmp:
                            b.Save(savePath + ".bmp", ImageFormat.Bmp);
                            break;

                        case PsbImageFormat.Png:
                        default:
                            b.Save(savePath + ".png", ImageFormat.Png);
                            //b.Save(savePath + $"_{attr}.png", ImageFormat.Png);
                            break;
                        }
                        break;
                    }
                }
                bmp.Dispose();
            }
        }
Пример #13
0
        public static void DecompressToImageFile(byte[] data, string path, int height, int width,
                                                 PsbImageFormat format = PsbImageFormat.png, PsbPixelFormat colorFormat = PsbPixelFormat.None, int align = 4)
        {
            byte[] bytes;
            try
            {
                bytes = Decompress(data, height, width, align);
            }
            catch (Exception e)
            {
                throw new PsbBadFormatException(PsbBadFormatReason.Resources, "data incorrect", e);
            }

            ConvertToImageFile(bytes, path, height, width, format, colorFormat);
        }
Пример #14
0
        public static byte[] GetPixelBytesFromImageFile(string path, PsbPixelFormat pixelFormat = PsbPixelFormat.None)
        {
            Bitmap bmp = new Bitmap(path, false);

            return(PixelBytesFromImage(bmp, pixelFormat));
        }
Пример #15
0
 public static byte[] CompressImageFile(string path, PsbPixelFormat pixelFormat = PsbPixelFormat.None)
 {
     return(CompressImage(new Bitmap(path, false), pixelFormat));
 }
Пример #16
0
 public static byte[] CompressImage(Bitmap image, PsbPixelFormat pixelFormat = PsbPixelFormat.None)
 {
     return(Compress(PixelBytesFromImage(image, pixelFormat)));
 }
Пример #17
0
        public static Bitmap ConvertToImage(byte[] data, int height, int width,
                                            PsbPixelFormat colorFormat = PsbPixelFormat.None)
        {
            var bmp     = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height),
                                       ImageLockMode.WriteOnly, bmp.PixelFormat);

            switch (colorFormat)
            {
            case PsbPixelFormat.BeRGBA4444:
                data = Argb428(data);
                Argb2Rgba(ref data);
                break;

            case PsbPixelFormat.LeRGBA4444:
                data = Argb428(data);
                break;

            case PsbPixelFormat.BeRGBA8:
                Switch_0_2(ref data);
                break;

            case PsbPixelFormat.A8L8:
                data = ReadA8L8(data, width, height);
                break;

            case PsbPixelFormat.A8L8_SW:
                data = ReadA8L8(data, width, height);
                data = PostProcessing.UnswizzleTexture(data, width, height, PixelFormat.Format32bppArgb);
                break;

            case PsbPixelFormat.DXT5:
                data = DxtUtil.DecompressDxt5(data, width, height);
                Switch_0_2(ref data);     //DXT5(for win) need conversion
                break;

            case PsbPixelFormat.RGBA8_SW:
                data = PostProcessing.UnswizzleTexture(data, bmp.Width, bmp.Height, bmp.PixelFormat);
                Switch_0_2(ref data);
                break;

            case PsbPixelFormat.LeRGBA4444_SW:
                data = Argb428(data);
                //Rgba2Argb(ref data);
                data = PostProcessing.UnswizzleTexture(data, bmp.Width, bmp.Height, bmp.PixelFormat);
                break;

            case PsbPixelFormat.TileRGBA8_SW:
                data = PostProcessing.UntileTexture(data, bmp.Width, bmp.Height, bmp.PixelFormat);
                break;

            case PsbPixelFormat.A8:
                data = ReadA8(data, height, width);
                break;

            case PsbPixelFormat.A8_SW:
                data = ReadA8(data, height, width);
                data = PostProcessing.UnswizzleTexture(data, width, height, PixelFormat.Format32bppArgb);
                break;

            case PsbPixelFormat.TileA8_SW:
                data = ReadA8(data, height, width);
                data = PostProcessing.UntileTexture(data, width, height, PixelFormat.Format32bppArgb);
                break;

            case PsbPixelFormat.L8:
                data = ReadL8(data, height, width);
                break;

            case PsbPixelFormat.L8_SW:
                data = ReadL8(data, height, width);
                data = PostProcessing.UnswizzleTexture(data, width, height, PixelFormat.Format32bppArgb);
                break;

            case PsbPixelFormat.RGBA5650:
                data = ReadRgba5650(data);
                break;

            case PsbPixelFormat.RGBA5650_SW:
                data = ReadRgba5650(data);
                data = PostProcessing.UnswizzleTexture(data, width, height, PixelFormat.Format32bppArgb);
                break;
            }

            int    stride    = bmpData.Stride;  // 扫描线的宽度
            int    offset    = stride - width;  // 显示宽度与扫描线宽度的间隙
            IntPtr iptr      = bmpData.Scan0;   // 获取bmpData的内存起始位置
            int    scanBytes = stride * height; // 用stride宽度,表示这是内存区域的大小

            if (scanBytes >= data.Length)
            {
                Marshal.Copy(data, 0, iptr, data.Length);
                bmp.UnlockBits(bmpData); // 解锁内存区域
                return(bmp);
            }

            throw new BadImageFormatException("data may not corresponding");
        }
Пример #18
0
        /// <summary>
        /// Try to switch Spec
        /// </summary>
        /// <param name="psb"></param>
        /// <param name="targetSpec"></param>
        /// <param name="pixelFormat"></param>
        public static void SwitchSpec(this PSB psb, PsbSpec targetSpec, PsbPixelFormat pixelFormat = PsbPixelFormat.None)
        {
            if (targetSpec == PsbSpec.other)
            {
                return;
            }

            //Alternative //TODO: Alternative table?
            bool isAlternative  = false;
            var  realTargetSpec = PsbSpec.common;

            var original = psb.Platform;

            if (original == PsbSpec.ems)
            {
                original = PsbSpec.common;
            }

            if (targetSpec == PsbSpec.ems)
            {
                isAlternative  = true;
                realTargetSpec = targetSpec;
                targetSpec     = PsbSpec.common;
            }

            if (targetSpec == PsbSpec.krkr) //krkr can not select pixel format
            {
                switch (original)
                {
                case PsbSpec.win:
                {
                    Common2KrkrConverter winKrkr = new Common2KrkrConverter();
                    winKrkr.Convert(psb);
                    break;
                }

                case PsbSpec.common:
                {
                    Common2KrkrConverter commonKrkr = new Common2KrkrConverter();
                    commonKrkr.Convert(psb);
                    break;
                }

                default:
                    psb.Platform = targetSpec;
                    break;
                }
            }

            else if (targetSpec == PsbSpec.win)
            {
                switch (original)
                {
                case PsbSpec.krkr:
                    Krkr2CommonConverter krkr2Win = new Krkr2CommonConverter(true);
                    krkr2Win.Convert(psb);
                    break;

                case PsbSpec.common:
                    CommonWinConverter winCommon = new CommonWinConverter();
                    winCommon.Convert(psb);
                    break;

                default:
                    psb.Platform = targetSpec;
                    break;
                }
            }

            else if (targetSpec == PsbSpec.common || targetSpec == PsbSpec.ems)
            {
                switch (original)
                {
                case PsbSpec.krkr:
                    Krkr2CommonConverter krkr2Common = new Krkr2CommonConverter();
                    krkr2Common.Convert(psb);
                    break;

                case PsbSpec.win:
                    CommonWinConverter commonWin = new CommonWinConverter();
                    commonWin.Convert(psb);
                    break;

                case PsbSpec.common:
                case PsbSpec.ems:
                    psb.Platform = targetSpec;
                    break;

                default:
                    psb.Platform = targetSpec;
                    break;
                }
            }

            else
            {
                psb.Platform = targetSpec;
            }

            if (isAlternative)
            {
                psb.Platform = realTargetSpec;
            }
        }
Пример #19
0
        private static byte[] PixelBytesFromImage(Bitmap bmp, PsbPixelFormat pixelFormat = PsbPixelFormat.None)
        {
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                                              ImageLockMode.ReadOnly, bmp.PixelFormat);

            int    stride    = bmpData.Stride;      // 扫描线的宽度
            int    offset    = stride - bmp.Width;  // 显示宽度与扫描线宽度的间隙
            IntPtr iPtr      = bmpData.Scan0;       // 获取bmpData的内存起始位置
            int    scanBytes = stride * bmp.Height; // 用stride宽度,表示这是内存区域的大小

            var result = new byte[scanBytes];

            Marshal.Copy(iPtr, result, 0, scanBytes);
            bmp.UnlockBits(bmpData); // 解锁内存区域

            switch (pixelFormat)
            {
            case PsbPixelFormat.LeRGBA4444:
                result = Argb428(result, false);
                break;

            case PsbPixelFormat.BeRGBA4444:
                Argb2Rgba(ref result, true);
                result = Argb428(result, false);
                break;

            case PsbPixelFormat.BeRGBA8:
                Switch_0_2(ref result);
                break;

            case PsbPixelFormat.A8L8:
                result = Argb2A8L8(result);
                break;

            case PsbPixelFormat.A8L8_SW:
                result = PostProcessing.SwizzleTexture(result, bmp.Width, bmp.Height, bmp.PixelFormat);
                result = Argb2A8L8(result);
                break;

            case PsbPixelFormat.DXT5:
                //Switch_0_2(ref result);
                result = DxtUtil.Dxt5Encode(result, bmp.Width, bmp.Height);
                break;

            case PsbPixelFormat.RGBA8_SW:
                result = PostProcessing.SwizzleTexture(result, bmp.Width, bmp.Height, bmp.PixelFormat);
                Switch_0_2(ref result);
                break;

            case PsbPixelFormat.TileRGBA8_SW:
                result = PostProcessing.TileTexture(result, bmp.Width, bmp.Height, bmp.PixelFormat);
                break;

            case PsbPixelFormat.L8:
                result = Argb2L8(result);
                break;

            case PsbPixelFormat.A8_SW:
                result = PostProcessing.SwizzleTexture(result, bmp.Width, bmp.Height, bmp.PixelFormat);
                result = Argb2A8(result);
                break;

            case PsbPixelFormat.TileA8_SW:
                result = PostProcessing.TileTexture(result, bmp.Width, bmp.Height, bmp.PixelFormat);
                result = Argb2A8(result);
                break;

            case PsbPixelFormat.A8:
                result = Argb2A8(result);
                break;

            case PsbPixelFormat.CI8_SW:
                result = PostProcessing.SwizzleTexture(result, bmp.Width, bmp.Height, bmp.PixelFormat);
                break;

            case PsbPixelFormat.CI4_SW:
                result = PostProcessing.SwizzleTexture(result, bmp.Width, bmp.Height, bmp.PixelFormat);
                break;

            case PsbPixelFormat.L8_SW:
                result = PostProcessing.SwizzleTexture(result, bmp.Width, bmp.Height, bmp.PixelFormat);
                result = Argb2L8(result);
                break;

            case PsbPixelFormat.LeRGBA4444_SW:
                result = PostProcessing.SwizzleTexture(result, bmp.Width, bmp.Height, bmp.PixelFormat);
                result = Argb428(result, false);
                break;

            case PsbPixelFormat.RGBA5650:
                result = Argb2Rgba5650(result);
                break;

            case PsbPixelFormat.RGBA5650_SW:
                result = PostProcessing.SwizzleTexture(result, bmp.Width, bmp.Height, bmp.PixelFormat);
                result = Argb2Rgba5650(result);
                break;
            }

            return(result);
        }