aboutsummaryrefslogtreecommitdiff
path: root/core/image/common.odin
diff options
context:
space:
mode:
authorHisham Aburaqibah <haburaqibah@giga.ly>2025-01-16 11:11:39 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2025-09-08 17:12:58 +0200
commita6f18c336772a735a70b439c7ffb687e3fb92efb (patch)
tree5bccc2d8c8058a018fa19eb42448c22615f7f0af /core/image/common.odin
parentd704c45c2417da5fa1aef36262b6adbfdd19411a (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.odin135
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