mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 18:56:17 +03:00
Merge pull request #1889 from rr-/libpngquant
Add libimagequant support in quantize()
This commit is contained in:
commit
3657bc10a6
|
@ -45,6 +45,9 @@ install:
|
||||||
# openjpeg
|
# openjpeg
|
||||||
- pushd depends && ./install_openjpeg.sh && popd
|
- pushd depends && ./install_openjpeg.sh && popd
|
||||||
|
|
||||||
|
# libimagequant
|
||||||
|
- pushd depends && ./install_imagequant.sh && popd
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- if [ "$TRAVIS_PYTHON_VERSION" != "nightly" ]; then coverage erase; fi
|
- if [ "$TRAVIS_PYTHON_VERSION" != "nightly" ]; then coverage erase; fi
|
||||||
- python setup.py clean
|
- python setup.py clean
|
||||||
|
|
|
@ -185,6 +185,7 @@ ADAPTIVE = 1
|
||||||
MEDIANCUT = 0
|
MEDIANCUT = 0
|
||||||
MAXCOVERAGE = 1
|
MAXCOVERAGE = 1
|
||||||
FASTOCTREE = 2
|
FASTOCTREE = 2
|
||||||
|
LIBIMAGEQUANT = 3
|
||||||
|
|
||||||
# categories
|
# categories
|
||||||
NORMAL = 0
|
NORMAL = 0
|
||||||
|
@ -961,6 +962,7 @@ class Image(object):
|
||||||
:param method: 0 = median cut
|
:param method: 0 = median cut
|
||||||
1 = maximum coverage
|
1 = maximum coverage
|
||||||
2 = fast octree
|
2 = fast octree
|
||||||
|
3 = libimagequant
|
||||||
:param kmeans: Integer
|
:param kmeans: Integer
|
||||||
:param palette: Quantize to the :py:class:`PIL.ImagingPalette` palette.
|
:param palette: Quantize to the :py:class:`PIL.ImagingPalette` palette.
|
||||||
:returns: A new image
|
:returns: A new image
|
||||||
|
@ -975,10 +977,11 @@ class Image(object):
|
||||||
if self.mode == 'RGBA':
|
if self.mode == 'RGBA':
|
||||||
method = 2
|
method = 2
|
||||||
|
|
||||||
if self.mode == 'RGBA' and method != 2:
|
if self.mode == 'RGBA' and method not in (2, 3):
|
||||||
# Caller specified an invalid mode.
|
# Caller specified an invalid mode.
|
||||||
raise ValueError('Fast Octree (method == 2) is the ' +
|
raise ValueError(
|
||||||
' only valid method for quantizing RGBA images')
|
'Fast Octree (method == 2) and libimagequant (method == 3) ' +
|
||||||
|
'are the only valid methods for quantizing RGBA images')
|
||||||
|
|
||||||
if palette:
|
if palette:
|
||||||
# use palette from reference image
|
# use palette from reference image
|
||||||
|
|
|
@ -6,31 +6,46 @@ from PIL import Image
|
||||||
class TestImageQuantize(PillowTestCase):
|
class TestImageQuantize(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
im = hopper()
|
image = hopper()
|
||||||
|
converted = image.quantize()
|
||||||
|
self.assert_image(converted, 'P', converted.size)
|
||||||
|
self.assert_image_similar(converted.convert('RGB'), image, 10)
|
||||||
|
|
||||||
im = im.quantize()
|
image = hopper()
|
||||||
self.assert_image(im, "P", im.size)
|
converted = image.quantize(palette=hopper('P'))
|
||||||
|
self.assert_image(converted, 'P', converted.size)
|
||||||
|
self.assert_image_similar(converted.convert('RGB'), image, 60)
|
||||||
|
|
||||||
im = hopper()
|
def test_libimagequant_quantize(self):
|
||||||
im = im.quantize(palette=hopper("P"))
|
image = hopper()
|
||||||
self.assert_image(im, "P", im.size)
|
try:
|
||||||
|
converted = image.quantize(100, Image.LIBIMAGEQUANT)
|
||||||
|
except ValueError as ex:
|
||||||
|
if 'dependency' in str(ex).lower():
|
||||||
|
self.skipTest('libimagequant support not available')
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
self.assert_image(converted, 'P', converted.size)
|
||||||
|
self.assert_image_similar(converted.convert('RGB'), image, 15)
|
||||||
|
assert len(converted.getcolors()) == 100
|
||||||
|
|
||||||
def test_octree_quantize(self):
|
def test_octree_quantize(self):
|
||||||
im = hopper()
|
image = hopper()
|
||||||
|
converted = image.quantize(100, Image.FASTOCTREE)
|
||||||
im = im.quantize(100, Image.FASTOCTREE)
|
self.assert_image(converted, 'P', converted.size)
|
||||||
self.assert_image(im, "P", im.size)
|
self.assert_image_similar(converted.convert('RGB'), image, 20)
|
||||||
|
assert len(converted.getcolors()) == 100
|
||||||
assert len(im.getcolors()) == 100
|
|
||||||
|
|
||||||
def test_rgba_quantize(self):
|
def test_rgba_quantize(self):
|
||||||
im = hopper('RGBA')
|
image = hopper('RGBA')
|
||||||
im.quantize()
|
image.quantize()
|
||||||
self.assertRaises(Exception, lambda: im.quantize(method=0))
|
self.assertRaises(Exception, lambda: image.quantize(method=0))
|
||||||
|
|
||||||
def test_quantize(self):
|
def test_quantize(self):
|
||||||
im = Image.open('Tests/images/caption_6_33_22.png')
|
image = Image.open('Tests/images/caption_6_33_22.png').convert('RGB')
|
||||||
im.convert('RGB').quantize().convert('RGB')
|
converted = image.quantize()
|
||||||
|
self.assert_image(converted, 'P', converted.size)
|
||||||
|
self.assert_image_similar(converted.convert('RGB'), image, 1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
Depends
|
Depends
|
||||||
=======
|
=======
|
||||||
|
|
||||||
``install_openjpeg.sh`` and ``install_webp.sh`` can be used to
|
``install_openjpeg.sh``, ``install_webp.sh`` and ``install_imagequant.sh`` can
|
||||||
download, build & install non-packaged dependencies; useful for
|
be used to download, build & install non-packaged dependencies; useful for
|
||||||
testing with Travis CI.
|
testing with Travis CI.
|
||||||
|
|
||||||
The other scripts can be used to install all of the dependencies for
|
The other scripts can be used to install all of the dependencies for
|
||||||
|
|
|
@ -14,3 +14,4 @@ sudo apt-get -y install libtiff5-dev libjpeg62-turbo-dev zlib1g-dev \
|
||||||
python-tk python3-tk
|
python-tk python3-tk
|
||||||
|
|
||||||
./install_openjpeg.sh
|
./install_openjpeg.sh
|
||||||
|
./install_imagequant.sh
|
||||||
|
|
12
depends/install_imagequant.sh
Executable file
12
depends/install_imagequant.sh
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# install libimagequant
|
||||||
|
|
||||||
|
git clone -b 2.6.0 https://github.com/pornel/pngquant
|
||||||
|
|
||||||
|
pushd pngquant
|
||||||
|
|
||||||
|
make -C lib shared
|
||||||
|
sudo cp lib/libimagequant.so* /usr/lib/
|
||||||
|
sudo cp lib/libimagequant.h /usr/include/
|
||||||
|
|
||||||
|
popd
|
|
@ -14,3 +14,4 @@ sudo apt-get install libtiff4-dev libjpeg8-dev zlib1g-dev \
|
||||||
|
|
||||||
./install_openjpeg.sh
|
./install_openjpeg.sh
|
||||||
./install_webp.sh
|
./install_webp.sh
|
||||||
|
./install_imagequant.sh
|
||||||
|
|
|
@ -12,3 +12,4 @@ sudo apt-get -y install libtiff5-dev libjpeg8-dev zlib1g-dev \
|
||||||
python-tk python3-tk
|
python-tk python3-tk
|
||||||
|
|
||||||
./install_openjpeg.sh
|
./install_openjpeg.sh
|
||||||
|
./install_imagequant.sh
|
||||||
|
|
|
@ -140,6 +140,8 @@ Many of Pillow's features require external libraries:
|
||||||
|
|
||||||
* **libfreetype** provides type related services
|
* **libfreetype** provides type related services
|
||||||
|
|
||||||
|
* **libimagequant** provides improved color quantization
|
||||||
|
|
||||||
* **littlecms** provides color management
|
* **littlecms** provides color management
|
||||||
|
|
||||||
* Pillow version 2.2.1 and below uses liblcms1, Pillow 2.3.0 and
|
* Pillow version 2.2.1 and below uses liblcms1, Pillow 2.3.0 and
|
||||||
|
@ -190,17 +192,17 @@ Build Options
|
||||||
* Build flags: ``--disable-zlib``, ``--disable-jpeg``,
|
* Build flags: ``--disable-zlib``, ``--disable-jpeg``,
|
||||||
``--disable-tiff``, ``--disable-freetype``, ``--disable-tcl``,
|
``--disable-tiff``, ``--disable-freetype``, ``--disable-tcl``,
|
||||||
``--disable-tk``, ``--disable-lcms``, ``--disable-webp``,
|
``--disable-tk``, ``--disable-lcms``, ``--disable-webp``,
|
||||||
``--disable-webpmux``, ``--disable-jpeg2000``. Disable building the
|
``--disable-webpmux``, ``--disable-jpeg2000``, ``--disable-imagequant``.
|
||||||
corresponding feature even if the development libraries are present
|
Disable building the corresponding feature even if the development
|
||||||
on the building machine.
|
libraries are present on the building machine.
|
||||||
|
|
||||||
* Build flags: ``--enable-zlib``, ``--enable-jpeg``,
|
* Build flags: ``--enable-zlib``, ``--enable-jpeg``,
|
||||||
``--enable-tiff``, ``--enable-freetype``, ``--enable-tcl``,
|
``--enable-tiff``, ``--enable-freetype``, ``--enable-tcl``,
|
||||||
``--enable-tk``, ``--enable-lcms``, ``--enable-webp``,
|
``--enable-tk``, ``--enable-lcms``, ``--enable-webp``,
|
||||||
``--enable-webpmux``, ``--enable-jpeg2000``. Require that the
|
``--enable-webpmux``, ``--enable-jpeg2000``, ``--enable-imagequant``.
|
||||||
corresponding feature is built. The build will raise an exception if
|
Require that the corresponding feature is built. The build will raise
|
||||||
the libraries are not found. Webpmux (WebP metadata) relies on WebP
|
an exception if the libraries are not found. Webpmux (WebP metadata)
|
||||||
support. Tcl and Tk also must be used together.
|
relies on WebP support. Tcl and Tk also must be used together.
|
||||||
|
|
||||||
* Build flag: ``--disable-platform-guessing``. Skips all of the
|
* Build flag: ``--disable-platform-guessing``. Skips all of the
|
||||||
platform dependent guessing of include and library directories for
|
platform dependent guessing of include and library directories for
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "QuantTypes.h"
|
#include "QuantTypes.h"
|
||||||
#include "QuantOctree.h"
|
#include "QuantOctree.h"
|
||||||
|
#include "QuantPngQuant.h"
|
||||||
#include "QuantHash.h"
|
#include "QuantHash.h"
|
||||||
#include "QuantHeap.h"
|
#include "QuantHeap.h"
|
||||||
|
|
||||||
|
@ -1483,8 +1484,8 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
|
||||||
strcmp(im->mode, "RGB") != 0 && strcmp(im->mode, "RGBA") !=0)
|
strcmp(im->mode, "RGB") != 0 && strcmp(im->mode, "RGBA") !=0)
|
||||||
return ImagingError_ModeError();
|
return ImagingError_ModeError();
|
||||||
|
|
||||||
/* only octree supports RGBA */
|
/* only octree and imagequant supports RGBA */
|
||||||
if (!strcmp(im->mode, "RGBA") && mode != 2)
|
if (!strcmp(im->mode, "RGBA") && mode != 2 && mode != 3)
|
||||||
return ImagingError_ModeError();
|
return ImagingError_ModeError();
|
||||||
|
|
||||||
p = malloc(sizeof(Pixel) * im->xsize * im->ysize);
|
p = malloc(sizeof(Pixel) * im->xsize * im->ysize);
|
||||||
|
@ -1503,8 +1504,10 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
|
||||||
should be done by a simple copy... */
|
should be done by a simple copy... */
|
||||||
|
|
||||||
for (i = y = 0; y < im->ysize; y++)
|
for (i = y = 0; y < im->ysize; y++)
|
||||||
for (x = 0; x < im->xsize; x++, i++)
|
for (x = 0; x < im->xsize; x++, i++) {
|
||||||
p[i].c.r = p[i].c.g = p[i].c.b = im->image8[y][x];
|
p[i].c.r = p[i].c.g = p[i].c.b = im->image8[y][x];
|
||||||
|
p[i].c.a = 255;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (!strcmp(im->mode, "P")) {
|
} else if (!strcmp(im->mode, "P")) {
|
||||||
/* palette */
|
/* palette */
|
||||||
|
@ -1517,6 +1520,7 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
|
||||||
p[i].c.r = pp[v*4+0];
|
p[i].c.r = pp[v*4+0];
|
||||||
p[i].c.g = pp[v*4+1];
|
p[i].c.g = pp[v*4+1];
|
||||||
p[i].c.b = pp[v*4+2];
|
p[i].c.b = pp[v*4+2];
|
||||||
|
p[i].c.a = pp[v*4+3];
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!strcmp(im->mode, "RGB") || !strcmp(im->mode, "RGBA")) {
|
} else if (!strcmp(im->mode, "RGB") || !strcmp(im->mode, "RGBA")) {
|
||||||
|
@ -1572,6 +1576,25 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
|
||||||
withAlpha
|
withAlpha
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
#ifdef HAVE_LIBIMAGEQUANT
|
||||||
|
if (!strcmp(im->mode, "RGBA")) {
|
||||||
|
withAlpha = 1;
|
||||||
|
}
|
||||||
|
result = quantize_pngquant(
|
||||||
|
p,
|
||||||
|
im->xsize,
|
||||||
|
im->ysize,
|
||||||
|
colors,
|
||||||
|
&palette,
|
||||||
|
&paletteLength,
|
||||||
|
&newData,
|
||||||
|
withAlpha
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
result = -1;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
result = 0;
|
result = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -1580,7 +1603,7 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
|
||||||
free(p);
|
free(p);
|
||||||
ImagingSectionLeave(&cookie);
|
ImagingSectionLeave(&cookie);
|
||||||
|
|
||||||
if (result) {
|
if (result > 0) {
|
||||||
imOut = ImagingNew("P", im->xsize, im->ysize);
|
imOut = ImagingNew("P", im->xsize, im->ysize);
|
||||||
ImagingSectionEnter(&cookie);
|
ImagingSectionEnter(&cookie);
|
||||||
|
|
||||||
|
@ -1620,6 +1643,12 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
if (result == -1) {
|
||||||
|
return (Imaging) ImagingError_ValueError(
|
||||||
|
"dependency required by this method was not "
|
||||||
|
"enabled at compile time");
|
||||||
|
}
|
||||||
|
|
||||||
return (Imaging) ImagingError_ValueError("quantization error");
|
return (Imaging) ImagingError_ValueError("quantization error");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
110
libImaging/QuantPngQuant.c
Normal file
110
libImaging/QuantPngQuant.c
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* The Python Imaging Library
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* quantization using libimagequant, a part of pngquant.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Marcin Kurczewski <rr-@sakuya.pl>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "QuantPngQuant.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBIMAGEQUANT
|
||||||
|
#include "libimagequant.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
quantize_pngquant(
|
||||||
|
Pixel *pixelData,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
uint32_t quantPixels,
|
||||||
|
Pixel **palette,
|
||||||
|
uint32_t *paletteLength,
|
||||||
|
uint32_t **quantizedPixels,
|
||||||
|
int withAlpha)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
liq_image *image = NULL;
|
||||||
|
liq_attr *attr = NULL;
|
||||||
|
liq_result *remap = NULL;
|
||||||
|
unsigned char *charMatrix = NULL;
|
||||||
|
unsigned char **charMatrixRows = NULL;
|
||||||
|
unsigned int i, y;
|
||||||
|
*palette = NULL;
|
||||||
|
*paletteLength = 0;
|
||||||
|
*quantizedPixels = NULL;
|
||||||
|
|
||||||
|
/* configure pngquant */
|
||||||
|
attr = liq_attr_create();
|
||||||
|
if (!attr) { goto err; }
|
||||||
|
if (quantPixels) {
|
||||||
|
liq_set_max_colors(attr, quantPixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prepare input image */
|
||||||
|
image = liq_image_create_rgba(
|
||||||
|
attr,
|
||||||
|
pixelData,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
0.45455 /* gamma */);
|
||||||
|
if (!image) { goto err; }
|
||||||
|
|
||||||
|
/* quantize the image */
|
||||||
|
remap = liq_quantize_image(attr, image);
|
||||||
|
if (!remap) { goto err; }
|
||||||
|
liq_set_output_gamma(remap, 0.45455);
|
||||||
|
liq_set_dithering_level(remap, 1);
|
||||||
|
|
||||||
|
/* write output palette */
|
||||||
|
const liq_palette *l_palette = liq_get_palette(remap);
|
||||||
|
*paletteLength = l_palette->count;
|
||||||
|
*palette = malloc(sizeof(Pixel) * l_palette->count);
|
||||||
|
if (!*palette) { goto err; }
|
||||||
|
for (i = 0; i < l_palette->count; i++) {
|
||||||
|
(*palette)[i].c.b = l_palette->entries[i].b;
|
||||||
|
(*palette)[i].c.g = l_palette->entries[i].g;
|
||||||
|
(*palette)[i].c.r = l_palette->entries[i].r;
|
||||||
|
(*palette)[i].c.a = l_palette->entries[i].a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write output pixels (pngquant uses char array) */
|
||||||
|
charMatrix = malloc(width * height);
|
||||||
|
if (!charMatrix) { goto err; }
|
||||||
|
charMatrixRows = malloc(height * sizeof(unsigned char*));
|
||||||
|
if (!charMatrixRows) { goto err; }
|
||||||
|
for (y = 0; y < height; y++) {
|
||||||
|
charMatrixRows[y] = &charMatrix[y * width];
|
||||||
|
}
|
||||||
|
if (LIQ_OK != liq_write_remapped_image_rows(remap, image, charMatrixRows)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* transcribe output pixels (pillow uses uint32_t array) */
|
||||||
|
*quantizedPixels = malloc(sizeof(uint32_t) * width * height);
|
||||||
|
if (!*quantizedPixels) { goto err; }
|
||||||
|
for (i = 0; i < width * height; i++) {
|
||||||
|
(*quantizedPixels)[i] = charMatrix[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
result = 1;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (attr) liq_attr_destroy(attr);
|
||||||
|
if (image) liq_image_destroy(image);
|
||||||
|
if (remap) liq_result_destroy(remap);
|
||||||
|
free(charMatrix);
|
||||||
|
free(charMatrixRows);
|
||||||
|
if (!result) {
|
||||||
|
free(*quantizedPixels);
|
||||||
|
free(*palette);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
15
libImaging/QuantPngQuant.h
Normal file
15
libImaging/QuantPngQuant.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef __QUANT_PNGQUANT_H__
|
||||||
|
#define __QUANT_PNGQUANT_H__
|
||||||
|
|
||||||
|
#include "QuantTypes.h"
|
||||||
|
|
||||||
|
int quantize_pngquant(Pixel *,
|
||||||
|
int,
|
||||||
|
int,
|
||||||
|
uint32_t,
|
||||||
|
Pixel **,
|
||||||
|
uint32_t *,
|
||||||
|
uint32_t **,
|
||||||
|
int);
|
||||||
|
|
||||||
|
#endif
|
19
setup.py
19
setup.py
|
@ -36,7 +36,7 @@ _LIB_IMAGING = (
|
||||||
"RankFilter", "RawDecode", "RawEncode", "Storage", "SunRleDecode",
|
"RankFilter", "RawDecode", "RawEncode", "Storage", "SunRleDecode",
|
||||||
"TgaRleDecode", "Unpack", "UnpackYCC", "UnsharpMask", "XbmDecode",
|
"TgaRleDecode", "Unpack", "UnpackYCC", "UnsharpMask", "XbmDecode",
|
||||||
"XbmEncode", "ZipDecode", "ZipEncode", "TiffDecode", "Incremental",
|
"XbmEncode", "ZipDecode", "ZipEncode", "TiffDecode", "Incremental",
|
||||||
"Jpeg2KDecode", "Jpeg2KEncode", "BoxBlur")
|
"Jpeg2KDecode", "Jpeg2KEncode", "BoxBlur", "QuantPngQuant")
|
||||||
|
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
|
|
||||||
|
@ -115,6 +115,7 @@ TCL_ROOT = None
|
||||||
JPEG_ROOT = None
|
JPEG_ROOT = None
|
||||||
JPEG2K_ROOT = None
|
JPEG2K_ROOT = None
|
||||||
ZLIB_ROOT = None
|
ZLIB_ROOT = None
|
||||||
|
IMAGEQUANT_ROOT = None
|
||||||
TIFF_ROOT = None
|
TIFF_ROOT = None
|
||||||
FREETYPE_ROOT = None
|
FREETYPE_ROOT = None
|
||||||
LCMS_ROOT = None
|
LCMS_ROOT = None
|
||||||
|
@ -123,7 +124,7 @@ LCMS_ROOT = None
|
||||||
class pil_build_ext(build_ext):
|
class pil_build_ext(build_ext):
|
||||||
class feature:
|
class feature:
|
||||||
features = ['zlib', 'jpeg', 'tiff', 'freetype', 'tcl', 'tk', 'lcms',
|
features = ['zlib', 'jpeg', 'tiff', 'freetype', 'tcl', 'tk', 'lcms',
|
||||||
'webp', 'webpmux', 'jpeg2000']
|
'webp', 'webpmux', 'jpeg2000', 'imagequant']
|
||||||
|
|
||||||
required = set(['jpeg', 'zlib'])
|
required = set(['jpeg', 'zlib'])
|
||||||
|
|
||||||
|
@ -193,7 +194,7 @@ class pil_build_ext(build_ext):
|
||||||
# add configured kits
|
# add configured kits
|
||||||
|
|
||||||
for root in (TCL_ROOT, JPEG_ROOT, JPEG2K_ROOT, TIFF_ROOT, ZLIB_ROOT,
|
for root in (TCL_ROOT, JPEG_ROOT, JPEG2K_ROOT, TIFF_ROOT, ZLIB_ROOT,
|
||||||
FREETYPE_ROOT, LCMS_ROOT):
|
FREETYPE_ROOT, LCMS_ROOT, IMAGEQUANT_ROOT):
|
||||||
if isinstance(root, type(())):
|
if isinstance(root, type(())):
|
||||||
lib_root, include_root = root
|
lib_root, include_root = root
|
||||||
else:
|
else:
|
||||||
|
@ -490,6 +491,14 @@ class pil_build_ext(build_ext):
|
||||||
feature.openjpeg_version = '.'.join([str(x) for x in
|
feature.openjpeg_version = '.'.join([str(x) for x in
|
||||||
best_version])
|
best_version])
|
||||||
|
|
||||||
|
if feature.want('imagequant'):
|
||||||
|
_dbg('Looking for imagequant')
|
||||||
|
if _find_include_file(self, 'libimagequant.h'):
|
||||||
|
if _find_library_file(self, "imagequant"):
|
||||||
|
feature.imagequant = "imagequant"
|
||||||
|
elif _find_library_file(self, "libimagequant"):
|
||||||
|
feature.imagequant = "libimagequant"
|
||||||
|
|
||||||
if feature.want('tiff'):
|
if feature.want('tiff'):
|
||||||
_dbg('Looking for tiff')
|
_dbg('Looking for tiff')
|
||||||
if _find_include_file(self, 'tiff.h'):
|
if _find_include_file(self, 'tiff.h'):
|
||||||
|
@ -603,6 +612,9 @@ class pil_build_ext(build_ext):
|
||||||
if feature.zlib:
|
if feature.zlib:
|
||||||
libs.append(feature.zlib)
|
libs.append(feature.zlib)
|
||||||
defs.append(("HAVE_LIBZ", None))
|
defs.append(("HAVE_LIBZ", None))
|
||||||
|
if feature.imagequant:
|
||||||
|
libs.append(feature.imagequant)
|
||||||
|
defs.append(("HAVE_LIBIMAGEQUANT", None))
|
||||||
if feature.tiff:
|
if feature.tiff:
|
||||||
libs.append(feature.tiff)
|
libs.append(feature.tiff)
|
||||||
defs.append(("HAVE_LIBTIFF", None))
|
defs.append(("HAVE_LIBTIFF", None))
|
||||||
|
@ -710,6 +722,7 @@ class pil_build_ext(build_ext):
|
||||||
(feature.jpeg2000, "OPENJPEG (JPEG2000)",
|
(feature.jpeg2000, "OPENJPEG (JPEG2000)",
|
||||||
feature.openjpeg_version),
|
feature.openjpeg_version),
|
||||||
(feature.zlib, "ZLIB (PNG/ZIP)"),
|
(feature.zlib, "ZLIB (PNG/ZIP)"),
|
||||||
|
(feature.imagequant, "LIBIMAGEQUANT"),
|
||||||
(feature.tiff, "LIBTIFF"),
|
(feature.tiff, "LIBTIFF"),
|
||||||
(feature.freetype, "FREETYPE2"),
|
(feature.freetype, "FREETYPE2"),
|
||||||
(feature.lcms, "LITTLECMS2"),
|
(feature.lcms, "LITTLECMS2"),
|
||||||
|
|
|
@ -15,4 +15,4 @@ For more extensive info, see the windows build instructions `docs/build.rst`.
|
||||||
* `python test.py` runs the tests on Pillow in all the virtual envs.
|
* `python test.py` runs the tests on Pillow in all the virtual envs.
|
||||||
* Currently working with zlib, libjpeg, freetype, and libtiff on Python 2.7, 3.3, and 3.4, both 32 and 64 bit, on a local win7 pro machine and appveyor.com
|
* Currently working with zlib, libjpeg, freetype, and libtiff on Python 2.7, 3.3, and 3.4, both 32 and 64 bit, on a local win7 pro machine and appveyor.com
|
||||||
* Webp is built, not detected.
|
* Webp is built, not detected.
|
||||||
* LCMS and OpenJpeg are not building.
|
* LCMS, OpenJpeg and libimagequant are not building.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user