mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-27 10:26:19 +03:00
commit
2fdd3e1fba
BIN
Tests/images/drawing_roundDown.emf
Normal file
BIN
Tests/images/drawing_roundDown.emf
Normal file
Binary file not shown.
BIN
Tests/images/hopper_roundDown.bmp
Normal file
BIN
Tests/images/hopper_roundDown.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
BIN
Tests/images/hopper_roundDown_2.tif
Normal file
BIN
Tests/images/hopper_roundDown_2.tif
Normal file
Binary file not shown.
BIN
Tests/images/hopper_roundDown_3.tif
Normal file
BIN
Tests/images/hopper_roundDown_3.tif
Normal file
Binary file not shown.
BIN
Tests/images/hopper_roundDown_None.tif
Normal file
BIN
Tests/images/hopper_roundDown_None.tif
Normal file
Binary file not shown.
BIN
Tests/images/hopper_roundUp_2.tif
Normal file
BIN
Tests/images/hopper_roundUp_2.tif
Normal file
Binary file not shown.
BIN
Tests/images/hopper_roundUp_3.tif
Normal file
BIN
Tests/images/hopper_roundUp_3.tif
Normal file
Binary file not shown.
BIN
Tests/images/hopper_roundUp_None.tif
Normal file
BIN
Tests/images/hopper_roundUp_None.tif
Normal file
Binary file not shown.
BIN
Tests/images/iptc_roundDown.jpg
Normal file
BIN
Tests/images/iptc_roundDown.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
Tests/images/iptc_roundUp.jpg
Normal file
BIN
Tests/images/iptc_roundUp.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -71,6 +71,27 @@ class TestFileBmp(PillowTestCase):
|
||||||
self.assertEqual(im.size, reloaded.size)
|
self.assertEqual(im.size, reloaded.size)
|
||||||
self.assertEqual(reloaded.format, "JPEG")
|
self.assertEqual(reloaded.format, "JPEG")
|
||||||
|
|
||||||
|
def test_load_dpi_rounding(self):
|
||||||
|
# Round up
|
||||||
|
im = Image.open('Tests/images/hopper.bmp')
|
||||||
|
self.assertEqual(im.info["dpi"], (96, 96))
|
||||||
|
|
||||||
|
# Round down
|
||||||
|
im = Image.open('Tests/images/hopper_roundDown.bmp')
|
||||||
|
self.assertEqual(im.info["dpi"], (72, 72))
|
||||||
|
|
||||||
|
def test_save_dpi_rounding(self):
|
||||||
|
outfile = self.tempfile("temp.bmp")
|
||||||
|
im = Image.open('Tests/images/hopper.bmp')
|
||||||
|
|
||||||
|
im.save(outfile, dpi=(72.2, 72.2))
|
||||||
|
reloaded = Image.open(outfile)
|
||||||
|
self.assertEqual(reloaded.info["dpi"], (72, 72))
|
||||||
|
|
||||||
|
im.save(outfile, dpi=(72.8, 72.8))
|
||||||
|
reloaded = Image.open(outfile)
|
||||||
|
self.assertEqual(reloaded.info["dpi"], (73, 73))
|
||||||
|
|
||||||
def test_load_dib(self):
|
def test_load_dib(self):
|
||||||
# test for #1293, Imagegrab returning Unsupported Bitfields Format
|
# test for #1293, Imagegrab returning Unsupported Bitfields Format
|
||||||
im = Image.open('Tests/images/clipboard.dib')
|
im = Image.open('Tests/images/clipboard.dib')
|
||||||
|
|
|
@ -524,6 +524,27 @@ class TestFileJpeg(PillowTestCase):
|
||||||
reloaded.load()
|
reloaded.load()
|
||||||
self.assertEqual(im.info['dpi'], reloaded.info['dpi'])
|
self.assertEqual(im.info['dpi'], reloaded.info['dpi'])
|
||||||
|
|
||||||
|
def test_load_dpi_rounding(self):
|
||||||
|
# Round up
|
||||||
|
im = Image.open('Tests/images/iptc_roundUp.jpg')
|
||||||
|
self.assertEqual(im.info["dpi"], (44, 44))
|
||||||
|
|
||||||
|
# Round down
|
||||||
|
im = Image.open('Tests/images/iptc_roundDown.jpg')
|
||||||
|
self.assertEqual(im.info["dpi"], (2, 2))
|
||||||
|
|
||||||
|
def test_save_dpi_rounding(self):
|
||||||
|
outfile = self.tempfile("temp.jpg")
|
||||||
|
im = Image.open('Tests/images/hopper.jpg')
|
||||||
|
|
||||||
|
im.save(outfile, dpi=(72.2, 72.2))
|
||||||
|
reloaded = Image.open(outfile)
|
||||||
|
self.assertEqual(reloaded.info["dpi"], (72, 72))
|
||||||
|
|
||||||
|
im.save(outfile, dpi=(72.8, 72.8))
|
||||||
|
reloaded = Image.open(outfile)
|
||||||
|
self.assertEqual(reloaded.info["dpi"], (73, 73))
|
||||||
|
|
||||||
def test_dpi_tuple_from_exif(self):
|
def test_dpi_tuple_from_exif(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
# This Photoshop CC 2017 image has DPI in EXIF not metadata
|
# This Photoshop CC 2017 image has DPI in EXIF not metadata
|
||||||
|
|
|
@ -389,6 +389,24 @@ class TestFilePng(PillowTestCase):
|
||||||
im = roundtrip(im, dpi=(100, 100))
|
im = roundtrip(im, dpi=(100, 100))
|
||||||
self.assertEqual(im.info["dpi"], (100, 100))
|
self.assertEqual(im.info["dpi"], (100, 100))
|
||||||
|
|
||||||
|
def test_load_dpi_rounding(self):
|
||||||
|
# Round up
|
||||||
|
im = Image.open(TEST_PNG_FILE)
|
||||||
|
self.assertEqual(im.info["dpi"], (96, 96))
|
||||||
|
|
||||||
|
# Round down
|
||||||
|
im = Image.open("Tests/images/icc_profile_none.png")
|
||||||
|
self.assertEqual(im.info["dpi"], (72, 72))
|
||||||
|
|
||||||
|
def test_save_dpi_rounding(self):
|
||||||
|
im = Image.open(TEST_PNG_FILE)
|
||||||
|
|
||||||
|
im = roundtrip(im, dpi=(72.2, 72.2))
|
||||||
|
self.assertEqual(im.info["dpi"], (72, 72))
|
||||||
|
|
||||||
|
im = roundtrip(im, dpi=(72.8, 72.8))
|
||||||
|
self.assertEqual(im.info["dpi"], (73, 73))
|
||||||
|
|
||||||
def test_roundtrip_text(self):
|
def test_roundtrip_text(self):
|
||||||
# Check text roundtripping
|
# Check text roundtripping
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,30 @@ class TestFileTiff(PillowTestCase):
|
||||||
im._setup()
|
im._setup()
|
||||||
self.assertEqual(im.info['dpi'], (71., 71.))
|
self.assertEqual(im.info['dpi'], (71., 71.))
|
||||||
|
|
||||||
|
def test_load_dpi_rounding(self):
|
||||||
|
for resolutionUnit, dpi in ((None, (72, 73)),
|
||||||
|
(2, (72, 73)),
|
||||||
|
(3, (183, 185))):
|
||||||
|
im = Image.open(
|
||||||
|
"Tests/images/hopper_roundDown_"+str(resolutionUnit)+".tif")
|
||||||
|
self.assertEqual(im.tag_v2.get(RESOLUTION_UNIT), resolutionUnit)
|
||||||
|
self.assertEqual(im.info['dpi'], (dpi[0], dpi[0]))
|
||||||
|
|
||||||
|
im = Image.open("Tests/images/hopper_roundUp_"+str(resolutionUnit)+".tif")
|
||||||
|
self.assertEqual(im.tag_v2.get(RESOLUTION_UNIT), resolutionUnit)
|
||||||
|
self.assertEqual(im.info['dpi'], (dpi[1], dpi[1]))
|
||||||
|
|
||||||
|
def test_save_dpi_rounding(self):
|
||||||
|
outfile = self.tempfile("temp.tif")
|
||||||
|
im = Image.open("Tests/images/hopper.tif")
|
||||||
|
|
||||||
|
for dpi in (72.2, 72.8):
|
||||||
|
im.save(outfile, dpi=(dpi, dpi))
|
||||||
|
|
||||||
|
reloaded = Image.open(outfile)
|
||||||
|
reloaded.load()
|
||||||
|
self.assertEqual((round(dpi), round(dpi)), reloaded.info['dpi'])
|
||||||
|
|
||||||
def test_save_setting_missing_resolution(self):
|
def test_save_setting_missing_resolution(self):
|
||||||
b = BytesIO()
|
b = BytesIO()
|
||||||
Image.open("Tests/images/10ct_32bit_128.tiff").save(
|
Image.open("Tests/images/10ct_32bit_128.tiff").save(
|
||||||
|
|
|
@ -45,6 +45,15 @@ class TestFileWmf(PillowTestCase):
|
||||||
# Restore the state before this test
|
# Restore the state before this test
|
||||||
WmfImagePlugin.register_handler(None)
|
WmfImagePlugin.register_handler(None)
|
||||||
|
|
||||||
|
def test_load_dpi_rounding(self):
|
||||||
|
# Round up
|
||||||
|
im = Image.open('Tests/images/drawing.emf')
|
||||||
|
self.assertEqual(im.info["dpi"], 1424)
|
||||||
|
|
||||||
|
# Round down
|
||||||
|
im = Image.open('Tests/images/drawing_roundDown.emf')
|
||||||
|
self.assertEqual(im.info["dpi"], 1426)
|
||||||
|
|
||||||
def test_save(self):
|
def test_save(self):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
from . import Image, ImageFile, ImagePalette
|
from . import Image, ImageFile, ImagePalette
|
||||||
from ._binary import i8, i16le as i16, i32le as i32, \
|
from ._binary import i8, i16le as i16, i32le as i32, \
|
||||||
o8, o16le as o16, o32le as o32
|
o8, o16le as o16, o32le as o32
|
||||||
import math
|
|
||||||
|
|
||||||
# __version__ is deprecated and will be removed in a future version. Use
|
# __version__ is deprecated and will be removed in a future version. Use
|
||||||
# PIL.__version__ instead.
|
# PIL.__version__ instead.
|
||||||
|
@ -121,8 +120,7 @@ class BmpImageFile(ImageFile.ImageFile):
|
||||||
file_info['colors'] = i32(header_data[28:32])
|
file_info['colors'] = i32(header_data[28:32])
|
||||||
file_info['palette_padding'] = 4
|
file_info['palette_padding'] = 4
|
||||||
self.info["dpi"] = tuple(
|
self.info["dpi"] = tuple(
|
||||||
map(lambda x: int(math.ceil(x / 39.3701)),
|
int(x / 39.3701 + 0.5) for x in file_info['pixels_per_meter'])
|
||||||
file_info['pixels_per_meter']))
|
|
||||||
if file_info['compression'] == self.BITFIELDS:
|
if file_info['compression'] == self.BITFIELDS:
|
||||||
if len(header_data) >= 52:
|
if len(header_data) >= 52:
|
||||||
for idx, mask in enumerate(['r_mask',
|
for idx, mask in enumerate(['r_mask',
|
||||||
|
@ -311,7 +309,7 @@ def _save(im, fp, filename, bitmap_header=True):
|
||||||
dpi = info.get("dpi", (96, 96))
|
dpi = info.get("dpi", (96, 96))
|
||||||
|
|
||||||
# 1 meter == 39.3701 inches
|
# 1 meter == 39.3701 inches
|
||||||
ppm = tuple(map(lambda x: int(x * 39.3701), dpi))
|
ppm = tuple(map(lambda x: int(x * 39.3701 + 0.5), dpi))
|
||||||
|
|
||||||
stride = ((im.size[0]*bits+7)//8+3) & (~3)
|
stride = ((im.size[0]*bits+7)//8+3) & (~3)
|
||||||
header = 40 # or 64 for OS/2 version 2
|
header = 40 # or 64 for OS/2 version 2
|
||||||
|
|
|
@ -160,13 +160,13 @@ def APP(self, marker):
|
||||||
resolution_unit = exif[0x0128]
|
resolution_unit = exif[0x0128]
|
||||||
x_resolution = exif[0x011A]
|
x_resolution = exif[0x011A]
|
||||||
try:
|
try:
|
||||||
dpi = x_resolution[0] / x_resolution[1]
|
dpi = float(x_resolution[0]) / x_resolution[1]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
dpi = x_resolution
|
dpi = x_resolution
|
||||||
if resolution_unit == 3: # cm
|
if resolution_unit == 3: # cm
|
||||||
# 1 dpcm = 2.54 dpi
|
# 1 dpcm = 2.54 dpi
|
||||||
dpi *= 2.54
|
dpi *= 2.54
|
||||||
self.info["dpi"] = dpi, dpi
|
self.info["dpi"] = int(dpi + 0.5), int(dpi + 0.5)
|
||||||
except (KeyError, SyntaxError, ZeroDivisionError):
|
except (KeyError, SyntaxError, ZeroDivisionError):
|
||||||
# SyntaxError for invalid/unreadable exif
|
# SyntaxError for invalid/unreadable exif
|
||||||
# KeyError for dpi not included
|
# KeyError for dpi not included
|
||||||
|
|
|
@ -1260,11 +1260,11 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
if xres and yres:
|
if xres and yres:
|
||||||
resunit = self.tag_v2.get(RESOLUTION_UNIT)
|
resunit = self.tag_v2.get(RESOLUTION_UNIT)
|
||||||
if resunit == 2: # dots per inch
|
if resunit == 2: # dots per inch
|
||||||
self.info["dpi"] = xres, yres
|
self.info["dpi"] = int(xres + 0.5), int(yres + 0.5)
|
||||||
elif resunit == 3: # dots per centimeter. convert to dpi
|
elif resunit == 3: # dots per centimeter. convert to dpi
|
||||||
self.info["dpi"] = xres * 2.54, yres * 2.54
|
self.info["dpi"] = int(xres * 2.54 + 0.5), int(yres * 2.54 + 0.5)
|
||||||
elif resunit is None: # used to default to 1, but now 2)
|
elif resunit is None: # used to default to 1, but now 2)
|
||||||
self.info["dpi"] = xres, yres
|
self.info["dpi"] = int(xres + 0.5), int(yres + 0.5)
|
||||||
# For backward compatibility,
|
# For backward compatibility,
|
||||||
# we also preserve the old behavior
|
# we also preserve the old behavior
|
||||||
self.info["resolution"] = xres, yres
|
self.info["resolution"] = xres, yres
|
||||||
|
@ -1475,8 +1475,8 @@ def _save(im, fp, filename):
|
||||||
dpi = im.encoderinfo.get("dpi")
|
dpi = im.encoderinfo.get("dpi")
|
||||||
if dpi:
|
if dpi:
|
||||||
ifd[RESOLUTION_UNIT] = 2
|
ifd[RESOLUTION_UNIT] = 2
|
||||||
ifd[X_RESOLUTION] = dpi[0]
|
ifd[X_RESOLUTION] = int(dpi[0] + 0.5)
|
||||||
ifd[Y_RESOLUTION] = dpi[1]
|
ifd[Y_RESOLUTION] = int(dpi[1] + 0.5)
|
||||||
|
|
||||||
if bits != (1,):
|
if bits != (1,):
|
||||||
ifd[BITSPERSAMPLE] = bits
|
ifd[BITSPERSAMPLE] = bits
|
||||||
|
|
|
@ -131,8 +131,8 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
size = x1 - x0, y1 - y0
|
size = x1 - x0, y1 - y0
|
||||||
|
|
||||||
# calculate dots per inch from bbox and frame
|
# calculate dots per inch from bbox and frame
|
||||||
xdpi = 2540 * (x1 - y0) // (frame[2] - frame[0])
|
xdpi = int(2540.0 * (x1 - y0) / (frame[2] - frame[0]) + 0.5)
|
||||||
ydpi = 2540 * (y1 - y0) // (frame[3] - frame[1])
|
ydpi = int(2540.0 * (y1 - y0) / (frame[3] - frame[1]) + 0.5)
|
||||||
|
|
||||||
self.info["wmf_bbox"] = x0, y0, x1, y1
|
self.info["wmf_bbox"] = x0, y0, x1, y1
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user