diff --git a/ArcFormats/NekoSDK/ImageALP.cs b/ArcFormats/NekoSDK/ImageALP.cs index 4c698b48..0516c883 100644 --- a/ArcFormats/NekoSDK/ImageALP.cs +++ b/ArcFormats/NekoSDK/ImageALP.cs @@ -27,6 +27,7 @@ using System; using System.ComponentModel.Composition; using System.IO; using System.Windows.Media; +using System.Windows.Media.Imaging; namespace GameRes.Formats.NekoSDK { @@ -35,19 +36,32 @@ namespace GameRes.Formats.NekoSDK { public ImageData Read (IBinaryStream file, BmpMetaData info) { - if (info.BPP != 24 && info.BPP != 32 || !file.CanSeek) + if (!file.CanSeek) return null; var alp_name = Path.ChangeExtension (info.FileName, "alp"); if (alp_name.Equals (info.FileName, StringComparison.InvariantCultureIgnoreCase) || !VFS.FileExists (alp_name)) return null; - var alpha_size = info.Width * info.Height; + int alp_stride = ((int)info.Width + 3) & -4; + int alpha_size = alp_stride * (int)info.Height; var alpha = new byte[alpha_size]; using (var alp = VFS.OpenStream (alp_name)) { - if (alpha.Length != alp.Read (alpha, 0, alpha.Length) || alp.ReadByte() != -1) + alpha_size = alp.Read (alpha, 0, alpha.Length); + if (alp.ReadByte() != -1) return null; + if (alpha_size != alpha.Length) + { + if (alp_stride == (int)info.Width) + return null; + alp_stride = (int)info.Width; + if (alpha_size != alp_stride * (int)info.Height) + return null; + } } + if (info.BPP != 24 && info.BPP != 32) + return ReadBmp (file, info, alpha, alp_stride); + file.Position = info.ImageOffset; int dst_stride = (int)info.Width * 4; int gap = -((int)info.Width * info.BPP / 8) & 3; @@ -56,7 +70,7 @@ namespace GameRes.Formats.NekoSDK int dst = (int)(info.Height-1) * dst_stride; for (int y = (int)info.Height-1; y >= 0; --y) { - int a_src = (int)info.Width * y; + int a_src = alp_stride * y; for (int x = 0; x < dst_stride; x += 4) { file.Read (pixels, dst+x, src_pixel_size); @@ -68,5 +82,29 @@ namespace GameRes.Formats.NekoSDK } return ImageData.Create (info, PixelFormats.Bgra32, null, pixels, dst_stride); } + + public ImageData ReadBmp (IBinaryStream file, BmpMetaData info, byte[] alpha, int alp_stride) + { + var decoder = new BmpBitmapDecoder (file.AsStream, + BitmapCreateOptions.None, BitmapCacheOption.OnLoad); + BitmapSource bitmap = decoder.Frames[0]; + bitmap = new FormatConvertedBitmap (bitmap, PixelFormats.Bgr32, null, 0); + int dst_stride = (int)info.Width * 4; + var pixels = new byte[(int)info.Height * dst_stride]; + bitmap.CopyPixels (pixels, dst_stride, 0); + int dst = 0; + int src = 0; + for (int y = (int)info.Height; y > 0; --y) + { + int a_src = src; + for (int x = 3; x < dst_stride; x += 4) + { + pixels[dst+x] = alpha[a_src++]; + } + dst += dst_stride; + src += alp_stride; + } + return ImageData.Create (info, PixelFormats.Bgra32, null, pixels, dst_stride); + } } }