mirror of https://github.com/adamdruppe/arsd.git
hack to help a user load a corrupted file
This commit is contained in:
parent
afbb2f144c
commit
d7d904ba85
32
bmp.d
32
bmp.d
|
@ -48,8 +48,22 @@ MemoryImage readBmp(in ubyte[] data, bool lookForFileHeader = true) {
|
||||||
History:
|
History:
|
||||||
The `lookForFileHeader` param was added in July 2020.
|
The `lookForFileHeader` param was added in July 2020.
|
||||||
+/
|
+/
|
||||||
MemoryImage readBmpIndirect(scope void delegate(void*, size_t) fread, bool lookForFileHeader = true) {
|
MemoryImage readBmpIndirect(scope void delegate(void*, size_t) fread, bool lookForFileHeader = true, bool hackAround64BitLongs = false) {
|
||||||
uint read4() { uint what; fread(&what, 4); return what; }
|
uint read4() { uint what; fread(&what, 4); return what; }
|
||||||
|
uint readLONG() {
|
||||||
|
auto le = read4();
|
||||||
|
/++
|
||||||
|
A user on discord encountered a file in the wild that wouldn't load
|
||||||
|
by any other bmp viewer. After looking at the raw bytes, it appeared it
|
||||||
|
wrote out the LONG fields on the bitmap info header as 64 bit values when
|
||||||
|
they are supposed to always be 32 bit values. This hack gives a chance to work
|
||||||
|
around that and load the file anyway.
|
||||||
|
+/
|
||||||
|
if(hackAround64BitLongs)
|
||||||
|
if(read4() != 0)
|
||||||
|
throw new Exception("hackAround64BitLongs is true, but the file doesn't appear to use 64 bit longs");
|
||||||
|
return le;
|
||||||
|
}
|
||||||
ushort read2(){ ushort what; fread(&what, 2); return what; }
|
ushort read2(){ ushort what; fread(&what, 2); return what; }
|
||||||
ubyte read1(){ ubyte what; fread(&what, 1); return what; }
|
ubyte read1(){ ubyte what; fread(&what, 1); return what; }
|
||||||
|
|
||||||
|
@ -58,8 +72,11 @@ MemoryImage readBmpIndirect(scope void delegate(void*, size_t) fread, bool lookF
|
||||||
throw new Exception("didn't get expected byte value", __FILE__, line);
|
throw new Exception("didn't get expected byte value", __FILE__, line);
|
||||||
}
|
}
|
||||||
void require2(ushort t) {
|
void require2(ushort t) {
|
||||||
if(read2() != t)
|
auto got = read2();
|
||||||
|
if(got != t) {
|
||||||
|
version(arsd_debug_bitmap_loader) { import core.stdc.stdio; printf("expected: %d, got %d\n", cast(int) t, cast(int) got); }
|
||||||
throw new Exception("didn't get expected short value");
|
throw new Exception("didn't get expected short value");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void require4(uint t, size_t line = __LINE__) {
|
void require4(uint t, size_t line = __LINE__) {
|
||||||
auto got = read4();
|
auto got = read4();
|
||||||
|
@ -83,6 +100,8 @@ MemoryImage readBmpIndirect(scope void delegate(void*, size_t) fread, bool lookF
|
||||||
auto sizeOfBitmapInfoHeader = read4();
|
auto sizeOfBitmapInfoHeader = read4();
|
||||||
if (sizeOfBitmapInfoHeader < 12) throw new Exception("invalid bitmap header size");
|
if (sizeOfBitmapInfoHeader < 12) throw new Exception("invalid bitmap header size");
|
||||||
|
|
||||||
|
version(arsd_debug_bitmap_loader) { import core.stdc.stdio; printf("size of bitmap info header: %d\n", cast(uint)sizeOfBitmapInfoHeader); }
|
||||||
|
|
||||||
int width, height, rdheight;
|
int width, height, rdheight;
|
||||||
|
|
||||||
if (sizeOfBitmapInfoHeader == 12) {
|
if (sizeOfBitmapInfoHeader == 12) {
|
||||||
|
@ -91,13 +110,14 @@ MemoryImage readBmpIndirect(scope void delegate(void*, size_t) fread, bool lookF
|
||||||
} else {
|
} else {
|
||||||
if (sizeOfBitmapInfoHeader < 16) throw new Exception("invalid bitmap header size");
|
if (sizeOfBitmapInfoHeader < 16) throw new Exception("invalid bitmap header size");
|
||||||
sizeOfBitmapInfoHeader -= 4; // hack!
|
sizeOfBitmapInfoHeader -= 4; // hack!
|
||||||
width = read4();
|
width = readLONG();
|
||||||
rdheight = cast(int)read4();
|
rdheight = cast(int)readLONG();
|
||||||
}
|
}
|
||||||
|
|
||||||
height = (rdheight < 0 ? -rdheight : rdheight);
|
height = (rdheight < 0 ? -rdheight : rdheight);
|
||||||
rdheight = (rdheight < 0 ? 1 : -1); // so we can use it as delta (note the inverted sign)
|
rdheight = (rdheight < 0 ? 1 : -1); // so we can use it as delta (note the inverted sign)
|
||||||
|
|
||||||
|
version(arsd_debug_bitmap_loader) { import core.stdc.stdio; printf("size: %dx%d\n", cast(int)width, cast(int) height); }
|
||||||
if (width < 1 || height < 1) throw new Exception("invalid bitmap dimensions");
|
if (width < 1 || height < 1) throw new Exception("invalid bitmap dimensions");
|
||||||
|
|
||||||
require2(1); // planes
|
require2(1); // planes
|
||||||
|
@ -127,8 +147,8 @@ MemoryImage readBmpIndirect(scope void delegate(void*, size_t) fread, bool lookF
|
||||||
sizeOfBitmapInfoHeader -= 6*4;
|
sizeOfBitmapInfoHeader -= 6*4;
|
||||||
compression = read4();
|
compression = read4();
|
||||||
sizeOfUncompressedData = read4();
|
sizeOfUncompressedData = read4();
|
||||||
xPixelsPerMeter = read4();
|
xPixelsPerMeter = readLONG();
|
||||||
yPixelsPerMeter = read4();
|
yPixelsPerMeter = readLONG();
|
||||||
colorsUsed = read4();
|
colorsUsed = read4();
|
||||||
colorsImportant = read4();
|
colorsImportant = read4();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue