mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-23 15:20:33 +03:00
commit
33d3bebb22
BIN
Tests/images/balloon.jpf
Normal file
BIN
Tests/images/balloon.jpf
Normal file
Binary file not shown.
|
@ -39,6 +39,12 @@ class TestFileJpeg2k(PillowTestCase):
|
||||||
self.assertEqual(im.mode, 'RGB')
|
self.assertEqual(im.mode, 'RGB')
|
||||||
self.assertEqual(im.size, (640, 480))
|
self.assertEqual(im.size, (640, 480))
|
||||||
self.assertEqual(im.format, 'JPEG2000')
|
self.assertEqual(im.format, 'JPEG2000')
|
||||||
|
self.assertEqual(im.get_format_mimetype(), 'image/jp2')
|
||||||
|
|
||||||
|
def test_jpf(self):
|
||||||
|
im = Image.open('Tests/images/balloon.jpf')
|
||||||
|
self.assertEqual(im.format, 'JPEG2000')
|
||||||
|
self.assertEqual(im.get_format_mimetype(), 'image/jpx')
|
||||||
|
|
||||||
def test_invalid_file(self):
|
def test_invalid_file(self):
|
||||||
invalid_file = "Tests/images/flower.jpg"
|
invalid_file = "Tests/images/flower.jpg"
|
||||||
|
|
|
@ -86,6 +86,7 @@ class TestFilePng(PillowTestCase):
|
||||||
self.assertEqual(im.mode, "RGB")
|
self.assertEqual(im.mode, "RGB")
|
||||||
self.assertEqual(im.size, (128, 128))
|
self.assertEqual(im.size, (128, 128))
|
||||||
self.assertEqual(im.format, "PNG")
|
self.assertEqual(im.format, "PNG")
|
||||||
|
self.assertEqual(im.get_format_mimetype(), 'image/png')
|
||||||
|
|
||||||
hopper("1").save(test_file)
|
hopper("1").save(test_file)
|
||||||
Image.open(test_file)
|
Image.open(test_file)
|
||||||
|
@ -589,6 +590,8 @@ class TestFilePng(PillowTestCase):
|
||||||
"WebP support not installed with animation")
|
"WebP support not installed with animation")
|
||||||
def test_apng(self):
|
def test_apng(self):
|
||||||
im = Image.open("Tests/images/iss634.apng")
|
im = Image.open("Tests/images/iss634.apng")
|
||||||
|
self.assertEqual(im.get_format_mimetype(), 'image/apng')
|
||||||
|
|
||||||
expected = Image.open("Tests/images/iss634.webp")
|
expected = Image.open("Tests/images/iss634.webp")
|
||||||
self.assert_image_similar(im, expected, 0.23)
|
self.assert_image_similar(im, expected, 0.23)
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ class TestFileSgi(PillowTestCase):
|
||||||
|
|
||||||
im = Image.open(test_file)
|
im = Image.open(test_file)
|
||||||
self.assert_image_equal(im, hopper())
|
self.assert_image_equal(im, hopper())
|
||||||
|
self.assertEqual(im.get_format_mimetype(), 'image/rgb')
|
||||||
|
|
||||||
def test_rgb16(self):
|
def test_rgb16(self):
|
||||||
test_file = "Tests/images/hopper16.rgb"
|
test_file = "Tests/images/hopper16.rgb"
|
||||||
|
@ -26,6 +27,7 @@ class TestFileSgi(PillowTestCase):
|
||||||
|
|
||||||
im = Image.open(test_file)
|
im = Image.open(test_file)
|
||||||
self.assert_image_similar(im, hopper('L'), 2)
|
self.assert_image_similar(im, hopper('L'), 2)
|
||||||
|
self.assertEqual(im.get_format_mimetype(), 'image/sgi')
|
||||||
|
|
||||||
def test_rgba(self):
|
def test_rgba(self):
|
||||||
# Created with ImageMagick:
|
# Created with ImageMagick:
|
||||||
|
@ -35,6 +37,7 @@ class TestFileSgi(PillowTestCase):
|
||||||
im = Image.open(test_file)
|
im = Image.open(test_file)
|
||||||
target = Image.open('Tests/images/transparent.png')
|
target = Image.open('Tests/images/transparent.png')
|
||||||
self.assert_image_equal(im, target)
|
self.assert_image_equal(im, target)
|
||||||
|
self.assertEqual(im.get_format_mimetype(), 'image/sgi')
|
||||||
|
|
||||||
def test_rle(self):
|
def test_rle(self):
|
||||||
# Created with ImageMagick:
|
# Created with ImageMagick:
|
||||||
|
|
|
@ -79,6 +79,8 @@ class ImageFile(Image.Image):
|
||||||
|
|
||||||
self._min_frame = 0
|
self._min_frame = 0
|
||||||
|
|
||||||
|
self.custom_mimetype = None
|
||||||
|
|
||||||
self.tile = None
|
self.tile = None
|
||||||
self.readonly = 1 # until we know better
|
self.readonly = 1 # until we know better
|
||||||
|
|
||||||
|
@ -120,7 +122,7 @@ class ImageFile(Image.Image):
|
||||||
def get_format_mimetype(self):
|
def get_format_mimetype(self):
|
||||||
if self.format is None:
|
if self.format is None:
|
||||||
return
|
return
|
||||||
return Image.MIME.get(self.format.upper())
|
return self.custom_mimetype or Image.MIME.get(self.format.upper())
|
||||||
|
|
||||||
def verify(self):
|
def verify(self):
|
||||||
"Check file integrity"
|
"Check file integrity"
|
||||||
|
|
|
@ -57,10 +57,11 @@ def _parse_codestream(fp):
|
||||||
|
|
||||||
def _parse_jp2_header(fp):
|
def _parse_jp2_header(fp):
|
||||||
"""Parse the JP2 header box to extract size, component count and
|
"""Parse the JP2 header box to extract size, component count and
|
||||||
color space information, returning a PIL (size, mode) tuple."""
|
color space information, returning a (size, mode, mimetype) tuple."""
|
||||||
|
|
||||||
# Find the JP2 header box
|
# Find the JP2 header box
|
||||||
header = None
|
header = None
|
||||||
|
mimetype = None
|
||||||
while True:
|
while True:
|
||||||
lbox, tbox = struct.unpack('>I4s', fp.read(8))
|
lbox, tbox = struct.unpack('>I4s', fp.read(8))
|
||||||
if lbox == 1:
|
if lbox == 1:
|
||||||
|
@ -75,6 +76,10 @@ def _parse_jp2_header(fp):
|
||||||
if tbox == b'jp2h':
|
if tbox == b'jp2h':
|
||||||
header = fp.read(lbox - hlen)
|
header = fp.read(lbox - hlen)
|
||||||
break
|
break
|
||||||
|
elif tbox == b'ftyp':
|
||||||
|
if fp.read(4) == b'jpx ':
|
||||||
|
mimetype = 'image/jpx'
|
||||||
|
fp.seek(lbox - hlen - 4, os.SEEK_CUR)
|
||||||
else:
|
else:
|
||||||
fp.seek(lbox - hlen, os.SEEK_CUR)
|
fp.seek(lbox - hlen, os.SEEK_CUR)
|
||||||
|
|
||||||
|
@ -145,7 +150,7 @@ def _parse_jp2_header(fp):
|
||||||
if size is None or mode is None:
|
if size is None or mode is None:
|
||||||
raise SyntaxError("Malformed jp2 header")
|
raise SyntaxError("Malformed jp2 header")
|
||||||
|
|
||||||
return (size, mode)
|
return (size, mode, mimetype)
|
||||||
|
|
||||||
##
|
##
|
||||||
# Image plugin for JPEG2000 images.
|
# Image plugin for JPEG2000 images.
|
||||||
|
@ -165,7 +170,8 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
if sig == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a':
|
if sig == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a':
|
||||||
self.codec = "jp2"
|
self.codec = "jp2"
|
||||||
self._size, self.mode = _parse_jp2_header(self.fp)
|
header = _parse_jp2_header(self.fp)
|
||||||
|
self._size, self.mode, self.custom_mimetype = header
|
||||||
else:
|
else:
|
||||||
raise SyntaxError('not a JPEG 2000 file')
|
raise SyntaxError('not a JPEG 2000 file')
|
||||||
|
|
||||||
|
@ -281,4 +287,3 @@ Image.register_extensions(Jpeg2KImageFile.format,
|
||||||
[".jp2", ".j2k", ".jpc", ".jpf", ".jpx", ".j2c"])
|
[".jp2", ".j2k", ".jpc", ".jpf", ".jpx", ".j2c"])
|
||||||
|
|
||||||
Image.register_mime(Jpeg2KImageFile.format, 'image/jp2')
|
Image.register_mime(Jpeg2KImageFile.format, 'image/jp2')
|
||||||
Image.register_mime(Jpeg2KImageFile.format, 'image/jpx')
|
|
||||||
|
|
|
@ -296,6 +296,7 @@ class PngStream(ChunkStream):
|
||||||
self.im_mode = None
|
self.im_mode = None
|
||||||
self.im_tile = None
|
self.im_tile = None
|
||||||
self.im_palette = None
|
self.im_palette = None
|
||||||
|
self.im_custom_mimetype = None
|
||||||
|
|
||||||
self.text_memory = 0
|
self.text_memory = 0
|
||||||
|
|
||||||
|
@ -529,6 +530,7 @@ class PngStream(ChunkStream):
|
||||||
# APNG chunks
|
# APNG chunks
|
||||||
def chunk_acTL(self, pos, length):
|
def chunk_acTL(self, pos, length):
|
||||||
s = ImageFile._safe_read(self.fp, length)
|
s = ImageFile._safe_read(self.fp, length)
|
||||||
|
self.im_custom_mimetype = 'image/apng'
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def chunk_fcTL(self, pos, length):
|
def chunk_fcTL(self, pos, length):
|
||||||
|
@ -594,6 +596,7 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
self.info = self.png.im_info
|
self.info = self.png.im_info
|
||||||
self._text = None
|
self._text = None
|
||||||
self.tile = self.png.im_tile
|
self.tile = self.png.im_tile
|
||||||
|
self.custom_mimetype = self.png.im_custom_mimetype
|
||||||
|
|
||||||
if self.png.im_palette:
|
if self.png.im_palette:
|
||||||
rawmode, data = self.png.im_palette
|
rawmode, data = self.png.im_palette
|
||||||
|
@ -908,4 +911,3 @@ Image.register_save(PngImageFile.format, _save)
|
||||||
Image.register_extensions(PngImageFile.format, [".png", ".apng"])
|
Image.register_extensions(PngImageFile.format, [".png", ".apng"])
|
||||||
|
|
||||||
Image.register_mime(PngImageFile.format, "image/png")
|
Image.register_mime(PngImageFile.format, "image/png")
|
||||||
Image.register_mime(PngImageFile.format, "image/apng")
|
|
||||||
|
|
|
@ -98,6 +98,8 @@ class SgiImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self._size = xsize, ysize
|
self._size = xsize, ysize
|
||||||
self.mode = rawmode.split(";")[0]
|
self.mode = rawmode.split(";")[0]
|
||||||
|
if self.mode == 'RGB':
|
||||||
|
self.custom_mimetype = 'image/rgb'
|
||||||
|
|
||||||
# orientation -1 : scanlines begins at the bottom-left corner
|
# orientation -1 : scanlines begins at the bottom-left corner
|
||||||
orientation = -1
|
orientation = -1
|
||||||
|
@ -220,7 +222,6 @@ Image.register_decoder("SGI16", SGI16Decoder)
|
||||||
Image.register_open(SgiImageFile.format, SgiImageFile, _accept)
|
Image.register_open(SgiImageFile.format, SgiImageFile, _accept)
|
||||||
Image.register_save(SgiImageFile.format, _save)
|
Image.register_save(SgiImageFile.format, _save)
|
||||||
Image.register_mime(SgiImageFile.format, "image/sgi")
|
Image.register_mime(SgiImageFile.format, "image/sgi")
|
||||||
Image.register_mime(SgiImageFile.format, "image/rgb")
|
|
||||||
|
|
||||||
Image.register_extensions(SgiImageFile.format,
|
Image.register_extensions(SgiImageFile.format,
|
||||||
[".bw", ".rgb", ".rgba", ".sgi"])
|
[".bw", ".rgb", ".rgba", ".sgi"])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user