private static List<ConstAnimationFrame> GetFrameInfo(CommandLineArgs cmdLine, NpkReader npk, NpkPath imgPath) { List<ConstAnimationFrame> frameInfo = new List<ConstAnimationFrame>(); List<FrameInfo> frames = npk.Frames[imgPath].ToList(); if (cmdLine.UseAllFrames) { for (int frameIndex = 0; frameIndex < frames.Count; frameIndex++) { frameInfo.Add(new AnimationFrame() { DelayInMs = cmdLine.FrameDelayInMs, Image = new ImageIdentifier(imgPath, frameIndex) }.AsConst()); } } else { foreach (int frameIndex in cmdLine.FrameIndexes) { if (frameIndex >= frames.Count) { Console.Error.WriteLine("{0} in {1} has {2} frames in it, so frame index {3} is not valid.", imgPath, cmdLine.NpkPath, frames.Count, frameIndex); Environment.Exit(1); } frameInfo.Add(new AnimationFrame() { DelayInMs = cmdLine.FrameDelayInMs, Image = new ImageIdentifier(imgPath, frameIndex) }.AsConst()); } } return frameInfo; }
static NpkDirContents GetNpkContents(string npkFilePath) { using (NpkReader npk = new NpkReader(npkFilePath)) { return new NpkDirContents(Path.GetFileName(npkFilePath), npk.Frames); } }
private static NpkPath GetImgPath(CommandLineArgs cmdLine, NpkReader npk) { if (cmdLine.ImgPath != null) { NpkPath imgPath = new NpkPath(cmdLine.ImgPath); IList<NpkPath> imgPathComponents = imgPath.GetPathComponents(); if (imgPathComponents.Count >= 1 && !imgPathComponents[0].Path.Equals("sprite", StringComparison.OrdinalIgnoreCase)) { // add sprite/ prefix if present imgPath = NpkPath.Combine("sprite", imgPath); } if (!npk.Images.ContainsKey(imgPath)) { Console.Error.WriteLine("There is no img file with path {0} in NPK file {1}", cmdLine.ImgPath, cmdLine.NpkPath); Environment.Exit(1); } return imgPath; } else { List<NpkPath> matchingPaths = new List<NpkPath>(); // Only the .img name was given. Look for it. foreach (NpkPath path in npk.Images.Keys) { if (path.GetFileName().Path.Equals(cmdLine.ImgName, StringComparison.OrdinalIgnoreCase)) { matchingPaths.Add(path); } } if (matchingPaths.Count == 1) { return matchingPaths[0]; } else if (matchingPaths.Count == 0) { Console.Error.WriteLine("There is no img file called {0} in NPK file {1}", cmdLine.ImgName, cmdLine.NpkPath); Environment.Exit(1); return null; // not reached } else { Console.Error.WriteLine("There are multiple img files matching the name {0} in NPK file {1}: {2}", cmdLine.ImgName, cmdLine.NpkPath, string.Join(", ", matchingPaths)); Environment.Exit(1); return null; // not reached } } }
public void Dispose() { if (_reader != null) { _reader.Dispose(); _reader = null; } if (_npkStream != null) { _npkStream.Dispose(); _npkStream = null; } _openFilePath = null; _disposed = true; }
/// <summary> /// If opening fails, the state is the same as it was before the open. /// </summary> /// <param name="path"></param> public void Open(string path) { ThrowIfDisposed(); // Open new file first to get any errors out of the way, then switch to it NpkReader newReader = null; FileStream newStream = null; try { newReader = new NpkReader(path); newStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); } catch (Exception) { if (newStream != null) { newStream.Dispose(); newReader.Dispose(); } throw; } NpkReader oldReader = _reader; FileStream oldStream = _npkStream; _reader = newReader; _npkStream = newStream; _openFilePath = path; if (oldStream != null) { oldStream.Dispose(); } if (oldReader != null) { oldReader.Dispose(); } }
static void Main(string[] args) { using (NpkReader npk = new NpkReader(@"C:\Neople\DFO\ImagePacks2\sprite_character_fighter_equipment_avatar_cap.NPK")) { npk.PreLoadAllSpriteFrameMetadata(); List<NpkPath> imgs = npk.Frames.Where(kvp => kvp.Value.Any(f => f.CompressedLength == 84)).Select(kvp => kvp.Key).ToList(); foreach (NpkPath img in imgs) { IReadOnlyList<FrameInfo> frames = npk.Frames[img]; for (int i = 0; i < frames.Count; i++) { if (frames[i].CompressedLength == 84 && !frames[i].IsCompressed) { Console.WriteLine(string.Format("{0} {1}", img, i)); } } } } Environment.Exit(0); foreach (string path in Directory.GetFiles(@"C:\Neople\DFO\ImagePacks2", "*.NPK")) { Console.WriteLine(path); using (NpkReader npk = new NpkReader(path)) { npk.PreLoadAllSpriteFrameMetadata(); foreach (NpkPath npkPath in npk.Frames.Keys) { var x = npk.Frames[npkPath]; for(int i = 0; i < x.Count; i++) { FrameInfo frame = x[i]; if (!frame.IsCompressed && frame.LinkFrame == null) { string pixelFormatString = frame.PixelFormat.ToString(); int actualLength = frame.Width * frame.Height * 2; if (frame.PixelFormat == PixelDataFormat.EightEightEightEight) { actualLength *= 2; } if (frame.CompressedLength != actualLength) { Console.WriteLine("Pixel Format: {0,22}, Compressed Length: {1,9}, Actual Length: {2,9} {3} {4}", pixelFormatString, frame.CompressedLength, actualLength, npkPath, i); } } } } } } Environment.Exit(0); using (NpkReader npkReader = new NpkReader(@"C:\Neople\DFO\ImagePacks2\sprite_monster_impossible_bakal.NPK")) using (NpkReader coolReader = new NpkReader(@"C:\Neople\DFO\ImagePacks2\sprite_character_swordman_effect_sayaex.NPK")) { DFO.Common.Images.Image image = npkReader.GetImage("monster/impossible_bakal/ashcore.img", 0); //Image image2 = npkReader.GetImage("worldmap/act1/elvengard.img", 1); using (Bitmap bitmap = new Bitmap(image.Attributes.Width, image.Attributes.Height)) { BitmapData raw = bitmap.LockBits(new Rectangle(0, 0, image.Attributes.Width, image.Attributes.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); unsafe { byte* ptr = (byte*)raw.Scan0; // RGBA -> BGRA (pixels in the bitmap have endianness) int width = image.Attributes.Width; int height = image.Attributes.Height; int stride = raw.Stride; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { ptr[y * stride + x * 4 + 0] = image.PixelData[y * width * 4 + x * 4 + 2]; ptr[y * stride + x * 4 + 1] = image.PixelData[y * width * 4 + x * 4 + 1]; ptr[y * stride + x * 4 + 2] = image.PixelData[y * width * 4 + x * 4 + 0]; ptr[y * stride + x * 4 + 3] = image.PixelData[y * width * 4 + x * 4 + 3]; } } } bitmap.UnlockBits(raw); bitmap.Save(@"output.png", System.Drawing.Imaging.ImageFormat.Png); RawAnimation animationData = new RawAnimation(); animationData.Loop = true; animationData.Frames = new List<ConstAnimationFrame>() { new AnimationFrame() { DelayInMs = 1000, Image = new ImageIdentifier("worldmap/act1/elvengard.img", 0) }.AsConst(), new AnimationFrame() { DelayInMs = 1000, Image = new ImageIdentifier("worldmap/act1/elvengard.img", 1) }.AsConst() }; RawAnimation cool = new RawAnimation(); cool.Loop = true; cool.Frames = new List<ConstAnimationFrame>() { new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 0) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 1) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 2) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 3) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 4) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 5) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 6) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 7) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 8) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 9) }.AsConst(), }; using (GifMaker giffer = new GifMaker(npkReader, disposeImageSource: false)) using (GifMaker coolGiffer = new GifMaker(coolReader, disposeImageSource: false)) using (FileStream gifOutputStream = new FileStream("output.gif", FileMode.Create, FileAccess.ReadWrite, FileShare.None)) using (FileStream coolGifOutputStream = new FileStream("cool.gif", FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { giffer.Create(animationData.AsConst(), gifOutputStream); coolGiffer.Create(cool.AsConst(), coolGifOutputStream); } } Console.WriteLine("Success!"); } }
static void Main(string[] args) { foreach (string path in Directory.GetFiles(@"C:\Neople\DFO\ImagePacks2", "*.NPK")) { using (NpkReader npk = new NpkReader(path)) { if (npk.Images.Keys.Any(img => img.Path.EndsWith("bufficon.img"))) { Console.WriteLine(path); Environment.Exit(0); } Console.WriteLine("Read {0}", path); } } Console.WriteLine("Not found!"); Environment.Exit(0); using (NpkReader npkReader = new NpkReader(@"C:\Neople\DFO\ImagePacks2\sprite_monster_impossible_bakal.NPK")) using (NpkReader coolReader = new NpkReader(@"C:\Neople\DFO\ImagePacks2\sprite_character_swordman_effect_sayaex.NPK")) { DFO.Common.Images.Image image = npkReader.GetImage("monster/impossible_bakal/ashcore.img", 0); //Image image2 = npkReader.GetImage("worldmap/act1/elvengard.img", 1); using (Bitmap bitmap = new Bitmap(image.Attributes.Width, image.Attributes.Height)) { BitmapData raw = bitmap.LockBits(new Rectangle(0, 0, image.Attributes.Width, image.Attributes.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); unsafe { byte* ptr = (byte*)raw.Scan0; // RGBA -> BGRA (pixels in the bitmap have endianness) int width = image.Attributes.Width; int height = image.Attributes.Height; int stride = raw.Stride; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { ptr[y * stride + x * 4 + 0] = image.PixelData[y * width * 4 + x * 4 + 2]; ptr[y * stride + x * 4 + 1] = image.PixelData[y * width * 4 + x * 4 + 1]; ptr[y * stride + x * 4 + 2] = image.PixelData[y * width * 4 + x * 4 + 0]; ptr[y * stride + x * 4 + 3] = image.PixelData[y * width * 4 + x * 4 + 3]; } } } bitmap.UnlockBits(raw); bitmap.Save(@"output.png", System.Drawing.Imaging.ImageFormat.Png); RawAnimation animationData = new RawAnimation(); animationData.Loop = true; animationData.Frames = new List<ConstAnimationFrame>() { new AnimationFrame() { DelayInMs = 1000, Image = new ImageIdentifier("worldmap/act1/elvengard.img", 0) }.AsConst(), new AnimationFrame() { DelayInMs = 1000, Image = new ImageIdentifier("worldmap/act1/elvengard.img", 1) }.AsConst() }; RawAnimation cool = new RawAnimation(); cool.Loop = true; cool.Frames = new List<ConstAnimationFrame>() { new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 0) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 1) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 2) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 3) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 4) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 5) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 6) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 7) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 8) }.AsConst(), new AnimationFrame() { DelayInMs = 100, Image = new ImageIdentifier("character/swordman/effect/sayaex/wingdodge.img", 9) }.AsConst(), }; using (GifMaker giffer = new GifMaker(npkReader, disposeImageSource: false)) using (GifMaker coolGiffer = new GifMaker(coolReader, disposeImageSource: false)) using (FileStream gifOutputStream = new FileStream("output.gif", FileMode.Create, FileAccess.ReadWrite, FileShare.None)) using (FileStream coolGifOutputStream = new FileStream("cool.gif", FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { giffer.Create(animationData.AsConst(), gifOutputStream); coolGiffer.Create(cool.AsConst(), coolGifOutputStream); } } Console.WriteLine("Success!"); } }
private static NpkReader LoadNpk(string path) { NpkReader npk = null; try { npk = new NpkReader(path); } catch (FileNotFoundException) { Console.Error.WriteLine("NPK file {0} not found.", path); Environment.Exit(1); } catch (UnauthorizedAccessException) { Console.Error.WriteLine("You do not have permission to read NPK file {0}", path); Environment.Exit(1); } catch (NpkException ex) { Console.Error.WriteLine("There was an error while loading the NPK file. The file format may have changed. Here is some information that may help debug the issue: {0}\n\n{1}", Utils.GetExceptionMessageWithInnerExceptions(ex), ex.StackTrace); Environment.Exit(1); } catch (Exception ex) { Console.Error.WriteLine("There was an error while loading the NPK file: {0}", ex.Message); Environment.Exit(1); } return npk; }
public void Open(string npkPath) { if (!CanOpen) { return; } // TODO: async? try { NpkReader oldNpk = _npk; _npk = new NpkReader(npkPath); if (oldNpk != null) { oldNpk.Dispose(); } } catch (Exception ex) { // Display error // Handle NpkExcption separately? // Better way of displaying than modal? MessageBox.Show(string.Format("Error opening NPK file: {0}", ex.Message)); return; } InnerFileList.Clear(); FrameList.Clear(); foreach (NpkPath imgPath in _npk.Images.Keys) { string imgName = imgPath.GetPathComponents().LastOrDefault(); if (imgName == null) continue; // TODO: Log this, something would have to be strange InnerFileList.Add(new InnerNpkFile(name: imgName, path: imgPath.Path)); } // Select first .img if (InnerFileList.Count > 0) { InnerFileList.MoveCurrentToFirst(); } }
/// <summary> /// /// </summary> /// <param name="imgPath"></param> /// <param name="frameIndex"></param> /// <param name="newFrameMetadata">If this indicates a link frame, <paramref name="newFramePixels"/> is ignored. The IsCompressed flag is honored, compressing the image if it is set. The CompressedLength field is not used.</param> /// <param name="newFramePixels">Readable stream consisting solely of the pixel data, in the format indicated by the metadata.</param> public void EditFrame(NpkPath imgPath, int frameIndex, FrameInfo newFrameMetadata, Stream newFramePixels) { ThrowIfDisposed(); ThrowIfNoFileOpen(); if (!_reader.Frames.ContainsKey(imgPath)) { throw new ArgumentException("{0} is not in the NPK.".F(imgPath)); } if (frameIndex >= _reader.Frames[imgPath].Count) { throw new ArgumentException("{0} does not have a frame {1}.".F(imgPath, frameIndex)); } NpkFileTableEntry entryOfImgEditing = _reader.Files.Where(f => f.Name.Equals(imgPath)).First(); IReadOnlyList <FrameInfo> frameListOfImgEditing = _reader.Frames[imgPath]; FrameInfo frameMetadataOfFrameEditing = frameListOfImgEditing[frameIndex]; // Render the new frame in memory // pixelData is null if it's a link frame // pixelData length may be bigger than the actual pixel data. Use newPixelDataLength instead of newPixelData.Length int newPixelDataLength; byte[] newPixelData = GetPixelData(newFrameMetadata, newFramePixels, out newPixelDataLength); byte[] frameMetadataBytes = GetFrameMetadataBytes(newFrameMetadata, newPixelDataLength); string tempNpkPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".NPK"); using (FileStream tempFileStream = File.OpenWrite(tempNpkPath)) { WriteEditedNPK(tempFileStream, imgPath, entryOfImgEditing, frameIndex, frameListOfImgEditing, frameMetadataOfFrameEditing, newFrameMetadata, newPixelData, newPixelDataLength, frameMetadataBytes); } // temp file now has the new NPK! // close _reader // close _npkStream // delete original file // move temp file // TODO: "refresh" it _reader.Dispose(); _npkStream.Dispose(); // TODO: Error handling File.Delete(_openFilePath); File.Move(tempNpkPath, _openFilePath); // reopen try { _reader = new NpkReader(_openFilePath); } catch (Exception) { _openFilePath = null; _reader = null; _npkStream = null; throw; } try { _npkStream = new FileStream(_openFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); } catch (Exception) { _openFilePath = null; _reader.Dispose(); _reader = null; _npkStream = null; throw; } }
public LazyFramesReadOnlyDictionary(NpkReader npk) { npk.ThrowIfNull("npk"); m_npk = npk; }