mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 18:56:17 +03:00
Added second attribute to avoid unstable nature of qsort
This commit is contained in:
parent
7387ec23ac
commit
6541bd7cb5
BIN
Tests/images/hopper_resized.gif
Normal file
BIN
Tests/images/hopper_resized.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
|
@ -7,7 +7,12 @@ import pytest
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from .helper import assert_image_equal, assert_image_similar, hopper
|
from .helper import (
|
||||||
|
assert_image_equal,
|
||||||
|
assert_image_equal_tofile,
|
||||||
|
assert_image_similar,
|
||||||
|
hopper,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestImagingCoreResize:
|
class TestImagingCoreResize:
|
||||||
|
@ -135,6 +140,17 @@ class TestImagingCoreResize:
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
self.resize(hopper(), (10, 10), 9)
|
self.resize(hopper(), (10, 10), 9)
|
||||||
|
|
||||||
|
def test_cross_platform(self, tmp_path):
|
||||||
|
# This test is intended for only check for consistent behaviour across
|
||||||
|
# platforms. So if a future Pillow change requires that the test file
|
||||||
|
# be updated, that is okay.
|
||||||
|
im = hopper().resize((64, 64))
|
||||||
|
temp_file = str(tmp_path / "temp.gif")
|
||||||
|
im.save(temp_file)
|
||||||
|
|
||||||
|
with Image.open(temp_file) as reloaded:
|
||||||
|
assert_image_equal_tofile(reloaded, "Tests/images/hopper_resized.gif")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def gradients_image():
|
def gradients_image():
|
||||||
|
|
|
@ -753,11 +753,19 @@ annotate_hash_table(BoxNode *n, HashTable *h, uint32_t *box) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t *distance;
|
||||||
|
uint32_t index;
|
||||||
|
} DistanceWithIndex;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_sort_ulong_ptr_keys(const void *a, const void *b) {
|
_sort_ulong_ptr_keys(const void *a, const void *b) {
|
||||||
uint32_t A = **(uint32_t **)a;
|
DistanceWithIndex *A = (DistanceWithIndex *)a;
|
||||||
uint32_t B = **(uint32_t **)b;
|
DistanceWithIndex *B = (DistanceWithIndex *)b;
|
||||||
return (A == B) ? 0 : ((A < B) ? -1 : +1);
|
if (*A->distance == *B->distance) {
|
||||||
|
return A->index < B->index ? -1 : +1;
|
||||||
|
}
|
||||||
|
return *A->distance < *B->distance ? -1 : +1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -793,24 +801,42 @@ static int
|
||||||
build_distance_tables(
|
build_distance_tables(
|
||||||
uint32_t *avgDist, uint32_t **avgDistSortKey, Pixel *p, uint32_t nEntries) {
|
uint32_t *avgDist, uint32_t **avgDistSortKey, Pixel *p, uint32_t nEntries) {
|
||||||
uint32_t i, j;
|
uint32_t i, j;
|
||||||
|
DistanceWithIndex *dwi;
|
||||||
|
|
||||||
|
dwi = calloc(nEntries * nEntries, sizeof(DistanceWithIndex));
|
||||||
|
if (!dwi) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
for (i = 0; i < nEntries; i++) {
|
for (i = 0; i < nEntries; i++) {
|
||||||
avgDist[i * nEntries + i] = 0;
|
avgDist[i * nEntries + i] = 0;
|
||||||
avgDistSortKey[i * nEntries + i] = &(avgDist[i * nEntries + i]);
|
dwi[i * nEntries + i] = (DistanceWithIndex){
|
||||||
|
&(avgDist[i * nEntries + i]),
|
||||||
|
i * nEntries + i
|
||||||
|
};
|
||||||
for (j = 0; j < i; j++) {
|
for (j = 0; j < i; j++) {
|
||||||
avgDist[j * nEntries + i] = avgDist[i * nEntries + j] =
|
avgDist[j * nEntries + i] = avgDist[i * nEntries + j] =
|
||||||
_DISTSQR(p + i, p + j);
|
_DISTSQR(p + i, p + j);
|
||||||
avgDistSortKey[j * nEntries + i] = &(avgDist[j * nEntries + i]);
|
dwi[j * nEntries + i] = (DistanceWithIndex){
|
||||||
avgDistSortKey[i * nEntries + j] = &(avgDist[i * nEntries + j]);
|
&(avgDist[j * nEntries + i]),
|
||||||
|
j * nEntries + i
|
||||||
|
};
|
||||||
|
dwi[i * nEntries + j] = (DistanceWithIndex){
|
||||||
|
&(avgDist[i * nEntries + j]),
|
||||||
|
i * nEntries + j
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < nEntries; i++) {
|
for (i = 0; i < nEntries; i++) {
|
||||||
qsort(
|
qsort(
|
||||||
avgDistSortKey + i * nEntries,
|
dwi + i * nEntries,
|
||||||
nEntries,
|
nEntries,
|
||||||
sizeof(uint32_t *),
|
sizeof(DistanceWithIndex),
|
||||||
_sort_ulong_ptr_keys);
|
_sort_ulong_ptr_keys);
|
||||||
|
for (j = 0; j < nEntries; j++) {
|
||||||
|
avgDistSortKey[i * nEntries + j] = dwi[i * nEntries + j].distance;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
free(dwi);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1176,8 +1202,10 @@ k_means(
|
||||||
if (!built) {
|
if (!built) {
|
||||||
compute_palette_from_quantized_pixels(
|
compute_palette_from_quantized_pixels(
|
||||||
pixelData, nPixels, paletteData, nPaletteEntries, avg, count, qp);
|
pixelData, nPixels, paletteData, nPaletteEntries, avg, count, qp);
|
||||||
build_distance_tables(
|
if (!build_distance_tables(
|
||||||
avgDist, avgDistSortKey, paletteData, nPaletteEntries);
|
avgDist, avgDistSortKey, paletteData, nPaletteEntries)) {
|
||||||
|
goto error_3;
|
||||||
|
}
|
||||||
built = 1;
|
built = 1;
|
||||||
} else {
|
} else {
|
||||||
recompute_palette_from_averages(paletteData, nPaletteEntries, avg, count);
|
recompute_palette_from_averages(paletteData, nPaletteEntries, avg, count);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user