brandonmpetty / Doxa

A Local Adaptive Thresholding framework for image binarization written in C++, with JS and Python bindings. Implementing: Otsu, Bernsen, Niblack, Sauvola, Wolf, Gatos, NICK, Su, T.R. Singh, WAN, ISauvola, Bataineh, Chan and Shafait.
https://brandonmpetty.github.io/Doxa/WebAssembly
Creative Commons Zero v1.0 Universal
167 stars 37 forks source link

Malformed output with “zebra stripes” due to a bug in `PNM.hpp` #36

Closed ghost closed 10 months ago

ghost commented 11 months ago

Hello,

I'm testing Doxa for converting color or grayscale book scans to bilevel images. I would say that 95% of time, it works, but 5% of time, Doxa produces malformed output with “zebra stripes” for lack of a better term. Here is how this output looks:

output pbm

The code I’m using is very basic:

        Doxa::Image doxaGsImage = Doxa::PNM::Read(input);
        Doxa::ISauvola::UpdateToBinary(doxaGsImage);
        Doxa::PNM::Write(doxaGsImage, output);

Thank you in advance for looking into this issue.

Please find attached, as ZIP file, a sample showing the problem. The ZIP file contains:

Sample.zip

ghost commented 11 months ago

OK, I figured it out myself, although it took me time. The issue is caused by a bug in Doxa::PNM::WriteP4, your function that outputs the image as PBM. Line:

const int paddedWidth = image.width + 8 - (image.width % 8);

assumes that all widths have to be padded to a full byte. But in my case, the width is 1320, which is already divisible by 8, so it doesn't need any padding. This scenario has been overlooked, it seems. The correct line is:

const int paddedWidth = image.width % 8 == 0 ? image.width : image.width + 8 - (image.width % 8);

P.S. You might also want to check Doxa::PNM::Read1BitBinary for the same bug.

brandonmpetty commented 11 months ago

Thank you! I will try to get this fixed as soon as possible.

brandonmpetty commented 10 months ago

Your solution has been implemented, with unit test coverage. Thanks again!