The default row-order for DIBs is bottom-up, indicated by a postive biHeight in the BITMAPINFOHEADER structure. A negative biHeight indicates top-down row order. See MSDN.
Unfortunately, TDib does not handle a negative biHeight. In particular, if given a filename of a top-down bitmap, the TDib constructor will fail and throw an exception. See [discussion:3b9d1452].
Bugs: #650
Discussion: 3b9d1452
Discussion: OWL-Support for opening bmp's with negative height
Wiki: OWLNext_Stable_Releases
@jogybl wrote:
If there isn't a ready available application to create a top-down DIB, I would think a simple testing strategy would be to:
Presumably, you can also create a test file by patching a normal bottom-up BMP file in a hex editor. Changing the sign of BITMAPINFOHEADER::biHeight should be enough, it seems.
Good idea, I will try this.
I wrote very simple code to recursively traverse my drives (using std::filesystem::recursive_directory_iterator) and look for .bmp file with negative height and found a whole bunch in AppData\LocalLow\Adobe\Acrobat\DC\ConnectorIcons\
I will use them to fix and test the code.
P.S. Helpful hint:
std::filesystem::directory_options::skip_permission_deniedis mandatory option when usingrecursive_directory_iteratoron C: drive@jogybl wrote:
Clever!
I had one of these thumbnail bitmaps in the same location. On resaving in Paint, it turned into ordinary bottom-up format. Looking at the files in a hex editor it seems the sign of the height is the only change in the BITMAPINFOHEADERs.
@jogybl committed:
Fix looks good, although constructor TDib(int width, int height, ...) still doesn't support top-down DIBs (negative height). The image size is incorrectly calculated if a negative height is given. Either use std::abs here as well, or harden the PRECONDITION to
height > 0and document the limitation. (By the way, the PRECONDITION should saywidth > 0.)Related
Commit: [r8893]
Commit: [r8894]
Commit: [r8896]
@jogybl committed:
That should do it, I think.
PS. I spotted a little nit: std::abs is now used in "gdiobjec.h", without an include-directive for "<cstdlib>" or "<cmath>". However, the latter is indirectly included via "geometry.h" (where incidentally it is not used). Ideally, move the "<cmath>" include-directive to "gdiobject.h", and make sure other headers depending on it also includes it, if any. Make sure to test the build without PCH.
Related
Commit: [r8898]
Commit: [r8899]
Commit: [r8900]
There are usages of std::lround at the end of geometry.h
@jogybl wrote:
Ah, indeed there are. My bad; I trusted Visual Studio IntelliSense, which greys the include directive and shows message
#include <cmath> is not used in this file. I guess this false positive is produced because std::lround is only used within templates, and the IntelliSense parser doesn't do proper two-phase lookup within templates (old MSVC issue).I did a simple test of the new top-down support in TDib(int width, int height, uint32 nColors, ...), and while it seems to work fine, I ran into an issue with the "nColors" parameter: What are we supposed to pass to create 16/24/32-bit bitmaps?
Note that NColors returns 0 for 16/24/32-bit bitmaps. But the TDib constructor does not allow 0 to be passed. The workaround is ugly:
Edit: I've now created a separate ticket for a related issue, that may cause this constructor to crash [bugs:#652]. The fix is easy, and should be applicable to the release branches.
Related
Bugs: #652
Last edit: Vidar Hasfjord 3 days ago