-
Notifications
You must be signed in to change notification settings - Fork 7.8k
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
Add write support for 16-bit PNG #763
base: master
Are you sure you want to change the base?
Conversation
Because this implementation supports both 8- and 16-bit channels by treating them as 1 or 2 bytes and using a multiply by the component count, it will slow down the common case of 1-byte channels unacceptably. It needs to use a separate path for the pixel loops. |
7ffb71e
to
07f714a
Compare
07f714a
to
d882013
Compare
Thanks for review, Sean. |
ok, yeah, that works too. i didn't realize it was a loop-constant that compiler MIGHT have fixed, but still worth changing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On reviewing this while trying to merge, I'm confused about some of the loops.
case 2: for (i=pixel_bytes; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break; | ||
case 3: for (i=pixel_bytes; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-pixel_bytes] + z[i-signed_stride])>>1); break; | ||
case 4: for (i=pixel_bytes; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-pixel_bytes], z[i-signed_stride], z[i-signed_stride-pixel_bytes]); break; | ||
case 5: for (i=pixel_bytes; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-pixel_bytes>>1]); break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a bug here, the code went from z[...]>>1 to z[...>>1 right before 'break']. I'm trying to fix this by changing the code back to using 'n' so that less code will be changed. I.e. change passed in parameter n to "channel_count", then say 'int n = pixel_bytes', and then most of the code is unchanged.
While doing that, though, I realized that the current code still loops i up to width * n, not width * pixel_bytes. That can't possibly be right, can it? But if it's wrong, then half of the image would have failed to encode, which I think you would have noticed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@WearerOfShoes , were you able to take a look at this comment by Sean? I'm very interested in being able to save into any type deeper than 8 bits...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@WearerOfShoes, I'm very interested in this, too...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nothings: So it took me a while to figure out, but apart from the right-shift bug you pointed out, the code is actually correct with regards to width * n
vs width * pixel_bytes
in the for-loops because width
has already been multiplied by comp_bytes
(i.e. 1 for 8-bit PNGs, 2 for 16-bit PNGs) in stbiw__write_png_to_mem_core()
:
// all calculations in PNG are based on bytes in 16-bit mode,
// so just treated it as a twice-as-wide 8-bit image works in most cases
// exceptions are patches up by sending along comp_bytes
x *= comp_bytes;
I also ran the tests in image_write_test and all generated PNGs are seemingly correct.
(BTW, I can make a new PR based on a fork of @WearerOfShoes work so we can finish this if you like)
This patch adds write support for 16-bit PNG.
I tried to mimic the way it is done on the read side, by having a special _16 function. I didn't modify the interface of any previously exposed functions.
Most of the functionality is shared with the 8-bit PNG writer, and I expect it to get a comparable performance and compression ratio. But I admit I haven't measured it.