コード例 #1
0
        private void WritedEditedFileTable(FileStream tempFileStream, NpkFileTableEntry entryOfImgEditing, int imgByteCountChange, byte[] imgPathBytes)
        {
            foreach (NpkFileTableEntry file in _reader.Files)
            {
                // uint - file location offset of file
                // uint - file size in bytes
                // 256 bytes for NPK path (eg sprite/foo/bar.img) - The path in ASCII is padded with 0 bytes to 256 bytes then xor'd with a static "key"

                if (file.Location.FileOffset <= entryOfImgEditing.Location.FileOffset)
                {
                    // If this file's bytes comes before the file whose bytes we're changing, its offset does not change.
                    // Same if it's the same file whose bytes we're changing or one that uses the same bytes.
                    tempFileStream.WriteUnsigned32Le((uint)file.Location.FileOffset, _intWriteBuffer);
                }
                else
                {
                    // otherwise, add the difference (possibly negative) between sizes of new file and old file
                    int newOffset = file.Location.FileOffset + imgByteCountChange;
                    tempFileStream.WriteUnsigned32Le((uint)newOffset, _intWriteBuffer);
                }

                if (file.Location.FileOffset != entryOfImgEditing.Location.FileOffset)
                {
                    // If this file is not the file we're changing or one that uses the same bytes, the size does not change
                    tempFileStream.WriteUnsigned32Le((uint)file.Location.Size, _intWriteBuffer);
                }
                else
                {
                    int newImgSize = file.Location.Size + imgByteCountChange;
                    tempFileStream.WriteUnsigned32Le((uint)newImgSize, _intWriteBuffer);
                }

                for (int i = 0; i < 256; i++)
                {
                    imgPathBytes[i] = 0;
                }

                Encoding.ASCII.GetBytes(file.Name.Path, 0, file.Name.Path.Length, imgPathBytes, 0);
                for (int i = 0; i < 256; i++)
                {
                    imgPathBytes[i] ^= NpkReader.s_key[i];
                }

                tempFileStream.Write(imgPathBytes, 0, 256);
            }
        }
コード例 #2
0
        private void WriteEditedNPK(FileStream tempFileStream, NpkPath imgPath, NpkFileTableEntry entryOfImgEditing, int editedFrameIndex,
                                    IReadOnlyList <FrameInfo> frameListOfImgEditing, FrameInfo frameMetadataOfFrameEditing,
                                    FrameInfo newFrameMetadata, byte[] newPixelData, int newPixelDataLength, byte[] frameMetadataBytes)
        {
            int imgByteCountChange = GetImgByteCountChange(frameMetadataOfFrameEditing, newFrameMetadata, newPixelDataLength);
            List <NpkByteRange> frameLocationsOfImgEditing = _reader.FrameLocations[imgPath];

            // Header is same
            tempFileStream.Write(NpkReader.s_headerBytes, 0, NpkReader.s_headerBytes.Length);

            // number of files is same
            tempFileStream.WriteUnsigned32Le((uint)_reader.Files.Count, _intWriteBuffer);

            byte[] imgPathBytes = new byte[256];

            // Write file table
            WritedEditedFileTable(tempFileStream, entryOfImgEditing, imgByteCountChange, imgPathBytes);

            // Write from original stream until offset of file we're changing
            // Write from current until currentEntry.Location.FileOffset
            _npkStream.Seek(tempFileStream.Position, SeekOrigin.Begin);
            int numBytesToCopy = (int)(entryOfImgEditing.Location.FileOffset - tempFileStream.Position);

            _npkStream.CopyToPartially(tempFileStream, numBytesToCopy);

            // Now write the new .img

            WriteEditedImg(tempFileStream, editedFrameIndex, frameListOfImgEditing, frameMetadataOfFrameEditing, newFrameMetadata, newPixelData, newPixelDataLength, frameMetadataBytes, frameLocationsOfImgEditing);

            // now write the rest of the original file that's after this .img
            if (entryOfImgEditing.Location.FileOffset + entryOfImgEditing.Location.Size < _npkStream.Length)
            {
                _npkStream.Seek(entryOfImgEditing.Location.FileOffset + entryOfImgEditing.Location.Size, SeekOrigin.Begin);
                numBytesToCopy = (int)_npkStream.Length - (entryOfImgEditing.Location.FileOffset + entryOfImgEditing.Location.Size);
                _npkStream.CopyToPartially(tempFileStream, numBytesToCopy);
            }
        }
コード例 #3
0
        /// <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;
            }
        }