aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2025-09-09 17:13:21 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2025-09-09 17:13:21 +0200
commit572b26a846b743933962719fde4a737da24db305 (patch)
tree633f09363f8d333d9a6338b734b5d1d5edc7d946
parent7b3ca701e0266cf2ffd4a8ee4b332ae569740fd1 (diff)
Expand grayscale JPEGs to RGB(A)
And handle grayscale jpeg example file in test suite.
-rw-r--r--core/image/jpeg/jpeg.odin34
-rw-r--r--tests/core/.gitignore2
-rw-r--r--tests/core/download_assets.py1
-rw-r--r--tests/core/image/test_core_image.odin8
4 files changed, 35 insertions, 10 deletions
diff --git a/core/image/jpeg/jpeg.odin b/core/image/jpeg/jpeg.odin
index 391b4316c..a2ad7e61e 100644
--- a/core/image/jpeg/jpeg.odin
+++ b/core/image/jpeg/jpeg.odin
@@ -190,6 +190,10 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
options -= {.return_header}
}
+ if .do_not_expand_channels in options || .do_not_expand_grayscale in options {
+ return img, .Unsupported_Option
+ }
+
first := compress.read_u8(ctx) or_return
soi := cast(image.JPEG_Marker)compress.read_u8(ctx) or_return
if first != 0xFF && soi != .SOI {
@@ -941,16 +945,25 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
}
}
+ orig_channels := img.channels
+
+ // We automatically expand grayscale images to RGB
+ if img.channels == 1 {
+ img.channels += 2
+ }
+
if .alpha_add_if_missing in options {
- img.channels += 1
+ img.channels += 1
+ orig_channels += 1
}
if resize(&img.pixels.buf, img.width * img.height * img.channels) != nil {
return img, .Unable_To_Allocate_Or_Resize
}
- switch img.channels {
- case 1:
+ switch orig_channels {
+ case 1: // Grayscale JPEG expanded to RGB
+ out := mem.slice_data_cast([]image.RGB_Pixel, img.pixels.buf[:])
out_idx := 0
for y in 0..<img.height {
mcu_row := y / BLOCK_SIZE
@@ -961,13 +974,15 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
mcu_idx := mcu_row * block_width + mcu_col
pixel_idx := pixel_row * BLOCK_SIZE + pixel_col
- img.pixels.buf[out_idx] = cast(byte)blocks[mcu_idx][.Y][pixel_idx]
+ luma := cast(byte)blocks[mcu_idx][.Y][pixel_idx]
+ out[out_idx] = {luma, luma, luma}
+
out_idx += 1
}
}
- case 2:
- out := mem.slice_data_cast([]image.GA_Pixel, img.pixels.buf[:])
+ case 2: // Grayscale JPEG expanded to RGBA
+ out := mem.slice_data_cast([]image.RGBA_Pixel, img.pixels.buf[:])
out_idx := 0
for y in 0..<img.height {
mcu_row := y / BLOCK_SIZE
@@ -979,10 +994,8 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
mcu_idx := mcu_row * block_width + mcu_col
pixel_idx := pixel_row * BLOCK_SIZE + pixel_col
- out[out_idx] = {
- cast(byte)blocks[mcu_idx][.Y][pixel_idx],
- 255, // Alpha
- }
+ luma := cast(byte)blocks[mcu_idx][.Y][pixel_idx]
+ out[out_idx] = {luma, luma, luma, 255}
out_idx += 1
}
}
@@ -1034,6 +1047,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
}
expect_EOI = true
+
case .TEM:
// TEM doesn't have a length, continue to next marker
case:
diff --git a/tests/core/.gitignore b/tests/core/.gitignore
index 40bf8bf19..05107f1f6 100644
--- a/tests/core/.gitignore
+++ b/tests/core/.gitignore
@@ -2,4 +2,6 @@
*.zip
*.png
*.jpg
+*.qoi
+*.pbm
math_big_test_library.* \ No newline at end of file
diff --git a/tests/core/download_assets.py b/tests/core/download_assets.py
index 22324dff0..b39aa059e 100644
--- a/tests/core/download_assets.py
+++ b/tests/core/download_assets.py
@@ -282,6 +282,7 @@ HMAC_DIGESTS = {
'emblem-1024.jpg': "d7b7e3ffaa5cda04c667e3742752091d78e02aa2d3c7a63406af679ce810a0a86666b10fcab12cc7ead2fadf2f6c2e1237bc94f892a62a4c218e18a20f96dbe4",
'emblem-1024-progressive.jpg': "7a6f4b112bd7189320c58dcddb9129968bcf268798c1e0c4f2243c10b3e3d9a6962c9f142d9fd65f8fb31e9a1e899008cae22b3ffde713250d315499b412e160",
+ 'emblem-1024-gray.jpg': "4c25aaab92451e0452cdb165833b2b5a51978c2571de9d053950944667847666ba198d3001291615acda098ebe45b7d2d53c210c492f077b04a6bfe386f8a5fd",
'unicode.xml': "e0cdc94f07fdbb15eea811ed2ae6dcf494a83d197dafe6580c740270feb0d8f5f7146d4a7d4c2d2ea25f8bd9678bc986123484b39399819a6b7262687959d1ae",
}
diff --git a/tests/core/image/test_core_image.odin b/tests/core/image/test_core_image.odin
index 3c7efc8a5..3293b80fa 100644
--- a/tests/core/image/test_core_image.odin
+++ b/tests/core/image/test_core_image.odin
@@ -51,6 +51,7 @@ Blend_BG_Keep :: image.Options{.blend_background, .alpha_add_if_missing}
Return_Metadata :: image.Options{.return_metadata}
No_Channel_Expansion :: image.Options{.do_not_expand_channels, .return_metadata}
+
Dims :: struct {
width: int,
height: int,
@@ -2375,6 +2376,13 @@ Basic_JPG_Tests := []Test{
{Default, .Unsupported_Frame_Type, {1024, 1024, 3, 8}, 0x_46a29e0f},
},
},
+ {
+ "emblem-1024-gray", {
+ {Default, nil, {1024, 1024, 3, 8}, 0x_4115d669},
+ {Alpha_Add, nil, {1024, 1024, 4, 8}, 0x_db496297},
+ {No_Channel_Expansion, .Unsupported_Option, {1024, 1024, 1, 8}, 0},
+ },
+ },
}
@test