mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-28 07:47:02 -05:00
* 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>
319 lines
8.7 KiB
Rust
319 lines
8.7 KiB
Rust
#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;
|