From 40e73a3873297040f3d57ffa7e1bebcf43f7a267 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Sun, 17 Dec 2023 15:55:20 -0800 Subject: [PATCH] file: parse JPEG files enough to pull out their size in pixels. This doesn't handle refilling toybuf in the case where there's so much EXIF data before the header we're looking for that we hit the end of toybuf first. (In part because I couldn't decide whether to do that or switch to a scheme where we only ever lseek() around, reading big-endian shorts.) --- toys/posix/file.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/toys/posix/file.c b/toys/posix/file.c index 8bc2b383..30d22495 100644 --- a/toys/posix/file.c +++ b/toys/posix/file.c @@ -244,10 +244,24 @@ static void do_regular_file(int fd, char *name) xprintf("GIF image data, version %3.3s, %d x %d\n", s-3, (int)peek_le(s, 2), (int)peek_le(s+2, 2)); - // TODO: parsing JPEG for width/height is harder than GIF or PNG. - else if (len>32 && !smemcmp(s, "\xff\xd8", 2)) xputs("JPEG image data"); + // https://en.wikipedia.org/wiki/JPEG#Syntax_and_structure + else if (len>32 && !smemcmp(s, "\xff\xd8", 2)) { + char *types[] = {"baseline", "extended sequential", "progressive"}; + int marker; + + printf("JPEG image data"); + while (s < toybuf+len-8) { // TODO: refill for files with lots of EXIF data? + marker = peek_be(s, 2); + if (marker >= 0xffd0 && marker <= 0xffd9) s += 2; // No data. + else if (marker >= 0xffc0 && marker <= 0xffc2) { + xprintf(", %s, %dx%d", types[marker-0xffc0], (int) peek_be(s+7, 2), + (int) peek_be(s+5, 2)); + break; + } else s += peek_be(s + 2, 2) + 2; + } + xputc('\n'); - else if (len>8 && strstart(&s, "\xca\xfe\xba\xbe")) { + } else if (len>8 && strstart(&s, "\xca\xfe\xba\xbe")) { unsigned count = peek_be(s, 4), i, arch; // 0xcafebabe can be a Java class file or a Mach-O universal binary. -- 2.39.2