Implement Header Sniffing For Magickload Tga (#2533)

Add TGA sniffing
This commit is contained in:
Moggers 2021-11-14 14:04:32 +10:00 committed by GitHub
parent 01e3f1fc33
commit b3ff4d9ed6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 4 deletions

View File

@ -52,12 +52,24 @@
#if defined(HAVE_MAGICK6) || defined(HAVE_MAGICK7)
/* ImageMagick can't detect some formats, like ICO, by examining the contents --
* ico.c simply does not have a recogniser.
/* ImageMagick can't detect some formats, like ICO and TGA, by examining the contents --
* ico.c and tga.c simply do not have recognisers.
*
* For these formats, do the detection ourselves.
*
* Return an IM format specifier, or NULL to let IM do the detection.
*
* For sniffing TGAs, we check that there is at least enough room for the header and that
* the preamble contains valid values:
* -----------------------------------------------------------
* |0x00 | 0-255 idlength, skip |
* |0x01 | 0-1, color map present |
* |0x02 | Any of (0, 1, 2, 3, 9, 10, 11), Image type |
* -----------------------------------------------------------
*
* References:
* * https://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf
* * http://www.paulbourke.net/dataformats/tga/
* * https://en.wikipedia.org/wiki/Truevision_TGA#Technical_details
*/
static const char *
magick_sniff( const unsigned char *bytes, size_t length )
@ -68,6 +80,16 @@ magick_sniff( const unsigned char *bytes, size_t length )
bytes[2] == 1 &&
bytes[3] == 0 )
return( "ICO" );
if( length >= 18 &&
(bytes[1] == 0 || bytes[1] == 1) && (
bytes[2] == 0 ||
bytes[2] == 1 ||
bytes[2] == 2 ||
bytes[2] == 3 ||
bytes[2] == 9 ||
bytes[2] == 10 ||
bytes[2] == 11) )
return( "TGA" );
return( NULL );
}

View File

@ -41,6 +41,8 @@ DICOM_FILE = os.path.join(IMAGES, "dicom_test_image.dcm")
BMP_FILE = os.path.join(IMAGES, "MARBLES.BMP")
NIFTI_FILE = os.path.join(IMAGES, "avg152T1_LR_nifti.nii.gz")
ICO_FILE = os.path.join(IMAGES, "favicon.ico")
TGA_FILE = os.path.join(IMAGES, "targa.tga")
SGI_FILE = os.path.join(IMAGES, "silicongraphics.sgi")
AVIF_FILE = os.path.join(IMAGES, "avif-orientation-6.avif")
HEIC_FILE = os.path.join(IMAGES, "heic-orientation-6.heic")
RGBA_FILE = os.path.join(IMAGES, "rgba.png")

Binary file not shown.

Binary file not shown.

View File

@ -10,7 +10,7 @@ from helpers import \
JPEG_FILE, SRGB_FILE, MATLAB_FILE, PNG_FILE, TIF_FILE, OME_FILE, \
ANALYZE_FILE, GIF_FILE, WEBP_FILE, EXR_FILE, FITS_FILE, OPENSLIDE_FILE, \
PDF_FILE, SVG_FILE, SVGZ_FILE, SVG_GZ_FILE, GIF_ANIM_FILE, DICOM_FILE, \
BMP_FILE, NIFTI_FILE, ICO_FILE, AVIF_FILE, TRUNCATED_FILE, \
BMP_FILE, NIFTI_FILE, ICO_FILE, TGA_FILE, SGI_FILE, AVIF_FILE, TRUNCATED_FILE, \
GIF_ANIM_EXPECTED_PNG_FILE, GIF_ANIM_DISPOSE_BACKGROUND_FILE, \
GIF_ANIM_DISPOSE_BACKGROUND_EXPECTED_PNG_FILE, \
GIF_ANIM_DISPOSE_PREVIOUS_FILE, \
@ -664,6 +664,22 @@ class TestForeign:
assert im.width == 16
assert im.height == 16
# libvips has its own sniffer for TGA, test that
with open(TGA_FILE, 'rb') as f:
buf = f.read()
im = pyvips.Image.new_from_buffer(buf, "")
assert im.width == 433
assert im.height == 433
# Test SGI/RGB files to sanity check that sniffers
# aren't too broad
with open(SGI_FILE, 'rb') as f:
buf = f.read()
im = pyvips.Image.new_from_buffer(buf, "")
assert im.width == 433
assert im.height == 433
# load should see metadata like eg. icc profiles
im = pyvips.Image.magickload(JPEG_FILE)
assert len(im.get("icc-profile-data")) == 564