int PNGAPI pngx_read_image(png_structp png_ptr, png_infop info_ptr, png_const_charpp fmt_name, png_const_charpp fmt_description) { png_byte sig[128]; size_t num; int (*read_fn)(png_structp, png_infop, FILE *); FILE *stream; fpos_t fpos; int result; /* Precondition. */ #ifdef PNG_FLAG_MALLOC_NULL_MEM_OK PNGX_ASSERT_MSG(!(png_ptr->flags & PNG_FLAG_MALLOC_NULL_MEM_OK), "pngxtern requires a safe allocator"); #endif /* Read the signature bytes. */ stream = (FILE *)png_get_io_ptr(png_ptr); PNGX_ASSERT(stream != NULL); if (fgetpos(stream, &fpos) != 0) png_error(png_ptr, "Can't ftell in input file stream"); num = fread(sig, 1, sizeof(sig), stream); if (fsetpos(stream, &fpos) != 0) png_error(png_ptr, "Can't fseek in input file stream"); /* Try the PNG format first. */ if (pngx_sig_is_png(png_ptr, sig, num, fmt_name, fmt_description) > 0) { png_read_png(png_ptr, info_ptr, 0, NULL); if (getc(stream) != EOF) { png_warning(png_ptr, "Extraneous data found after IEND"); fseek(stream, 0, SEEK_END); } return 1; } /* Check the signature bytes against other known image formats. */ if (pngx_sig_is_bmp(sig, num, fmt_name, fmt_description) > 0) read_fn = pngx_read_bmp; else if (pngx_sig_is_gif(sig, num, fmt_name, fmt_description) > 0) read_fn = pngx_read_gif; else if (pngx_sig_is_jpeg(sig, num, fmt_name, fmt_description) > 0) read_fn = pngx_read_jpeg; else if (pngx_sig_is_pnm(sig, num, fmt_name, fmt_description) > 0) read_fn = pngx_read_pnm; else if (pngx_sig_is_tiff(sig, num, fmt_name, fmt_description) > 0) read_fn = pngx_read_tiff; else return 0; /* not a known image format */ /* Read the image. */ result = read_fn(png_ptr, info_ptr, stream); /* Signature checking may give false positives; reading can still fail. */ if (result <= 0) /* this isn't the format we thought it was */ if (fsetpos(stream, &fpos) != 0) png_error(png_ptr, "Can't fseek in input file stream"); return result; }
int /* PRIVATE */ pngx_read_jpeg(png_structp png_ptr, png_infop info_ptr, FILE *stream) { png_byte buf[JPEG_SIG_SIZE_MAX]; int sig_code; if (fread(buf, JPEG_SIG_SIZE_MAX, 1, stream) != 1) return 0; /* not a JPEG file */ sig_code = pngx_sig_is_jpeg(buf, JPEG_SIG_SIZE_MAX, NULL, NULL); /* TODO: Use the format names passed by pngx_sig_is_jpeg. */ switch (sig_code) { case 1: png_error(png_ptr, "JPEG decoding is not supported"); /* NOTREACHED */ break; case 2: png_error(png_ptr, "JPEG-2000 decoding is not supported"); /* NOTREACHED */ break; case 3: png_error(png_ptr, "JNG (JPEG) decoding is not supported"); /* NOTREACHED */ break; } if (info_ptr == NULL) /* dummy, keep compilers happy */ return 0; return 0; /* always fail */ }