aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2023-12-17 15:55:20 -0800
committerRob Landley <rob@landley.net>2023-12-20 15:00:03 -0600
commit40e73a3873297040f3d57ffa7e1bebcf43f7a267 (patch)
treea562b49a35b8a0a688db1c7b306c3169e247beba
parent25cae192c6156512776de49b5d5569825a6931c5 (diff)
downloadtoybox-40e73a3873297040f3d57ffa7e1bebcf43f7a267.tar.gz
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.)
-rw-r--r--toys/posix/file.c20
1 files 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.