Skip to content

Commit

Permalink
Merge branch 'main' into fix-padding
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed Sep 21, 2022
2 parents 597dff7 + f98fde7 commit b3e847a
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 12 deletions.
17 changes: 17 additions & 0 deletions .github/renovate.json
@@ -0,0 +1,17 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
],
"labels": [
"Dependency"
],
"packageRules": [
{
"groupName": "github-actions",
"matchManagers": ["github-actions"],
"separateMajorMinor": "false"
}
],
"schedule": ["on the 3rd day of the month"]
}
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Expand Up @@ -40,6 +40,7 @@ repos:
rev: v4.3.0
hooks:
- id: check-merge-conflict
- id: check-json
- id: check-yaml

- repo: https://github.com/sphinx-contrib/sphinx-lint
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Expand Up @@ -25,6 +25,7 @@ exclude .coveragerc
exclude .editorconfig
exclude .readthedocs.yml
exclude codecov.yml
exclude renovate.json
global-exclude .git*
global-exclude *.pyc
global-exclude *.so
Expand Down
3 changes: 3 additions & 0 deletions README.md
Expand Up @@ -74,6 +74,9 @@ As of 2019, Pillow development is
<a href="https://pypi.org/project/Pillow/"><img
alt="Number of PyPI downloads"
src="https://img.shields.io/pypi/dm/pillow.svg"></a>
<a href="https://bestpractices.coreinfrastructure.org/projects/6331"><img
alt="OpenSSF Best Practices"
src="https://bestpractices.coreinfrastructure.org/projects/6331/badge"></a>
</td>
</tr>
<tr>
Expand Down
13 changes: 13 additions & 0 deletions Tests/test_file_gif.py
Expand Up @@ -1087,6 +1087,19 @@ def test_palette_save_P(tmp_path):
assert_image_equal(reloaded, im)


def test_palette_save_duplicate_entries(tmp_path):
im = Image.new("P", (1, 2))
im.putpixel((0, 1), 1)

im.putpalette((0, 0, 0, 0, 0, 0))

out = str(tmp_path / "temp.gif")
im.save(out, palette=[0, 0, 0, 0, 0, 0, 1, 1, 1])

with Image.open(out) as reloaded:
assert reloaded.convert("RGB").getpixel((0, 1)) == (0, 0, 0)


def test_palette_save_all_P(tmp_path):
frames = []
colors = ((255, 0, 0), (0, 255, 0))
Expand Down
1 change: 1 addition & 0 deletions Tests/test_image.py
Expand Up @@ -620,6 +620,7 @@ def test_remap_palette_transparency(self):

im_remapped = im.remap_palette([1, 0])
assert im_remapped.info["transparency"] == 1
assert len(im_remapped.getpalette()) == 6

# Test unused transparency
im.info["transparency"] = 2
Expand Down
19 changes: 19 additions & 0 deletions Tests/test_imageops.py
Expand Up @@ -110,6 +110,16 @@ def test_contain(new_size):
assert new_im.size == (256, 256)


def test_contain_round():
im = Image.new("1", (43, 63), 1)
new_im = ImageOps.contain(im, (5, 7))
assert new_im.width == 5

im = Image.new("1", (63, 43), 1)
new_im = ImageOps.contain(im, (7, 5))
assert new_im.height == 5


def test_pad():
# Same ratio
im = hopper()
Expand All @@ -130,6 +140,15 @@ def test_pad():
)


def test_pad_round():
im = Image.new("1", (1, 1), 1)
new_im = ImageOps.pad(im, (4, 1))
assert new_im.load()[2, 0] == 1

new_im = ImageOps.pad(im, (1, 4))
assert new_im.load()[0, 2] == 1


@pytest.mark.parametrize("mode", ("P", "PA"))
def test_palette(mode):
im = hopper(mode)
Expand Down
4 changes: 4 additions & 0 deletions docs/index.rst
Expand Up @@ -69,6 +69,10 @@ Pillow for enterprise is available via the Tidelift Subscription. `Learn more <h
:target: https://pypi.org/project/Pillow/
:alt: Number of PyPI downloads

.. image:: https://bestpractices.coreinfrastructure.org/projects/6331/badge
:target: https://bestpractices.coreinfrastructure.org/projects/6331
:alt: OpenSSF Best Practices

Overview
========

Expand Down
5 changes: 2 additions & 3 deletions src/PIL/GifImagePlugin.py
Expand Up @@ -519,9 +519,8 @@ def _normalize_palette(im, palette, info):
used_palette_colors = []
for i in range(0, len(source_palette), 3):
source_color = tuple(source_palette[i : i + 3])
try:
index = im.palette.colors[source_color]
except KeyError:
index = im.palette.colors.get(source_color)
if index in used_palette_colors:
index = None
used_palette_colors.append(index)
for i, index in enumerate(used_palette_colors):
Expand Down
6 changes: 1 addition & 5 deletions src/PIL/Image.py
Expand Up @@ -1949,11 +1949,7 @@ def remap_palette(self, dest_map, source_palette=None):

m_im = m_im.convert("L")

# Internally, we require 256 palette entries.
new_palette_bytes = (
palette_bytes + ((256 * bands) - len(palette_bytes)) * b"\x00"
)
m_im.putpalette(new_palette_bytes, palette_mode)
m_im.putpalette(palette_bytes, palette_mode)
m_im.palette = ImagePalette.ImagePalette(palette_mode, palette=palette_bytes)

if "transparency" in self.info:
Expand Down
8 changes: 4 additions & 4 deletions src/PIL/ImageOps.py
Expand Up @@ -255,11 +255,11 @@ def contain(image, size, method=Image.Resampling.BICUBIC):

if im_ratio != dest_ratio:
if im_ratio > dest_ratio:
new_height = int(image.height / image.width * size[0])
new_height = round(image.height / image.width * size[0])
if new_height != size[1]:
size = (size[0], new_height)
else:
new_width = int(image.width / image.height * size[1])
new_width = round(image.width / image.height * size[1])
if new_width != size[0]:
size = (new_width, size[1])
return image.resize(size, resample=method)
Expand Down Expand Up @@ -294,10 +294,10 @@ def pad(image, size, method=Image.Resampling.BICUBIC, color=None, centering=(0.5
if resized.palette:
out.putpalette(resized.getpalette())
if resized.width != size[0]:
x = int((size[0] - resized.width) * max(0, min(centering[0], 1)))
x = round((size[0] - resized.width) * max(0, min(centering[0], 1)))
out.paste(resized, (x, 0))
else:
y = int((size[1] - resized.height) * max(0, min(centering[1], 1)))
y = round((size[1] - resized.height) * max(0, min(centering[1], 1)))
out.paste(resized, (0, y))
return out

Expand Down

0 comments on commit b3e847a

Please sign in to comment.