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

Fixed jpeg encoder last bytes flushing bug #1876

Merged
merged 1 commit into from
Dec 6, 2021

Conversation

br3aker
Copy link
Contributor

@br3aker br3aker commented Dec 5, 2021

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules 👮.
  • I have provided test coverage for my change (where applicable)

Description

I've made quite a mistake during jpeg encoder optimization for last bytes flushing to the stream:

int valuableBytesCount = (int)Numerics.DivideCeil((uint)this.bitCount, 8);
uint packedBytes = this.accumulatedBits | (uint.MaxValue >> this.bitCount);
this.emitBuffer[--this.emitWriteIndex] = packedBytes;

int endIndex = (this.emitWriteIndex * 4) - 4 + valuableBytesCount;
this.FlushToStream(endIndex);

uint buffer size is 4 for simplicity. Let's say we have 3 bits to pad with 1's for full byte and write to the stream:

bufferSize = 4
emitWriteIndex = 4
bitCount = 3
accumulatedBits = 101|0_0000_...

int valuableBytesCount = 1
uint packedBytes = 101|1_1111_...
--emitWriteIndex = 3
int endIndex = 3 * 4 - 4 + 1 = 12 - 4 + 1 = 9

// bytes indices written to the stream:
15 14 13 12 11 10 9

So extra 6 bytes written on top of 1 byte with actual information. Same setup with fix from this PR:

bufferSize = 4
emitWriteIndex = 4
bitCount = 3
accumulatedBits = 101|0_0000_...

int valuableBytesCount = 1
uint packedBytes = 101|1_1111_...
int endIndex = 4 * 4 - 1 = 16 - 1 = 15

// bytes indices written to the stream:
15

This bug wasn't critical and actually isn't spottable by photoshop or JpegSnoop as extra written bytes do not corrupt resulting jpeg but it's still a problem introduced in one of my PRs (I'm really sorry).

I've tested a couple of images from test folder and got following binary size difference:

Calliphora.jpg:
master: 257.540b
PR: 257.537b

winter420_noninterleaved.jpg: -
master: 248.048b
PR: 248.042b

@codecov
Copy link

codecov bot commented Dec 5, 2021

Codecov Report

Merging #1876 (e9b6b8a) into master (952af37) will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff           @@
##           master   #1876   +/-   ##
======================================
  Coverage      87%     87%           
======================================
  Files         935     935           
  Lines       48939   48939           
  Branches     6086    6086           
======================================
  Hits        42814   42814           
  Misses       5115    5115           
  Partials     1010    1010           
Flag Coverage Δ
unittests 87% <100%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
...mats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs 96% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 952af37...e9b6b8a. Read the comment docs.

Copy link
Member

@JimBobSquarePants JimBobSquarePants left a comment

Choose a reason for hiding this comment

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

No need to apologize!! Nobody here caught it.

@JimBobSquarePants JimBobSquarePants merged commit 4ee7830 into SixLabors:master Dec 6, 2021
@br3aker br3aker deleted the dp/jpeg-encoder-ff-fix branch December 6, 2021 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants