From 2264fa40a01d5c03077b8a61288cfdd9955f585e Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sat, 9 Feb 2019 22:39:23 -0500 Subject: [PATCH 01/19] Include OP2BmpLoader in external OP2Utility.h --- include/OP2Utility.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/OP2Utility.h b/include/OP2Utility.h index 7d0b3a49..51de8e1d 100644 --- a/include/OP2Utility.h +++ b/include/OP2Utility.h @@ -18,8 +18,9 @@ #include "../src/Map/Map.h" -#include "../src/Sprite/ArtFile.h" #include "../src/Bitmap/BitmapFile.h" +#include "../src/Sprite/ArtFile.h" +#include "../src/Sprite/OP2BmpLoader.h" #include "../src/Stream/FileReader.h" #include "../src/Stream/SliceReader.h" From ffa5afb91ed5622a7ff78251ab103c8230597f5f Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sat, 9 Feb 2019 22:43:12 -0500 Subject: [PATCH 02/19] Allow OP2BmpLoader to pass image, layer, frame, and animation counts --- src/Sprite/OP2BmpLoader.cpp | 7 +++++++ src/Sprite/OP2BmpLoader.h | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/src/Sprite/OP2BmpLoader.cpp b/src/Sprite/OP2BmpLoader.cpp index 96a4062a..ec3de9e8 100644 --- a/src/Sprite/OP2BmpLoader.cpp +++ b/src/Sprite/OP2BmpLoader.cpp @@ -32,6 +32,13 @@ void OP2BmpLoader::ExtractImage(std::size_t index, const std::string& filenameOu BitmapFile::WriteIndexed(filenameOut, imageMeta.GetBitCount(), imageMeta.width, -static_cast(imageMeta.height), palette, pixelContainer); } +std::size_t OP2BmpLoader::FrameCount(std::size_t animationIndex) const { + return artFile.animations[animationIndex].frames.size(); +} + +std::size_t OP2BmpLoader::LayerCount(std::size_t animationIndex, std::size_t frameIndex) const { + return artFile.animations[animationIndex].frames[frameIndex].layers.size(); +} std::unique_ptr OP2BmpLoader::GetPixels(std::size_t startingIndex, std::size_t length) { return std::make_unique(bmpReader.Slice(startingIndex, length)); diff --git a/src/Sprite/OP2BmpLoader.h b/src/Sprite/OP2BmpLoader.h index a17a9276..5ebefd2c 100644 --- a/src/Sprite/OP2BmpLoader.h +++ b/src/Sprite/OP2BmpLoader.h @@ -12,6 +12,11 @@ class OP2BmpLoader OP2BmpLoader(std::string bmpFilename, std::string artFilename); void ExtractImage(std::size_t index, const std::string& filenameOut); + + inline std::size_t ImageCount() const { return artFile.imageMetas.size(); } + inline std::size_t AnimationCount() const { return artFile.animations.size(); } + std::size_t FrameCount(std::size_t animationIndex) const; + std::size_t LayerCount(std::size_t animationIndex, std::size_t frameIndex) const; private: // Bmp loader for Outpost 2 specific BMP file From 98b7cab4dc5b1f8ed949e30f4679eb1d99db01a8 Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sat, 9 Feb 2019 22:45:18 -0500 Subject: [PATCH 03/19] Add OP2BmpLoader constructor that can load data from an artFile stream This allows instantiating OP2BmpLoader without extracting op2_art.prt from the art.vol (volume) --- src/Sprite/OP2BmpLoader.cpp | 3 +++ src/Sprite/OP2BmpLoader.h | 1 + 2 files changed, 4 insertions(+) diff --git a/src/Sprite/OP2BmpLoader.cpp b/src/Sprite/OP2BmpLoader.cpp index ec3de9e8..2b77b0d0 100644 --- a/src/Sprite/OP2BmpLoader.cpp +++ b/src/Sprite/OP2BmpLoader.cpp @@ -8,6 +8,9 @@ OP2BmpLoader::OP2BmpLoader(std::string bmpFilename, std::string artFilename) : bmpReader(bmpFilename), artFile(ArtFile::Read(artFilename)) { } +OP2BmpLoader::OP2BmpLoader(std::string bmpFilename, Stream::BidirectionalSeekableReader& artFileStream) : + bmpReader(bmpFilename), artFile(ArtFile::Read(artFileStream)) { } + void OP2BmpLoader::ExtractImage(std::size_t index, const std::string& filenameOut) { artFile.VerifyImageIndexInBounds(index); diff --git a/src/Sprite/OP2BmpLoader.h b/src/Sprite/OP2BmpLoader.h index 5ebefd2c..398920dc 100644 --- a/src/Sprite/OP2BmpLoader.h +++ b/src/Sprite/OP2BmpLoader.h @@ -10,6 +10,7 @@ class OP2BmpLoader { public: OP2BmpLoader(std::string bmpFilename, std::string artFilename); + OP2BmpLoader(std::string bmpFilename, Stream::BidirectionalSeekableReader& artFileStream); void ExtractImage(std::size_t index, const std::string& filenameOut); From c9d5edd4921e48705e294c392c2cbcdd1583dab7 Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sat, 9 Feb 2019 22:48:15 -0500 Subject: [PATCH 04/19] Allow OP2BmpLoader to pass a 1 or 8 bit palette as appropriate Still need to look closely at 1 bit images to ensure they are forming fully correctly. Earlier it would just throw an error. --- src/Sprite/OP2BmpLoader.cpp | 20 ++++++++++++++++++-- src/Sprite/OP2BmpLoader.h | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Sprite/OP2BmpLoader.cpp b/src/Sprite/OP2BmpLoader.cpp index 2b77b0d0..7c6a35c0 100644 --- a/src/Sprite/OP2BmpLoader.cpp +++ b/src/Sprite/OP2BmpLoader.cpp @@ -17,8 +17,7 @@ void OP2BmpLoader::ExtractImage(std::size_t index, const std::string& filenameOu ImageMeta& imageMeta = artFile.imageMetas[index]; - std::vector palette(artFile.palettes[imageMeta.paletteIndex].size()); - std::copy(artFile.palettes[imageMeta.paletteIndex].begin(), artFile.palettes[imageMeta.paletteIndex].end(), palette.begin()); + const auto palette = CreatePalette(imageMeta); std::size_t pixelOffset = imageMeta.pixelDataOffset + 14 + sizeof(ImageHeader) + palette.size() * sizeof(Color); @@ -42,6 +41,23 @@ std::size_t OP2BmpLoader::FrameCount(std::size_t animationIndex) const { std::size_t OP2BmpLoader::LayerCount(std::size_t animationIndex, std::size_t frameIndex) const { return artFile.animations[animationIndex].frames[frameIndex].layers.size(); } + +std::vector OP2BmpLoader::CreatePalette(const ImageMeta& imageMeta) const +{ + std::vector palette; + + if (imageMeta.GetBitCount() == 1) { + palette.push_back(Color{ 0, 0, 0 }); + palette.push_back(Color{ 255, 255, 255 }); + } + else { + palette.resize(artFile.palettes[imageMeta.paletteIndex].size()); + std::copy(artFile.palettes[imageMeta.paletteIndex].begin(), artFile.palettes[imageMeta.paletteIndex].end(), palette.begin()); + } + + return palette; +} + std::unique_ptr OP2BmpLoader::GetPixels(std::size_t startingIndex, std::size_t length) { return std::make_unique(bmpReader.Slice(startingIndex, length)); diff --git a/src/Sprite/OP2BmpLoader.h b/src/Sprite/OP2BmpLoader.h index 398920dc..76515d26 100644 --- a/src/Sprite/OP2BmpLoader.h +++ b/src/Sprite/OP2BmpLoader.h @@ -26,5 +26,6 @@ class OP2BmpLoader Stream::FileReader bmpReader; ArtFile artFile; + std::vector CreatePalette(const ImageMeta& imageMeta) const; std::unique_ptr GetPixels(std::size_t startingIndex, std::size_t length); }; From 82e89cfe0dd8b654efdec2bf7bd89136f5c2178f Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sat, 9 Feb 2019 22:49:16 -0500 Subject: [PATCH 05/19] Mark ExtractImage internal variables as const where appropriate --- src/Sprite/OP2BmpLoader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Sprite/OP2BmpLoader.cpp b/src/Sprite/OP2BmpLoader.cpp index 7c6a35c0..a966f961 100644 --- a/src/Sprite/OP2BmpLoader.cpp +++ b/src/Sprite/OP2BmpLoader.cpp @@ -15,13 +15,13 @@ void OP2BmpLoader::ExtractImage(std::size_t index, const std::string& filenameOu { artFile.VerifyImageIndexInBounds(index); - ImageMeta& imageMeta = artFile.imageMetas[index]; + const ImageMeta& imageMeta = artFile.imageMetas[index]; const auto palette = CreatePalette(imageMeta); - std::size_t pixelOffset = imageMeta.pixelDataOffset + 14 + sizeof(ImageHeader) + palette.size() * sizeof(Color); + const std::size_t pixelOffset = imageMeta.pixelDataOffset + 14 + sizeof(ImageHeader) + palette.size() * sizeof(Color); - auto pixels = GetPixels(pixelOffset, imageMeta.scanLineByteWidth * imageMeta.height); + const auto pixels = GetPixels(pixelOffset, imageMeta.scanLineByteWidth * imageMeta.height); std::vector pixelContainer(imageMeta.scanLineByteWidth * imageMeta.height); (*pixels).Read(pixelContainer); From dc5b645ac9da16eea020f5c7e6bb9cbcf0fe6ed6 Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sat, 9 Feb 2019 22:51:27 -0500 Subject: [PATCH 06/19] Improve and standardize casing on function description comments --- src/Bitmap/BitmapFile.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Bitmap/BitmapFile.h b/src/Bitmap/BitmapFile.h index ed67d17c..36909e29 100644 --- a/src/Bitmap/BitmapFile.h +++ b/src/Bitmap/BitmapFile.h @@ -22,14 +22,15 @@ class BitmapFile std::vector palette; std::vector pixels; + // Uses a default 4 byte pitch static BitmapFile CreateDefaultIndexed(uint16_t bitCount, uint32_t width, uint32_t height); - // BMP Reader only supports Indexed Color palettes (1, 2, and 8 bit BMPs). + // BMP Reader only supports indexed color palettes (1, 2, and 8 bit BMPs). static BitmapFile ReadIndexed(const std::string& filename); static BitmapFile ReadIndexed(Stream::BidirectionalSeekableReader& seekableReader); - // BMP Writer only supporting Indexed Color palettes (1, 2, and 8 bit BMPs). - // @indexedPixels: Must include padding to fill each image row out to the next 4 byte memory border (pitch). + // BMP Writer only supports indexed color palettes (1, 2, and 8 bit BMPs). + // @indexedPixels: Must include padding to fill each image row out to the next byte memory border (pitch). 4 byte pitch is typical. static void WriteIndexed(std::string filename, uint16_t bitCount, int32_t width, int32_t height, std::vector palette, const std::vector& indexedPixels); static void WriteIndexed(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int32_t width, int32_t height, std::vector palette, const std::vector& indexedPixels); static void WriteIndexed(std::string filename, const BitmapFile& bitmapFile); From bb817323f466fa76564be10b51f8dab9bf07bbef Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sat, 9 Feb 2019 22:59:19 -0500 Subject: [PATCH 07/19] Rename CalculatePitch to CalculateDefaultPitch Better represents the fact that pitch does not have to be 4 byte intervals. Still provides a standard default value so user doesn't have to worry about calculating their own if they do not wish to. --- src/Bitmap/BitmapFile.cpp | 4 ++-- src/Bitmap/ImageHeader.cpp | 6 +++--- src/Bitmap/ImageHeader.h | 5 +++-- src/Bitmap/IndexedBmpWriter.cpp | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Bitmap/BitmapFile.cpp b/src/Bitmap/BitmapFile.cpp index 485a8a0d..c6d2fa9d 100644 --- a/src/Bitmap/BitmapFile.cpp +++ b/src/Bitmap/BitmapFile.cpp @@ -7,7 +7,7 @@ BitmapFile BitmapFile::CreateDefaultIndexed(uint16_t bitCount, uint32_t width, u BitmapFile bitmapFile; bitmapFile.imageHeader = ImageHeader::Create(width, height, bitCount); bitmapFile.palette.resize(bitmapFile.imageHeader.CalcMaxIndexedPaletteSize()); - bitmapFile.pixels.resize(bitmapFile.imageHeader.CalculatePitch() * height); + bitmapFile.pixels.resize(bitmapFile.imageHeader.CalculateDefaultPitch() * height); const std::size_t pixelOffset = sizeof(BmpHeader) + sizeof(ImageHeader) + bitmapFile.palette.size() * sizeof(Color); const std::size_t bitmapFileSize = pixelOffset + bitmapFile.pixels.size() * sizeof(uint8_t); @@ -40,7 +40,7 @@ void BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch() const void BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(uint16_t bitCount, int32_t width, int32_t height, std::size_t pixelsWithPitchSize) { - if (pixelsWithPitchSize != ImageHeader::CalculatePitch(bitCount, width) * std::abs(height)) { + if (pixelsWithPitchSize != ImageHeader::CalculateDefaultPitch(bitCount, width) * std::abs(height)) { throw std::runtime_error("The size of pixels does not match the image's height time pitch"); } } diff --git a/src/Bitmap/ImageHeader.cpp b/src/Bitmap/ImageHeader.cpp index 4c412313..fbbe9044 100644 --- a/src/Bitmap/ImageHeader.cpp +++ b/src/Bitmap/ImageHeader.cpp @@ -63,12 +63,12 @@ void ImageHeader::VerifyValidBitCount(uint16_t bitCount) } } -std::size_t ImageHeader::CalculatePitch() const +std::size_t ImageHeader::CalculateDefaultPitch() const { - return ImageHeader::CalculatePitch(bitCount, width); + return ImageHeader::CalculateDefaultPitch(bitCount, width); } -std::size_t ImageHeader::CalculatePitch(uint16_t bitCount, int32_t width) +std::size_t ImageHeader::CalculateDefaultPitch(uint16_t bitCount, int32_t width) { const auto bytesOfPixelsPerRow = CalcPixelByteWidth(bitCount, width); return (bytesOfPixelsPerRow + 3) & ~3; diff --git a/src/Bitmap/ImageHeader.h b/src/Bitmap/ImageHeader.h index 939d8355..91116eae 100644 --- a/src/Bitmap/ImageHeader.h +++ b/src/Bitmap/ImageHeader.h @@ -42,8 +42,9 @@ struct ImageHeader void VerifyValidBitCount() const; static void VerifyValidBitCount(uint16_t bitCount); - std::size_t CalculatePitch() const; - static std::size_t CalculatePitch(uint16_t bitCount, int32_t width); + // Default pitch interval is 32 + std::size_t CalculateDefaultPitch() const; + static std::size_t CalculateDefaultPitch(uint16_t bitCount, int32_t width); // Does not include padding std::size_t CalcPixelByteWidth() const; diff --git a/src/Bitmap/IndexedBmpWriter.cpp b/src/Bitmap/IndexedBmpWriter.cpp index df9fe8d1..f529cc52 100644 --- a/src/Bitmap/IndexedBmpWriter.cpp +++ b/src/Bitmap/IndexedBmpWriter.cpp @@ -38,7 +38,7 @@ void BitmapFile::WriteIndexed(Stream::BidirectionalSeekableWriter& seekableWrite void BitmapFile::WriteHeaders(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int width, int height, const std::vector& palette) { std::size_t pixelOffset = sizeof(BmpHeader) + sizeof(ImageHeader) + palette.size() * sizeof(Color); - std::size_t fileSize = pixelOffset + ImageHeader::CalculatePitch(bitCount, width) * std::abs(height); + std::size_t fileSize = pixelOffset + ImageHeader::CalculateDefaultPitch(bitCount, width) * std::abs(height); if (fileSize > UINT32_MAX) { throw std::runtime_error("Bitmap size is too large to save to disk."); @@ -53,7 +53,7 @@ void BitmapFile::WriteHeaders(Stream::BidirectionalSeekableWriter& seekableWrite void BitmapFile::WritePixels(Stream::BidirectionalSeekableWriter& seekableWriter, const std::vector& pixels, int32_t width, uint16_t bitCount) { - const auto pitch = ImageHeader::CalculatePitch(bitCount, width); + const auto pitch = ImageHeader::CalculateDefaultPitch(bitCount, width); const auto bytesOfPixelsPerRow = ImageHeader::CalcPixelByteWidth(bitCount, width); const std::vector padding(pitch - bytesOfPixelsPerRow, 0); From 3942ceaef590e1da5924408076f507ab85808357 Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sat, 9 Feb 2019 23:04:27 -0500 Subject: [PATCH 08/19] Allow setting a custom pitch when writing bitmaps --- src/Bitmap/BitmapFile.cpp | 4 ++-- src/Bitmap/BitmapFile.h | 11 +++++----- src/Bitmap/IndexedBmpWriter.cpp | 37 +++++++++++++++++++++++---------- src/Sprite/OP2BmpLoader.cpp | 2 +- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/Bitmap/BitmapFile.cpp b/src/Bitmap/BitmapFile.cpp index c6d2fa9d..e52bc3ec 100644 --- a/src/Bitmap/BitmapFile.cpp +++ b/src/Bitmap/BitmapFile.cpp @@ -38,9 +38,9 @@ void BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch() const BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(imageHeader.bitCount, imageHeader.width, imageHeader.height, pixels.size()); } -void BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(uint16_t bitCount, int32_t width, int32_t height, std::size_t pixelsWithPitchSize) +void BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(uint16_t bitCount, std::size_t pitch, int32_t height, std::size_t pixelsWithPitchSize) { - if (pixelsWithPitchSize != ImageHeader::CalculateDefaultPitch(bitCount, width) * std::abs(height)) { + if (pixelsWithPitchSize != pitch * std::abs(height)) { throw std::runtime_error("The size of pixels does not match the image's height time pitch"); } } diff --git a/src/Bitmap/BitmapFile.h b/src/Bitmap/BitmapFile.h index 36909e29..9c37a1b8 100644 --- a/src/Bitmap/BitmapFile.h +++ b/src/Bitmap/BitmapFile.h @@ -31,8 +31,8 @@ class BitmapFile // BMP Writer only supports indexed color palettes (1, 2, and 8 bit BMPs). // @indexedPixels: Must include padding to fill each image row out to the next byte memory border (pitch). 4 byte pitch is typical. - static void WriteIndexed(std::string filename, uint16_t bitCount, int32_t width, int32_t height, std::vector palette, const std::vector& indexedPixels); - static void WriteIndexed(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int32_t width, int32_t height, std::vector palette, const std::vector& indexedPixels); + static void WriteIndexed(std::string filename, uint16_t bitCount, int32_t width, int32_t height, std::size_t pitch, std::vector palette, const std::vector& indexedPixels); + static void WriteIndexed(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int32_t width, int32_t height, std::size_t pitch, std::vector palette, const std::vector& indexedPixels); static void WriteIndexed(std::string filename, const BitmapFile& bitmapFile); void VerifyIndexedPaletteSizeDoesNotExceedBitCount() const; @@ -42,7 +42,7 @@ class BitmapFile // @width: Width in pixels. Do not include the pitch in width. // @pixelsWithPitchSize: Number of pixels including padding pixels to next 4 byte boundary. void VerifyPixelSizeMatchesImageDimensionsWithPitch() const; - static void VerifyPixelSizeMatchesImageDimensionsWithPitch(uint16_t bitCount, int32_t width, int32_t height, std::size_t pixelsWithPitchSize); + static void VerifyPixelSizeMatchesImageDimensionsWithPitch(uint16_t bitCount, std::size_t pitch, int32_t height, std::size_t pixelsWithPitchSize); void Validate() const; @@ -56,8 +56,9 @@ class BitmapFile static void ReadPixels(Stream::BidirectionalSeekableReader& seekableReader, BitmapFile& bitmapFile); // Write - static void WriteHeaders(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int width, int height, const std::vector& palette); - static void WritePixels(Stream::BidirectionalSeekableWriter& seekableWriter, const std::vector& pixels, int32_t width, uint16_t bitCount); + static std::size_t FindPitch(std::size_t width, std::size_t height, std::size_t pixelCount); + static void WriteHeaders(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int width, int height, std::size_t pitch, const std::vector& palette); + static void WritePixels(Stream::BidirectionalSeekableWriter& seekableWriter, const std::vector& pixels, int32_t width, uint16_t bitCount, std::size_t pitch); }; bool operator==(const BitmapFile& lhs, const BitmapFile& rhs); diff --git a/src/Bitmap/IndexedBmpWriter.cpp b/src/Bitmap/IndexedBmpWriter.cpp index f529cc52..e19a6db4 100644 --- a/src/Bitmap/IndexedBmpWriter.cpp +++ b/src/Bitmap/IndexedBmpWriter.cpp @@ -11,34 +11,50 @@ void BitmapFile::WriteIndexed(std::string filename, const BitmapFile& bitmapFile } bitmapFile.Validate(); + const auto pitch = FindPitch(bitmapFile.imageHeader.width, bitmapFile.imageHeader.height, bitmapFile.pixels.size()); - WriteIndexed(filename, bitmapFile.imageHeader.bitCount, bitmapFile.imageHeader.width, bitmapFile.imageHeader.height, bitmapFile.palette, bitmapFile.pixels); + WriteIndexed(filename, bitmapFile.imageHeader.bitCount, bitmapFile.imageHeader.width, bitmapFile.imageHeader.height, pitch, bitmapFile.palette, bitmapFile.pixels); } -void BitmapFile::WriteIndexed(std::string filename, uint16_t bitCount, int32_t width, int32_t height, std::vector palette, const std::vector& indexedPixels) +void BitmapFile::WriteIndexed(std::string filename, uint16_t bitCount, int32_t width, int32_t height, std::size_t pitch, std::vector palette, const std::vector& indexedPixels) { Stream::FileWriter fileWriter(filename); - WriteIndexed(fileWriter, bitCount, width, height, palette, indexedPixels); + WriteIndexed(fileWriter, bitCount, width, height, pitch, palette, indexedPixels); } -void BitmapFile::WriteIndexed(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int32_t width, int32_t height, std::vector palette, const std::vector& indexedPixels) +void BitmapFile::WriteIndexed(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int32_t width, int32_t height, std::size_t pitch, std::vector palette, const std::vector& indexedPixels) { VerifyIndexedImageForSerialization(bitCount); VerifyIndexedPaletteSizeDoesNotExceedBitCount(bitCount, palette.size()); - VerifyPixelSizeMatchesImageDimensionsWithPitch(bitCount, width, height, indexedPixels.size()); + VerifyPixelSizeMatchesImageDimensionsWithPitch(bitCount, pitch, height, indexedPixels.size()); palette.resize(ImageHeader::CalcMaxIndexedPaletteSize(bitCount), DiscreteColor::Black); - WriteHeaders(seekableWriter, bitCount, width, height, palette); + WriteHeaders(seekableWriter, bitCount, width, height, pitch, palette); seekableWriter.Write(palette); - WritePixels(seekableWriter, indexedPixels, width, bitCount); + WritePixels(seekableWriter, indexedPixels, width, bitCount, pitch); } -void BitmapFile::WriteHeaders(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int width, int height, const std::vector& palette) +std::size_t BitmapFile::FindPitch(std::size_t width, std::size_t height, std::size_t pixelCount) +{ + if (pixelCount % height != 0) { + throw std::runtime_error("Unable to calculate a valid pitch based on height and pixel count"); + } + + const std::size_t pitch = pixelCount / height; + + if (pitch < width) { + throw std::runtime_error("Calculated pitch would be smaller than image pixel width"); + } + + return pitch; +} + +void BitmapFile::WriteHeaders(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int width, int height, std::size_t pitch, const std::vector& palette) { std::size_t pixelOffset = sizeof(BmpHeader) + sizeof(ImageHeader) + palette.size() * sizeof(Color); - std::size_t fileSize = pixelOffset + ImageHeader::CalculateDefaultPitch(bitCount, width) * std::abs(height); + std::size_t fileSize = pixelOffset + pitch * std::abs(height); if (fileSize > UINT32_MAX) { throw std::runtime_error("Bitmap size is too large to save to disk."); @@ -51,9 +67,8 @@ void BitmapFile::WriteHeaders(Stream::BidirectionalSeekableWriter& seekableWrite seekableWriter.Write(imageHeader); } -void BitmapFile::WritePixels(Stream::BidirectionalSeekableWriter& seekableWriter, const std::vector& pixels, int32_t width, uint16_t bitCount) +void BitmapFile::WritePixels(Stream::BidirectionalSeekableWriter& seekableWriter, const std::vector& pixels, int32_t width, uint16_t bitCount, std::size_t pitch) { - const auto pitch = ImageHeader::CalculateDefaultPitch(bitCount, width); const auto bytesOfPixelsPerRow = ImageHeader::CalcPixelByteWidth(bitCount, width); const std::vector padding(pitch - bytesOfPixelsPerRow, 0); diff --git a/src/Sprite/OP2BmpLoader.cpp b/src/Sprite/OP2BmpLoader.cpp index a966f961..26bc694b 100644 --- a/src/Sprite/OP2BmpLoader.cpp +++ b/src/Sprite/OP2BmpLoader.cpp @@ -31,7 +31,7 @@ void OP2BmpLoader::ExtractImage(std::size_t index, const std::string& filenameOu throw std::runtime_error("Image height is too large to fit in standard bitmap file format."); } - BitmapFile::WriteIndexed(filenameOut, imageMeta.GetBitCount(), imageMeta.width, -static_cast(imageMeta.height), palette, pixelContainer); + BitmapFile::WriteIndexed(filenameOut, imageMeta.GetBitCount(), imageMeta.width, -static_cast(imageMeta.height), imageMeta.scanLineByteWidth, palette, pixelContainer); } std::size_t OP2BmpLoader::FrameCount(std::size_t animationIndex) const { From d2546c14af3687faac31fa7b0c69f698758f9e40 Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sun, 10 Feb 2019 17:47:54 -0500 Subject: [PATCH 09/19] Update unit tests to include pitch when writing a bitmap --- test/Bitmap/IndexedBmpWriter.test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/Bitmap/IndexedBmpWriter.test.cpp b/test/Bitmap/IndexedBmpWriter.test.cpp index 2d434801..6f82b9c4 100644 --- a/test/Bitmap/IndexedBmpWriter.test.cpp +++ b/test/Bitmap/IndexedBmpWriter.test.cpp @@ -12,8 +12,8 @@ TEST(BitmapFile, InvalidBitCountThrows) const std::vector pixels(4, 0); const std::string filename = "Sprite/data/MonochromeTest.bmp"; - EXPECT_THROW(BitmapFile::WriteIndexed(filename, 3, 1, 1, palette, pixels), std::runtime_error); - EXPECT_THROW(BitmapFile::WriteIndexed(filename, 32, 1, 1, palette, pixels), std::runtime_error); + EXPECT_THROW(BitmapFile::WriteIndexed(filename, 3, 1, 1, 4, palette, pixels), std::runtime_error); + EXPECT_THROW(BitmapFile::WriteIndexed(filename, 32, 1, 1, 4, palette, pixels), std::runtime_error); XFile::DeletePath(filename); } @@ -24,7 +24,7 @@ TEST(BitmapFile, TooManyPaletteEntriesThrows) const std::vector pixels(4, 0); const std::string filename("Sprite/data/PaletteRangeTest.bmp"); - EXPECT_THROW(BitmapFile::WriteIndexed(filename, 1, 1, 1, palette, pixels), std::runtime_error); + EXPECT_THROW(BitmapFile::WriteIndexed(filename, 1, 1, 1, 4, palette, pixels), std::runtime_error); XFile::DeletePath(filename); } @@ -35,7 +35,7 @@ TEST(BitmapFile, WritePartiallyFilledPalette) const std::vector pixels(4, 0); const std::string filename("Sprite/data/PaletteRangeTest.bmp"); - EXPECT_NO_THROW(BitmapFile::WriteIndexed(filename, 1, 1, 1, palette, pixels)); + EXPECT_NO_THROW(BitmapFile::WriteIndexed(filename, 1, 1, 1, 4, palette, pixels)); XFile::DeletePath(filename); } @@ -46,10 +46,10 @@ TEST(BitmapFile, IncorrectPixelPaddingThrows) const std::string filename("Sprite/data/IncorrectPixelPaddingTest.bmp"); std::vector pixels(3, 0); - EXPECT_THROW(BitmapFile::WriteIndexed(filename, 1, 1, 1, palette, pixels), std::runtime_error); + EXPECT_THROW(BitmapFile::WriteIndexed(filename, 1, 1, 1, 4, palette, pixels), std::runtime_error); pixels.resize(5, 0); - EXPECT_THROW(BitmapFile::WriteIndexed(filename, 1, 1, 1, palette, pixels), std::runtime_error); + EXPECT_THROW(BitmapFile::WriteIndexed(filename, 1, 1, 1, 4, palette, pixels), std::runtime_error); XFile::DeletePath(filename); } From a3a853cb337b3fa46316676c77ba9da47502885e Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sun, 10 Feb 2019 17:48:31 -0500 Subject: [PATCH 10/19] Update function name in unit test to match when calculating default pitch --- test/Bitmap/ImageHeader.test.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/Bitmap/ImageHeader.test.cpp b/test/Bitmap/ImageHeader.test.cpp index b1fdf75a..49c9718e 100644 --- a/test/Bitmap/ImageHeader.test.cpp +++ b/test/Bitmap/ImageHeader.test.cpp @@ -77,23 +77,23 @@ TEST(ImageHeader, VerifyValidBitCount) TEST(ImageHeader, CalculatePitch) { - EXPECT_EQ(4, ImageHeader::CalculatePitch(1, 1)); - EXPECT_EQ(4, ImageHeader::CalculatePitch(1, 32)); - EXPECT_EQ(8, ImageHeader::CalculatePitch(1, 33)); + EXPECT_EQ(4, ImageHeader::CalculateDefaultPitch(1, 1)); + EXPECT_EQ(4, ImageHeader::CalculateDefaultPitch(1, 32)); + EXPECT_EQ(8, ImageHeader::CalculateDefaultPitch(1, 33)); - EXPECT_EQ(4, ImageHeader::CalculatePitch(4, 1)); - EXPECT_EQ(4, ImageHeader::CalculatePitch(4, 8)); - EXPECT_EQ(8, ImageHeader::CalculatePitch(4, 9)); + EXPECT_EQ(4, ImageHeader::CalculateDefaultPitch(4, 1)); + EXPECT_EQ(4, ImageHeader::CalculateDefaultPitch(4, 8)); + EXPECT_EQ(8, ImageHeader::CalculateDefaultPitch(4, 9)); - EXPECT_EQ(4, ImageHeader::CalculatePitch(8, 1)); - EXPECT_EQ(4, ImageHeader::CalculatePitch(8, 4)); - EXPECT_EQ(8, ImageHeader::CalculatePitch(8, 5)); + EXPECT_EQ(4, ImageHeader::CalculateDefaultPitch(8, 1)); + EXPECT_EQ(4, ImageHeader::CalculateDefaultPitch(8, 4)); + EXPECT_EQ(8, ImageHeader::CalculateDefaultPitch(8, 5)); // Test non-static version of function ImageHeader imageHeader; imageHeader.bitCount = 1; imageHeader.width = 1; - EXPECT_EQ(4, imageHeader.CalculatePitch()); + EXPECT_EQ(4, imageHeader.CalculateDefaultPitch()); } TEST(ImageHeader, CalcByteWidth) From 967ce2d3d1a111614de11ebb7621025b44f59eba Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sun, 10 Feb 2019 17:51:12 -0500 Subject: [PATCH 11/19] Move FindPitch to a public Bmp header and add a non-static version of function --- src/Bitmap/BitmapFile.cpp | 20 ++++++++++++++++++++ src/Bitmap/BitmapFile.h | 6 ++++-- src/Bitmap/IndexedBmpWriter.cpp | 15 --------------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/Bitmap/BitmapFile.cpp b/src/Bitmap/BitmapFile.cpp index e52bc3ec..f12509e5 100644 --- a/src/Bitmap/BitmapFile.cpp +++ b/src/Bitmap/BitmapFile.cpp @@ -45,6 +45,26 @@ void BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(uint16_t bitCoun } } +std::size_t BitmapFile::FindPitch() const +{ + return FindPitch(imageHeader.width, imageHeader.height, pixels.size()); +} + +std::size_t BitmapFile::FindPitch(std::size_t width, std::size_t height, std::size_t pixelCount) +{ + if (pixelCount % height != 0) { + throw std::runtime_error("Unable to calculate a valid pitch based on height and pixel count"); + } + + const std::size_t pitch = pixelCount / height; + + if (pitch < width) { + throw std::runtime_error("Calculated pitch would be smaller than image pixel width"); + } + + return pitch; +} + void BitmapFile::VerifyIndexedImageForSerialization(uint16_t bitCount) { if (!ImageHeader::IsIndexedImage(bitCount)) { diff --git a/src/Bitmap/BitmapFile.h b/src/Bitmap/BitmapFile.h index 9c37a1b8..54845a77 100644 --- a/src/Bitmap/BitmapFile.h +++ b/src/Bitmap/BitmapFile.h @@ -20,7 +20,7 @@ class BitmapFile BmpHeader bmpHeader; ImageHeader imageHeader; std::vector palette; - std::vector pixels; + std::vector pixels; // Includes pitch // Uses a default 4 byte pitch static BitmapFile CreateDefaultIndexed(uint16_t bitCount, uint32_t width, uint32_t height); @@ -43,6 +43,9 @@ class BitmapFile // @pixelsWithPitchSize: Number of pixels including padding pixels to next 4 byte boundary. void VerifyPixelSizeMatchesImageDimensionsWithPitch() const; static void VerifyPixelSizeMatchesImageDimensionsWithPitch(uint16_t bitCount, std::size_t pitch, int32_t height, std::size_t pixelsWithPitchSize); + + std::size_t FindPitch() const; + static std::size_t FindPitch(std::size_t width, std::size_t height, std::size_t pixelCount); void Validate() const; @@ -56,7 +59,6 @@ class BitmapFile static void ReadPixels(Stream::BidirectionalSeekableReader& seekableReader, BitmapFile& bitmapFile); // Write - static std::size_t FindPitch(std::size_t width, std::size_t height, std::size_t pixelCount); static void WriteHeaders(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int width, int height, std::size_t pitch, const std::vector& palette); static void WritePixels(Stream::BidirectionalSeekableWriter& seekableWriter, const std::vector& pixels, int32_t width, uint16_t bitCount, std::size_t pitch); }; diff --git a/src/Bitmap/IndexedBmpWriter.cpp b/src/Bitmap/IndexedBmpWriter.cpp index e19a6db4..020b125b 100644 --- a/src/Bitmap/IndexedBmpWriter.cpp +++ b/src/Bitmap/IndexedBmpWriter.cpp @@ -36,21 +36,6 @@ void BitmapFile::WriteIndexed(Stream::BidirectionalSeekableWriter& seekableWrite WritePixels(seekableWriter, indexedPixels, width, bitCount, pitch); } -std::size_t BitmapFile::FindPitch(std::size_t width, std::size_t height, std::size_t pixelCount) -{ - if (pixelCount % height != 0) { - throw std::runtime_error("Unable to calculate a valid pitch based on height and pixel count"); - } - - const std::size_t pitch = pixelCount / height; - - if (pitch < width) { - throw std::runtime_error("Calculated pitch would be smaller than image pixel width"); - } - - return pitch; -} - void BitmapFile::WriteHeaders(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int width, int height, std::size_t pitch, const std::vector& palette) { std::size_t pixelOffset = sizeof(BmpHeader) + sizeof(ImageHeader) + palette.size() * sizeof(Color); From 413b1b6bf24b49593612ed10bc6c40653ff05a25 Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sun, 10 Feb 2019 17:53:42 -0500 Subject: [PATCH 12/19] Fix bug in VerifyPixelSizeMatchesImageDimensionsWithPitch and update unit tests --- src/Bitmap/BitmapFile.cpp | 2 +- src/Bitmap/BitmapFile.h | 7 +++---- test/Bitmap/BitmapFile.test.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Bitmap/BitmapFile.cpp b/src/Bitmap/BitmapFile.cpp index f12509e5..1bf64a3e 100644 --- a/src/Bitmap/BitmapFile.cpp +++ b/src/Bitmap/BitmapFile.cpp @@ -35,7 +35,7 @@ void BitmapFile::VerifyIndexedPaletteSizeDoesNotExceedBitCount(uint16_t bitCount void BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch() const { - BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(imageHeader.bitCount, imageHeader.width, imageHeader.height, pixels.size()); + VerifyPixelSizeMatchesImageDimensionsWithPitch(imageHeader.bitCount, FindPitch(), imageHeader.height, pixels.size()); } void BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(uint16_t bitCount, std::size_t pitch, int32_t height, std::size_t pixelsWithPitchSize) diff --git a/src/Bitmap/BitmapFile.h b/src/Bitmap/BitmapFile.h index 54845a77..b56d5986 100644 --- a/src/Bitmap/BitmapFile.h +++ b/src/Bitmap/BitmapFile.h @@ -38,10 +38,9 @@ class BitmapFile void VerifyIndexedPaletteSizeDoesNotExceedBitCount() const; static void VerifyIndexedPaletteSizeDoesNotExceedBitCount(uint16_t bitCount, std::size_t paletteSize); - // Check the pixel count is correct and already includes dummy pixels out to next 4 byte boundary. - // @width: Width in pixels. Do not include the pitch in width. - // @pixelsWithPitchSize: Number of pixels including padding pixels to next 4 byte boundary. - void VerifyPixelSizeMatchesImageDimensionsWithPitch() const; + // Check the pixel count is correct and already includes dummy pixels out to pitch boundary. + void BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch() const; + // @pixelsWithPitchSize: Number of pixels including padding pixels to next pitch boundary. static void VerifyPixelSizeMatchesImageDimensionsWithPitch(uint16_t bitCount, std::size_t pitch, int32_t height, std::size_t pixelsWithPitchSize); std::size_t FindPitch() const; diff --git a/test/Bitmap/BitmapFile.test.cpp b/test/Bitmap/BitmapFile.test.cpp index bbc2c7df..aa0ccb01 100644 --- a/test/Bitmap/BitmapFile.test.cpp +++ b/test/Bitmap/BitmapFile.test.cpp @@ -62,13 +62,13 @@ TEST(BitmapFile, VerifyIndexedPaletteSizeDoesNotExceedBitCount) TEST(BitmapFile, VerifyPixelSizeMatchesImageDimensionsWithPitch) { - EXPECT_NO_THROW(BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(1, 1, 1, 4)); - EXPECT_THROW(BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(1, 1, 1, 1), std::runtime_error); + EXPECT_NO_THROW(BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(1, 4, 1, 4)); + EXPECT_THROW(BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(1, 4, 1, 1), std::runtime_error); // Test non-static version of function - BitmapFile bitmapFile = BitmapFile::CreateDefaultIndexed(1, 1, 1);; + BitmapFile bitmapFile = BitmapFile::CreateDefaultIndexed(1, 1, 2);; EXPECT_NO_THROW(bitmapFile.VerifyPixelSizeMatchesImageDimensionsWithPitch()); - bitmapFile.pixels.resize(1, 0); + bitmapFile.pixels.resize(3, 0); // Cannot calculate a valid pitch EXPECT_THROW(bitmapFile.VerifyPixelSizeMatchesImageDimensionsWithPitch(), std::runtime_error); } From 70f4280dcf482530016d236e04ddc9ad200e16bf Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sun, 10 Feb 2019 17:59:36 -0500 Subject: [PATCH 13/19] Update comments to standardize wording to 4 bytes when mentioning default pitch interval --- src/Bitmap/BitmapFile.h | 2 +- src/Bitmap/ImageHeader.h | 2 +- src/Sprite/ImageMeta.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Bitmap/BitmapFile.h b/src/Bitmap/BitmapFile.h index b56d5986..fdc91861 100644 --- a/src/Bitmap/BitmapFile.h +++ b/src/Bitmap/BitmapFile.h @@ -30,7 +30,7 @@ class BitmapFile static BitmapFile ReadIndexed(Stream::BidirectionalSeekableReader& seekableReader); // BMP Writer only supports indexed color palettes (1, 2, and 8 bit BMPs). - // @indexedPixels: Must include padding to fill each image row out to the next byte memory border (pitch). 4 byte pitch is typical. + // @indexedPixels: Size must be padded to a multiple of pitch. (4 byte pitch is typical) static void WriteIndexed(std::string filename, uint16_t bitCount, int32_t width, int32_t height, std::size_t pitch, std::vector palette, const std::vector& indexedPixels); static void WriteIndexed(Stream::BidirectionalSeekableWriter& seekableWriter, uint16_t bitCount, int32_t width, int32_t height, std::size_t pitch, std::vector palette, const std::vector& indexedPixels); static void WriteIndexed(std::string filename, const BitmapFile& bitmapFile); diff --git a/src/Bitmap/ImageHeader.h b/src/Bitmap/ImageHeader.h index 91116eae..f63f34d7 100644 --- a/src/Bitmap/ImageHeader.h +++ b/src/Bitmap/ImageHeader.h @@ -42,7 +42,7 @@ struct ImageHeader void VerifyValidBitCount() const; static void VerifyValidBitCount(uint16_t bitCount); - // Default pitch interval is 32 + // Default pitch interval is 4 bytes std::size_t CalculateDefaultPitch() const; static std::size_t CalculateDefaultPitch(uint16_t bitCount, int32_t width); diff --git a/src/Sprite/ImageMeta.h b/src/Sprite/ImageMeta.h index cdb5765a..1ecd367c 100644 --- a/src/Sprite/ImageMeta.h +++ b/src/Sprite/ImageMeta.h @@ -23,7 +23,7 @@ struct ImageMeta { static_assert(2 == sizeof(ImageType), "ImageMeta::ImageType is an unexpected size"); - uint32_t scanLineByteWidth; //number of bytes in each scan line of image (this should be the width of the image rounded up to a 32 bit boundary) + uint32_t scanLineByteWidth; //number of bytes in each scan line of image (this should be the width of the image rounded up to a 4 bit boundary) uint32_t pixelDataOffset; // Offset of the pixel data in the .bmp file uint32_t height; // Height of image in pixels uint32_t width; // Width of image in pixels From 1869af6330611820fb3d39048979913e8688bf86 Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Sun, 10 Feb 2019 18:07:30 -0500 Subject: [PATCH 14/19] Add a default monochrome bitmap header --- src/Sprite/OP2BmpLoader.cpp | 5 +++-- src/Sprite/OP2BmpLoader.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Sprite/OP2BmpLoader.cpp b/src/Sprite/OP2BmpLoader.cpp index 26bc694b..e2a04dbe 100644 --- a/src/Sprite/OP2BmpLoader.cpp +++ b/src/Sprite/OP2BmpLoader.cpp @@ -5,6 +5,8 @@ #include #include +const std::vector DefaultMonochromePalette{ Color{0, 0, 0}, Color{255, 255, 255} }; + OP2BmpLoader::OP2BmpLoader(std::string bmpFilename, std::string artFilename) : bmpReader(bmpFilename), artFile(ArtFile::Read(artFilename)) { } @@ -47,8 +49,7 @@ std::vector OP2BmpLoader::CreatePalette(const ImageMeta& imageMeta) const std::vector palette; if (imageMeta.GetBitCount() == 1) { - palette.push_back(Color{ 0, 0, 0 }); - palette.push_back(Color{ 255, 255, 255 }); + return DefaultMonochromePalette; } else { palette.resize(artFile.palettes[imageMeta.paletteIndex].size()); diff --git a/src/Sprite/OP2BmpLoader.h b/src/Sprite/OP2BmpLoader.h index 76515d26..beaab2b1 100644 --- a/src/Sprite/OP2BmpLoader.h +++ b/src/Sprite/OP2BmpLoader.h @@ -25,6 +25,7 @@ class OP2BmpLoader // Actual palette data and range of pixels to form each image is contained in the .prt file. Stream::FileReader bmpReader; ArtFile artFile; + static const std::vector DefaultMonochromePalette; std::vector CreatePalette(const ImageMeta& imageMeta) const; std::unique_ptr GetPixels(std::size_t startingIndex, std::size_t length); From 96e2d113ab2a9ad2f005d043ec1721eb563f22fb Mon Sep 17 00:00:00 2001 From: Daniel Stevens Date: Mon, 11 Feb 2019 09:38:22 +0700 Subject: [PATCH 15/19] Update comments Interval implies a start value and end value. Granularity implies a minimum spacing for values. --- src/Bitmap/ImageHeader.h | 2 +- src/Sprite/ImageMeta.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bitmap/ImageHeader.h b/src/Bitmap/ImageHeader.h index f63f34d7..1371e91b 100644 --- a/src/Bitmap/ImageHeader.h +++ b/src/Bitmap/ImageHeader.h @@ -42,7 +42,7 @@ struct ImageHeader void VerifyValidBitCount() const; static void VerifyValidBitCount(uint16_t bitCount); - // Default pitch interval is 4 bytes + // Default pitch granularity is 4 bytes std::size_t CalculateDefaultPitch() const; static std::size_t CalculateDefaultPitch(uint16_t bitCount, int32_t width); diff --git a/src/Sprite/ImageMeta.h b/src/Sprite/ImageMeta.h index 1ecd367c..ca79b1f4 100644 --- a/src/Sprite/ImageMeta.h +++ b/src/Sprite/ImageMeta.h @@ -23,7 +23,7 @@ struct ImageMeta { static_assert(2 == sizeof(ImageType), "ImageMeta::ImageType is an unexpected size"); - uint32_t scanLineByteWidth; //number of bytes in each scan line of image (this should be the width of the image rounded up to a 4 bit boundary) + uint32_t scanLineByteWidth; //number of bytes in each scan line of image (this should be the width of the image rounded up to a 4 byte boundary) uint32_t pixelDataOffset; // Offset of the pixel data in the .bmp file uint32_t height; // Height of image in pixels uint32_t width; // Width of image in pixels From df91957df19d624f6bcb6ae62c15eacc0848e567 Mon Sep 17 00:00:00 2001 From: Daniel Stevens Date: Mon, 11 Feb 2019 09:44:34 +0700 Subject: [PATCH 16/19] Remove extra qualification on member function --- src/Bitmap/BitmapFile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bitmap/BitmapFile.h b/src/Bitmap/BitmapFile.h index fdc91861..e37ac1d9 100644 --- a/src/Bitmap/BitmapFile.h +++ b/src/Bitmap/BitmapFile.h @@ -39,7 +39,7 @@ class BitmapFile static void VerifyIndexedPaletteSizeDoesNotExceedBitCount(uint16_t bitCount, std::size_t paletteSize); // Check the pixel count is correct and already includes dummy pixels out to pitch boundary. - void BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch() const; + void VerifyPixelSizeMatchesImageDimensionsWithPitch() const; // @pixelsWithPitchSize: Number of pixels including padding pixels to next pitch boundary. static void VerifyPixelSizeMatchesImageDimensionsWithPitch(uint16_t bitCount, std::size_t pitch, int32_t height, std::size_t pixelsWithPitchSize); From c3323f634ede7bfb5fa3e4b5f98aabb5da41d924 Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Mon, 11 Feb 2019 22:29:21 -0500 Subject: [PATCH 17/19] Add missing class name to static property definition --- src/Sprite/OP2BmpLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sprite/OP2BmpLoader.cpp b/src/Sprite/OP2BmpLoader.cpp index e2a04dbe..37bac521 100644 --- a/src/Sprite/OP2BmpLoader.cpp +++ b/src/Sprite/OP2BmpLoader.cpp @@ -5,7 +5,7 @@ #include #include -const std::vector DefaultMonochromePalette{ Color{0, 0, 0}, Color{255, 255, 255} }; +const std::vector OP2BmpLoader::DefaultMonochromePalette{ Color{0, 0, 0}, Color{255, 255, 255} }; OP2BmpLoader::OP2BmpLoader(std::string bmpFilename, std::string artFilename) : bmpReader(bmpFilename), artFile(ArtFile::Read(artFilename)) { } From 893ff39c4b781973e070e9d56c2ebaf69708b790 Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Mon, 11 Feb 2019 22:31:11 -0500 Subject: [PATCH 18/19] change type name from Palette to Palette8Bit --- src/Bitmap/Color.h | 2 +- src/Sprite/ArtFile.h | 2 +- src/Sprite/PaletteHeader.cpp | 2 +- test/Sprite/ArtWriter.test.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Bitmap/Color.h b/src/Bitmap/Color.h index 41558bab..c4fa3552 100644 --- a/src/Bitmap/Color.h +++ b/src/Bitmap/Color.h @@ -19,7 +19,7 @@ static_assert(4 == sizeof(Color), "Color is an unexpected size"); bool operator==(const Color& lhs, const Color& rhs); bool operator!=(const Color& lhs, const Color& rhs); -using Palette = std::array; +using Palette8Bit = std::array; namespace DiscreteColor { diff --git a/src/Sprite/ArtFile.h b/src/Sprite/ArtFile.h index 1daa8f88..f563c954 100644 --- a/src/Sprite/ArtFile.h +++ b/src/Sprite/ArtFile.h @@ -17,7 +17,7 @@ namespace Stream { struct ArtFile { public: - std::vector palettes; + std::vector palettes; std::vector imageMetas; std::vector animations; uint32_t unknownAnimationCount; diff --git a/src/Sprite/PaletteHeader.cpp b/src/Sprite/PaletteHeader.cpp index 06919460..a35e65e4 100644 --- a/src/Sprite/PaletteHeader.cpp +++ b/src/Sprite/PaletteHeader.cpp @@ -10,7 +10,7 @@ PaletteHeader::PaletteHeader() : remainingTagCount(0) {} PaletteHeader::PaletteHeader(const ArtFile& artFile) : remainingTagCount(1) { - uint64_t dataSize = sizeof(Palette); + uint64_t dataSize = sizeof(Palette8Bit); uint64_t overallSize = 4 + sizeof(overallHeader) + sizeof(sectionHeader) + sizeof(remainingTagCount) + dataSize; diff --git a/test/Sprite/ArtWriter.test.cpp b/test/Sprite/ArtWriter.test.cpp index 0cfe83f9..8c316db9 100644 --- a/test/Sprite/ArtWriter.test.cpp +++ b/test/Sprite/ArtWriter.test.cpp @@ -27,7 +27,7 @@ TEST(ArtWriter, BlankFilename) class SimpleArtFile : public ::testing::Test { public: inline SimpleArtFile() { - artFile.palettes.push_back(Palette()); + artFile.palettes.push_back(Palette8Bit()); ImageMeta imageMeta; imageMeta.width = 10; From 04521ba3ecbd0a07025ae6a335f0ddd56e6847e5 Mon Sep 17 00:00:00 2001 From: Brett208 <15183337+Brett208@users.noreply.github.com> Date: Mon, 11 Feb 2019 22:32:02 -0500 Subject: [PATCH 19/19] Fix bug where Reader was using width instead of pitch --- src/Bitmap/IndexedBmpReader.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Bitmap/IndexedBmpReader.cpp b/src/Bitmap/IndexedBmpReader.cpp index 2c263cc2..4e68ff36 100644 --- a/src/Bitmap/IndexedBmpReader.cpp +++ b/src/Bitmap/IndexedBmpReader.cpp @@ -62,8 +62,9 @@ void BitmapFile::ReadPalette(Stream::BidirectionalSeekableReader& seekableReader void BitmapFile::ReadPixels(Stream::BidirectionalSeekableReader& seekableReader, BitmapFile& bitmapFile) { - std::size_t pixelContainerSize = bitmapFile.bmpHeader.size - bitmapFile.bmpHeader.pixelOffset; - BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(bitmapFile.imageHeader.bitCount, bitmapFile.imageHeader.width, bitmapFile.imageHeader.height, pixelContainerSize); + const std::size_t pixelContainerSize = bitmapFile.bmpHeader.size - bitmapFile.bmpHeader.pixelOffset; + const std::size_t pitch = FindPitch(bitmapFile.imageHeader.width, bitmapFile.imageHeader.height, pixelContainerSize); + BitmapFile::VerifyPixelSizeMatchesImageDimensionsWithPitch(bitmapFile.imageHeader.bitCount, pitch, bitmapFile.imageHeader.height, pixelContainerSize); bitmapFile.pixels.clear(); bitmapFile.pixels.resize(pixelContainerSize);