diff options
| author | Hisham Aburaqibah <haburaqibah@giga.ly> | 2025-01-16 11:11:39 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2025-09-08 17:12:58 +0200 |
| commit | a6f18c336772a735a70b439c7ffb687e3fb92efb (patch) | |
| tree | 5bccc2d8c8058a018fa19eb42448c22615f7f0af /core/image/common.odin | |
| parent | d704c45c2417da5fa1aef36262b6adbfdd19411a (diff) | |
image/jpeg: implement jpeg decoding for baseline and extended sequential jpegs
Diffstat (limited to 'core/image/common.odin')
| -rw-r--r-- | core/image/common.odin | 135 |
1 files changed, 133 insertions, 2 deletions
diff --git a/core/image/common.odin b/core/image/common.odin index 690ebc045..6d67115a1 100644 --- a/core/image/common.odin +++ b/core/image/common.odin @@ -64,6 +64,7 @@ Image_Metadata :: union #shared_nil { ^QOI_Info, ^TGA_Info, ^BMP_Info, + ^JPEG_Info, } @@ -112,8 +113,7 @@ Image_Option: `.alpha_drop_if_present` If the image has an alpha channel, drop it. - You may want to use `.alpha_ - tiply` in this case. + You may want to use `.alpha_premultiply` in this case. NOTE: For PNG, this also skips handling of the tRNS chunk, if present, unless you select `alpha_premultiply`. @@ -163,6 +163,7 @@ Error :: union #shared_nil { PNG_Error, QOI_Error, BMP_Error, + JPEG_Error, compress.Error, compress.General_Error, @@ -575,6 +576,136 @@ TGA_Info :: struct { extension: Maybe(TGA_Extension), } + +/* + JPEG-specific +*/ +JFIF_Magic := [?]byte{0x4A, 0x46, 0x49, 0x46} // "JFIF" +JFXX_Magic := [?]byte{0x4A, 0x46, 0x58, 0x58} // "JFXX" + +JPEG_Error :: enum { + None = 0, + Duplicate_SOI_Marker, + Invalid_JFXX_Extension_Code, + Encountered_SOS_Before_SOF, + Invalid_Quantization_Table_Precision, + Invalid_Quantization_Table_Index, + Invalid_Huffman_Coefficient_Type, + Invalid_Huffman_Table_Index, + Unsupported_Frame_Type, + Invalid_Frame_Bit_Depth_Combo, + Invalid_Sampling_Factor, + Unsupported_12_Bit_Depth, + Multiple_SOS_Markers, + Encountered_RST_Marker_Outside_ECS, + Extra_Data_After_SOS, // Image seemed to have decoded okay, but there's more data after SOS + Invalid_Thumbnail_Size, +} + +JFIF_Unit :: enum byte { + None = 0, + Dots_Per_Inch = 1, + Dots_Per_Centimeter = 2, +} + +JFIF_APP0 :: struct { + version: u16be, + units: JFIF_Unit, + x_density: u16be, + y_density: u16be, + x_thumbnail: byte, + y_thumbnail: byte, + thumbnail: []RGB_Pixel `fmt:"-"`, + greyscale_thumbnail: bool, +} + +JFXX_APP0 :: struct { + extension_code: JFXX_Extension_Code, + x_thumbnail: int, + y_thumbnail: int, + thumbnail: []byte `fmt:"-"`, +} + +JFXX_Extension_Code :: enum u8 { + Thumbnail_JPEG = 0x10, + Thumbnail_1_Byte_Palette = 0x11, + Thumbnail_3_Byte_RGB = 0x13, +} + +JPEG_Marker :: enum u8 { + SOF0 = 0xC0, + SOF1 = 0xC1, + SOF2 = 0xC2, + SOF3 = 0xC3, + DHT = 0xC4, + SOF5 = 0xC5, + SOF6 = 0xC6, + SOF7 = 0xC7, + JPG = 0xC8, + SOF9 = 0xC9, + SOF10 = 0xCA, + SOF11 = 0xCB, + DAC = 0xCC, + SOF13 = 0xCD, + SOF14 = 0xCE, + SOF15 = 0xCF, + RST0 = 0xD0, + RST1 = 0xD1, + RST2 = 0xD2, + RST3 = 0xD3, + RST4 = 0xD4, + RST5 = 0xD5, + RST6 = 0xD6, + RST7 = 0xD7, + SOI = 0xD8, + EOI = 0xD9, + SOS = 0xDA, + DQT = 0xDB, + DNL = 0xDC, + DRI = 0xDD, + DHP = 0xDE, + EXP = 0xDF, + APP0 = 0xE0, + APP1 = 0xE1, + APP2 = 0xE2, + APP3 = 0xE3, + APP4 = 0xE4, + APP5 = 0xE5, + APP6 = 0xE6, + APP7 = 0xE7, + APP8 = 0xE8, + APP9 = 0xE9, + APP10 = 0xEA, + APP11 = 0xEB, + APP12 = 0xEC, + APP13 = 0xED, + APP14 = 0xEE, + APP15 = 0xEF, + JPG0 = 0xF0, + JPG1 = 0xF1, + JPG2 = 0xF2, + JPG3 = 0xF3, + JPG4 = 0xF4, + JPG5 = 0xF5, + JPG6 = 0xF6, + JPG7 = 0xF7, + JPG8 = 0xF8, + JPG9 = 0xF9, + JPG10 = 0xFA, + JPG11 = 0xFB, + JPG12 = 0xFC, + JPG13 = 0xFD, + COM = 0xFE, + TEM = 0x01, +} + +JPEG_Info :: struct { + jfif_app0: Maybe(JFIF_APP0), + jfxx_app0: Maybe(JFXX_APP0), + comments: [dynamic]string, + //exif: Maybe(Exif), +} + // Function to help with image buffer calculations compute_buffer_size :: proc(width, height, channels, depth: int, extra_row_bytes := int(0)) -> (size: int) { size = ((((channels * width * depth) + 7) >> 3) + extra_row_bytes) * height |