mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-27 23:37:04 -05:00
patterns: Added TIFF pattern (#126)
* Create tiff.hexpat * Update README.md Update readme to include tiff hexpat * added file to test the pattern --------- Co-authored-by: joelalves <joel.17.alves@gmail.com>
This commit is contained in:
@@ -82,6 +82,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
| STL | `model/stl` | [`patterns/stl.hexpat`](patterns/stl.hexpat) | STL 3D Model format |
|
||||
| StuffItV5 | `application/x-stuffit` | [`patterns/sit5.hexpat`](patterns/sit5.hexpat) | StuffIt V5 archive |
|
||||
| TAR | `application/x-tar` | [`patterns/tar.hexpat`](patterns/tar.hexpat) | Tar file format |
|
||||
| TIFF | `image/tiff` | [`patterns/tiff.hexpat`](patterns/tiff.hexpat) | Tag Image File Format |
|
||||
| TGA | `image/tga` | [`patterns/tga.hexpat`](patterns/tga.hexpat) | Truevision TGA/TARGA image |
|
||||
| UEFI | | [`patterns/uefi.hexpat`](patterns/uefi.hexpat)` | UEFI structs for parsing efivars |
|
||||
| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) |
|
||||
|
||||
318
patterns/tiff.hexpat
Normal file
318
patterns/tiff.hexpat
Normal file
@@ -0,0 +1,318 @@
|
||||
#pragma MIME image/tiff
|
||||
|
||||
#pragma eval_depth 100
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/string.pat>
|
||||
#include <std/core.pat>
|
||||
|
||||
#define BIG 1
|
||||
#define LITTLE 2
|
||||
|
||||
|
||||
u32 stripCount = 0;
|
||||
s32 current_strip = 0;
|
||||
|
||||
fn get_next_strip_index(){
|
||||
if (current_strip <= stripCount) {
|
||||
current_strip = current_strip + 1;
|
||||
return current_strip - 1;
|
||||
} else {
|
||||
return stripCount+1;
|
||||
}
|
||||
};
|
||||
|
||||
fn reset_counter_strip(){
|
||||
current_strip = 0;
|
||||
stripCount = 0;
|
||||
};
|
||||
|
||||
fn start_counter_strip(u32 total){
|
||||
current_strip = 0;
|
||||
stripCount = total;
|
||||
};
|
||||
|
||||
fn set_endian(str magic) {
|
||||
if (std::string::starts_with(magic, "II")) {
|
||||
std::core::set_endian(std::mem::Endian::Little);
|
||||
} else if (std::string::starts_with(magic, "MM")) {
|
||||
std::core::set_endian(std::mem::Endian::Big);
|
||||
}
|
||||
};
|
||||
|
||||
fn get_total_IFDs(u32 first_offset){
|
||||
u32 ifd_count = 0;
|
||||
u32 current_offset = first_offset;
|
||||
while (current_offset != 0) {
|
||||
u16 ifd_entries_count = std::mem::read_unsigned(current_offset, 2, std::core::get_endian());
|
||||
current_offset = std::mem::read_unsigned(current_offset + 2 + ifd_entries_count * 12, 4, std::core::get_endian());
|
||||
ifd_count = ifd_count + 1;
|
||||
}
|
||||
return ifd_count;
|
||||
};
|
||||
|
||||
fn get_ifds_offsets(u32 first_offset) {
|
||||
u32 total_ifds = get_total_IFDs(first_offset);
|
||||
u32 index = 0;
|
||||
u32 current_offset = first_offset;
|
||||
u32 ifd_offsets[total_ifds];
|
||||
while (current_offset != 0) {
|
||||
ifd_offsets[index] = current_offset;
|
||||
u16 ifd_entries_count = std::mem::read_unsigned(current_offset, 2, std::core::get_endian());
|
||||
current_offset = std::mem::read_unsigned(current_offset + 2 + ifd_entries_count * 12, 4, std::core::get_endian());
|
||||
index = index + 1;
|
||||
}
|
||||
return ifd_offsets;
|
||||
};
|
||||
using TIFFFieldType;
|
||||
using TIFFTag;
|
||||
fn get_entry_value(u32 offset, TIFFTag Tag){
|
||||
u16 count = std::mem::read_unsigned(offset, 2, std::core::get_endian());
|
||||
u8 step = 12;
|
||||
offset = offset + 2;
|
||||
while (count != 0) {
|
||||
if (std::mem::read_unsigned(offset, 2, std::core::get_endian()) == Tag) {
|
||||
if (std::mem::read_unsigned(offset + 2, 2, std::core::get_endian()) == TIFFFieldType::SHORT) {
|
||||
return std::mem::read_unsigned(offset + 8, 2, std::core::get_endian());
|
||||
} else if (std::mem::read_unsigned(offset + 2, 2, std::core::get_endian()) == TIFFFieldType::LONG) {
|
||||
return std::mem::read_unsigned(offset + 8, 4, std::core::get_endian());
|
||||
}
|
||||
}
|
||||
count = count - 1;
|
||||
offset = offset + step;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct TIFFHeader {
|
||||
char Magic[2];
|
||||
set_endian(Magic);
|
||||
u16 Version;
|
||||
u32 Offset;
|
||||
};
|
||||
|
||||
enum TIFFFieldType : u16 {
|
||||
BYTE = 1,
|
||||
ASCII = 2,
|
||||
SHORT = 3,
|
||||
LONG = 4,
|
||||
RATIONAL = 5,
|
||||
SBYTE = 6,
|
||||
UNDEFINED = 7,
|
||||
SSHORT = 8,
|
||||
SLONG = 9,
|
||||
SRATIONAL = 10,
|
||||
FLOAT = 11,
|
||||
DOUBLE = 12
|
||||
};
|
||||
|
||||
enum TIFFTag : u16 {
|
||||
NewSubfileType = 0x00FE,
|
||||
SubfileType = 0x00FF,
|
||||
ImageWidth = 0x0100,
|
||||
ImageLength = 0x0101,
|
||||
BitsPerSample = 0x0102,
|
||||
Compression = 0x0103,
|
||||
PhotometricInterpretation = 0x0106,
|
||||
Threshholding = 0x0107,
|
||||
CellWidth = 0x0108,
|
||||
CellLength = 0x0109,
|
||||
FillOrder = 0x010A,
|
||||
DocumentName = 0x010D,
|
||||
ImageDescription = 0x010E,
|
||||
Make = 0x010F,
|
||||
Model = 0x0110,
|
||||
StripOffsets = 0x0111,
|
||||
Orientation = 0x0112,
|
||||
SamplesPerPixel = 0x0115,
|
||||
RowsPerStrip = 0x0116,
|
||||
StripByteCounts = 0x0117,
|
||||
MinSampleValue = 0x0118,
|
||||
MaxSampleValue = 0x0119,
|
||||
XResolution = 0x011A,
|
||||
YResolution = 0x011B,
|
||||
PlanarConfiguration = 0x011C,
|
||||
PageName = 0x011D,
|
||||
XPosition = 0x011E,
|
||||
YPosition = 0x011F,
|
||||
FreeOffsets = 0x0120,
|
||||
FreeByteCounts = 0x0121,
|
||||
GrayResponseUnit = 0x0122,
|
||||
GrayResponseCurve = 0x0123,
|
||||
T4Options = 0x0124,
|
||||
T6Options = 0x0125,
|
||||
ResolutionUnit = 0x0128,
|
||||
PageNumber = 0x0129,
|
||||
TransferFunction = 0x012D,
|
||||
Software = 0x0131,
|
||||
DateTime = 0x0132,
|
||||
Artist = 0x013B,
|
||||
HostComputer = 0x013C,
|
||||
Predictor = 0x013D,
|
||||
WhitePoint = 0x013E,
|
||||
PrimaryChromaticities = 0x013F,
|
||||
ColorMap = 0x0140,
|
||||
HalftoneHints = 0x0141,
|
||||
TileWidth = 0x0142,
|
||||
TileLength = 0x0143,
|
||||
TileOffsets = 0x0144,
|
||||
TileByteCounts = 0x0145,
|
||||
InkSet = 0x014C,
|
||||
InkNames = 0x014D,
|
||||
NumberOfInks = 0x014E,
|
||||
DotRange = 0x0150,
|
||||
TargetPrinter = 0x0151,
|
||||
ExtraSamples = 0x0152,
|
||||
SampleFormat = 0x0153,
|
||||
SMinSampleValue = 0x0154,
|
||||
SMaxSampleValue = 0x0155,
|
||||
TransferRange = 0x0156,
|
||||
JPEGProc = 0x0200,
|
||||
JPEGInterchangeFormat = 0x0201,
|
||||
JPEGInterchangeFormatLngth = 0x0202,
|
||||
JPEGRestartInterval = 0x0203,
|
||||
JPEGLosslessPredictors = 0x0205,
|
||||
JPEGPointTransforms = 0x0206,
|
||||
JPEGQTables = 0x0207,
|
||||
JPEGDCTables = 0x0208,
|
||||
JPEGACTables = 0x0209,
|
||||
YCbCrCoefficients = 0x0211,
|
||||
YCbCrSubSampling = 0x0212,
|
||||
YCbCrPositioning = 0x0213,
|
||||
ReferenceBlackWhite = 0x0214,
|
||||
Copyright = 0x8298,
|
||||
InterColorProfile = 0x8773
|
||||
};
|
||||
|
||||
|
||||
struct IFDEntry {
|
||||
TIFFTag Tag;
|
||||
TIFFFieldType Type;
|
||||
u32 Count;
|
||||
|
||||
match (Type) {
|
||||
(TIFFFieldType::BYTE): {
|
||||
if (std::core::get_endian() == BIG){
|
||||
u8 Value;
|
||||
padding[3];
|
||||
} else {
|
||||
u32 Value;
|
||||
}
|
||||
}
|
||||
(TIFFFieldType::ASCII): {
|
||||
u32 value_offset[[hidden]];
|
||||
char Value[Count] @ value_offset;
|
||||
}
|
||||
(TIFFFieldType::SHORT): {
|
||||
if (std::core::get_endian() == BIG){
|
||||
u16 Value;
|
||||
padding[2];
|
||||
} else {
|
||||
u32 Value;
|
||||
}
|
||||
}
|
||||
(TIFFFieldType::LONG): u32 Value;
|
||||
(TIFFFieldType::RATIONAL): {
|
||||
u32 value_offset[[hidden]];
|
||||
u32 Numerator @ value_offset;
|
||||
u32 Denominator @ value_offset + 4;
|
||||
}
|
||||
(TIFFFieldType::SBYTE): {
|
||||
if (std::core::get_endian() == BIG){
|
||||
s8 Value;
|
||||
padding[3];
|
||||
} else {
|
||||
s32 Value;
|
||||
}
|
||||
}
|
||||
(TIFFFieldType::UNDEFINED): {
|
||||
u32 value_offset[[hidden]];
|
||||
u8 Value[Count] @ value_offset;
|
||||
}
|
||||
(TIFFFieldType::SSHORT): {
|
||||
if (std::core::get_endian() == BIG){
|
||||
s16 Value;
|
||||
padding[2];
|
||||
} else {
|
||||
s32 Value;
|
||||
}
|
||||
}
|
||||
(TIFFFieldType::SLONG): s32 Value;
|
||||
(TIFFFieldType::SRATIONAL): {
|
||||
u32 value_offset[[hidden]];
|
||||
s32 Numerator @ value_offset;
|
||||
s32 Denominator @ value_offset + 4;
|
||||
}
|
||||
(TIFFFieldType::FLOAT): float Value;
|
||||
(TIFFFieldType::DOUBLE): {
|
||||
u32 value_offset[[hidden]];
|
||||
double Value @ value_offset;
|
||||
}
|
||||
(_): {
|
||||
padding[4];
|
||||
std::print("TIFFFieldType not supported");
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct StripList {
|
||||
u16 entry_count [[hidden]];
|
||||
u32 ImageLength = get_entry_value(addressof(this), TIFFTag::ImageLength);
|
||||
u32 RowsPerStrip = get_entry_value(addressof(this), TIFFTag::RowsPerStrip);
|
||||
u32 StripByteCounts = get_entry_value(addressof(this), TIFFTag::StripByteCounts);
|
||||
u32 StripOffsets = get_entry_value(addressof(this), TIFFTag::StripOffsets);
|
||||
|
||||
s32 next_strip_index = get_next_strip_index();
|
||||
if ((ImageLength/RowsPerStrip) > 1) {
|
||||
u32 StripOffsetsArray[ImageLength/RowsPerStrip] @ StripOffsets [[hidden]];
|
||||
u32 StripByteCountsArray[ImageLength/RowsPerStrip] @ StripByteCounts [[hidden]];
|
||||
u8 Strip[StripByteCountsArray[next_strip_index]] @ StripOffsetsArray[next_strip_index];
|
||||
} else {
|
||||
u8 Strip[StripByteCounts] @ StripOffsets;
|
||||
}
|
||||
|
||||
if (current_strip < stripCount) {
|
||||
StripList strips @ addressof(this);
|
||||
} else {
|
||||
reset_counter_strip();
|
||||
break;
|
||||
}
|
||||
|
||||
}[[inline]];
|
||||
|
||||
|
||||
struct IFD {
|
||||
u16 NumberDirectoryEntries;
|
||||
IFDEntry DirectoryEntry[NumberDirectoryEntries];
|
||||
u32 NextIFD;
|
||||
u32 ImageLength = get_entry_value(addressof(this), TIFFTag::ImageLength);
|
||||
u32 RowsPerStrip = get_entry_value(addressof(this), TIFFTag::RowsPerStrip);
|
||||
u32 StripByteCounts = get_entry_value(addressof(this), TIFFTag::StripByteCounts);
|
||||
u32 StripOffsets = get_entry_value(addressof(this), TIFFTag::StripOffsets);
|
||||
u32 StripOffsetsArray[ImageLength/RowsPerStrip] @ StripOffsets;
|
||||
u32 StripByteCountsArray[ImageLength/RowsPerStrip] @ StripByteCounts;
|
||||
start_counter_strip(ImageLength/RowsPerStrip);
|
||||
StripList ImageData[] @ addressof(this);
|
||||
};
|
||||
|
||||
struct IFDS {
|
||||
IFD IFD;
|
||||
if (IFD.NextIFD > 0) {
|
||||
IFDS IFD_tmp @ IFD.NextIFD;
|
||||
}else {
|
||||
break;
|
||||
}
|
||||
}[[inline]];
|
||||
|
||||
struct TIFFFile {
|
||||
TIFFHeader Header;
|
||||
set_endian(Header.Magic);
|
||||
u32 total_ifds = get_total_IFDs(Header.Offset);
|
||||
IFDS IFDs[total_ifds] @ Header.Offset;
|
||||
};
|
||||
|
||||
|
||||
TIFFFile File @ 0x00;
|
||||
BIN
tests/patterns/test_data/tiff.hexpat.tiff
Normal file
BIN
tests/patterns/test_data/tiff.hexpat.tiff
Normal file
Binary file not shown.
Reference in New Issue
Block a user