Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow custom pitch when writing bitmaps #256

Open
wants to merge 21 commits into
base: master
Choose a base branch
from

Conversation

Brett208
Copy link
Member

This is a pretty extensive rollup of changes. I've been playing with extracting images from op2_art. These changes were a result of that work.

Doesn't need to be reviewed quickly.

-Brett

This allows instantiating OP2BmpLoader without extracting op2_art.prt from the art.vol (volume)
Still need to look closely at 1 bit images to ensure they are forming fully correctly. Earlier it would just throw an error.
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.
@Brett208 Brett208 requested a review from DanRStevens February 10, 2019 04:06
@Brett208
Copy link
Member Author

Forgot to commit unit tests and out of time for now. Will try and fix tomorrow.

-Brett

src/Sprite/OP2BmpLoader.cpp Show resolved Hide resolved
src/Bitmap/BitmapFile.h Outdated Show resolved Hide resolved
src/Bitmap/ImageHeader.h Outdated Show resolved Hide resolved
Copy link
Member Author

@Brett208 Brett208 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing the highlight algorithm issue should get everything building again. I'll add an issue for the using Palette8Bit so we can clean that up later.

throw std::runtime_error("Unable to calculate a valid pitch based on height and pixel count");
}

const std::size_t pitch = pixelCount / height;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hack of mine is causing the unit tests to fail. They happen to be fairly robust for this small section of the code compared to others.

The next step is probably to figure out a proper bit twiddle or calculation that determines pitch without assuming it is a 4 byte interval. @DanRStevens, feel free to chime in if you have something up your sleeve.

-Brett

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pitch is either assumed, or given. It's not generally calculated (other than in an assumption, such as rounding the scanline byte width up to a multiple of 4 bytes). The problem with trying to calculate it, is the data source could always have chosen a larger pitch than is necessary.

I find it a little non-intuitive to use pixelCount here. When I think pixel could, I generally assume it's simply width * height, which is not particularly useful for calculating pitch if you already have the width. Plus, pitch is a byte measurement, not a pixel measurement. The bitDepth needs to be accounted for.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are wanting to work on this branch feel free. I'm not going to pick it up again for a long time.

-Brett

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I quite have the context to pick this one up right now.

@@ -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 granularity is 4 bytes
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had intentionally left this as interval. Perhaps it is a regional language different but interval seems a better and easier to understand choice than granularity to me. Being a comment, it probably isn't worth arguing over now that it has been changed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A disagreement in terminology might signal a disagreement about what is intended here.

I would define an interval as having a start and end point. Granularity is about the minimum spacing of values.

Here the pitch is rounded to some multiple of a certain value. That is defining the granularity of the value. As in, values are a multiple of 4 bytes. Is does not define the length of an interval as 4 bytes. For example, the spacing between scanlines could easily be 12 bytes, even though the granularity of that value is 4 bytes.

More deeply, I'm not sure I would really consider pitch to be an interval. It's more of a spacing between scanlines. If pitch were an interval, I'd be uncertain how to define the start and end points.

Looking back at std::size_t CalculateDefaultPitch() const;, I'm actually a little uncertain what the comment is trying to tell me, or why it is important. Is it trying to tell me the value is a multiple of 4 bytes? From the example test code, that would seem to be the case.

I vaguely recall some requirement that pitch is a minimum of 4 bytes, though can be a larger multiple of it.

I might also consider the phrasing:
Default pitch is the scanline byte width rounded up to a multiple of 4 bytes

@@ -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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might be more of a maximum upper bound, rather than an exact size. There may be other sections stored in the bitmap file, after the pixel data, before the end of the file.

@Brett208
Copy link
Member Author

I am attempting to pull some of the better ideas out of this branch and commit them as smaller, separate branches and then close this pull request.

I think the custom pitch thrust itself went poorly, but there was some supporting code that I didn't want to toss when terminating the branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants