Merge branch 'readme' of https://github.com/wiredfool/Pillow into readme

This commit is contained in:
wiredfool 2013-04-09 12:42:33 -07:00
commit bb5f61fd80
31 changed files with 848 additions and 812 deletions

View File

@ -713,6 +713,16 @@ class Image:
if dither is None:
dither = FLOYDSTEINBERG
# fake a P-mode image, otherwise the transparency will get lost as there is
# currently no other way to convert transparency into an RGBA image
if self.mode == "L" and mode == "RGBA" and "transparency" in self.info:
from PIL import ImagePalette
self.mode = "P"
bytePalette = bytes([i//3 for i in range(768)])
self.palette = ImagePalette.raw("RGB", bytePalette)
self.palette.dirty = 1
self.load()
try:
im = self.im.convert(mode, dither)
except ValueError:

View File

@ -433,8 +433,9 @@ class Parser:
# @param im Image object.
# @param fp File object.
# @param tile Tile list.
# @param bufsize Optional buffer size
def _save(im, fp, tile):
def _save(im, fp, tile, bufsize=0):
"Helper to save image based on tile list"
im.load()
@ -442,7 +443,10 @@ def _save(im, fp, tile):
im.encoderconfig = ()
tile.sort(key=_tilesort)
# FIXME: make MAXBLOCK a configuration parameter
bufsize = max(MAXBLOCK, im.size[0] * 4) # see RawEncode.c
# It would be great if we could have the encoder specifiy what it needs
# But, it would need at least the image size in most cases. RawEncode is
# a tricky case.
bufsize = max(MAXBLOCK, bufsize, im.size[0] * 4) # see RawEncode.c
try:
fh = fp.fileno()
fp.flush()

View File

@ -17,7 +17,7 @@
from functools import reduce
class Filter:
class Filter(object):
pass
##

View File

@ -36,7 +36,7 @@ __version__ = "0.6"
import array, struct
from PIL import Image, ImageFile, _binary
from JpegPresets import presets
from PIL.JpegPresets import presets
i8 = _binary.i8
o8 = _binary.o8
@ -483,7 +483,7 @@ def _save(im, fp, filename):
elif subsampling == "keep":
if im.format != "JPEG":
raise ValueError("Cannot use 'keep' when original image is not a JPEG")
subsampling = get_sampling(im)
subsampling = get_sampling(im)
def validate_qtables(qtables):
if qtables is None:
@ -513,7 +513,7 @@ def _save(im, fp, filename):
else:
qtables[idx] = list(table)
return qtables
if qtables == "keep":
if im.format != "JPEG":
raise ValueError("Cannot use 'keep' when original image is not a JPEG")
@ -554,7 +554,15 @@ def _save(im, fp, filename):
info.get("exif", b"")
)
ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
# if we optimize, libjpeg needs a buffer big enough to hold the whole image in a shot.
# Guessing on the size, at im.size bytes. (raw pizel size is channels*size, this
# is a value that's been used in a django patch.
# https://github.com/jdriscoll/django-imagekit/issues/50
bufsize=0
if "optimize" in info:
bufsize = im.size[0]*im.size[1]
ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)], bufsize)
def _save_cjpeg(im, fp, filename):
# ALTERNATIVE: handle JPEGs via the IJG command line utilities.

View File

@ -70,7 +70,7 @@ _MODES = {
}
_simple_palette = re.compile(b'^\xff+\x00+$')
_simple_palette = re.compile(b'^\xff+\x00\xff*$')
# --------------------------------------------------------------------
# Support classes. Suitable for PNG and related formats like MNG etc.
@ -550,11 +550,14 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
if "transparency" in im.encoderinfo:
if im.mode == "P":
transparency = max(0, min(255, im.encoderinfo["transparency"]))
alpha = b'\xFF' * transparency + b'\0'
# limit to actual palette size
alpha_bytes = 2**bits
chunk(fp, b"tRNS", alpha[:alpha_bytes])
if isinstance(im.encoderinfo["transparency"], bytes):
chunk(fp, b"tRNS", im.encoderinfo["transparency"][:alpha_bytes])
else:
transparency = max(0, min(255, im.encoderinfo["transparency"]))
alpha = b'\xFF' * transparency + b'\0'
chunk(fp, b"tRNS", alpha[:alpha_bytes])
elif im.mode == "L":
transparency = max(0, min(65535, im.encoderinfo["transparency"]))
chunk(fp, b"tRNS", o16(transparency))

View File

@ -4,6 +4,7 @@ Pillow
.. Note:: Pillow >= 2.0.0 supports Python versions: 2.6, 2.7, 3.2, 3.3; Pillow < 2.0.0 supports Python versions: 2.4, 2.5, 2.6, 2.7.
.. image:: https://travis-ci.org/python-imaging/Pillow.png
:target: https://travis-ci.org/python-imaging/Pillow
Pillow is the "friendly" PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lundh and Contributors.
@ -22,6 +23,26 @@ Why a fork?
PIL is not setuptools compatible. Please see http://mail.python.org/pipermail/image-sig/2010-August/006480.html for a more detailed explanation. Also, PIL's current bi-yearly (or greater) release schedule is too infrequent to accomodate the large number and frequency of issues reported.
Porting
-------
Pillow is a functional dropin for the Python Imaging Library. To run
under Pillow, existing code needs to be modified to import the Imaging
modules from the PIL namespace instead of the global namespace.
Change::
import Image
to::
from PIL import Image
Note that if your code imports _imaging, that will also be hosted in the PIL namespace. The preferred method of importing _imaging is::
from PIL import Image
_imaging = Image.core
What about image code bugs?
---------------------------
@ -80,18 +101,18 @@ Current platform support for Pillow. Binary distributions are contributed for ea
.. [2] In some cases, x86 support may indicate 32-bit compilation on 64-bit architecture (vs. compilation on 32-bit hardware).
Installation
============
------------
If there is a binary package for your system, that is the preferred way of obtaining Pillow.
Building from Source
--------------------
+++++++++
Some of Pillow's features require external libraries.
* libjpeg provides JPEG functionality.
* Pillow has been tested with libjpev versions 6b and 8
* Pillow has been tested with libjpev versions 6b, 8, and 9
* zlib provides access to compressed PNGs
@ -105,7 +126,7 @@ Some of Pillow's features require external libraries.
* libwebp provides the Webp format.
If the prerequisites are installed in the standard library locations for your machine, no configuration shoule be required. If they are installed in a non-standard location, you may need to configure setuptools to use those locations. See [[url here]] for more information.
If the prerequisites are installed in the standard library locations for your machine, no configuration shoule be required. If they are installed in a non-standard location, you may need to configure setuptools to use those locations.
Once you have assembed the prerequisites, run:
@ -114,7 +135,7 @@ Once you have assembed the prerequisites, run:
$ pip install pillow
Platform Specific Instructions
------------------------------
+++++++++
Mac OSX
*******
@ -137,23 +158,23 @@ The library prerequisites are installed with::
# Ubuntu 12.04 LTS
sudo apt-get install libtiff4-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms1-dev libwebp-dev
##Undone## Debian library versions.
Windows
*******
Donations
---------
You can help fund Pillow development!
Porting
=======
.. Note:: New contributors: please add your name (and donation preference) here and send a pull request.
Pillow is a functional dropin for the Python Imaging Library. To run under Pillow, existing code needs to be modified to import the Imaging modules from the PIL namespace instead of the global namespace.
Change::
import Image
to::
from PIL import Image
Pillow is a volunteer effort led by Alex Clark. Any contributor interested in receiving donations may add their name (and donation preference) here.
+--------------------------------------+---------------------------------------+
| **Developer** | **Preference** |
+--------------------------------------+---------------------------------------+
| Alex Clark (fork author) | http://gittip.com/aclark4life |
+--------------------------------------+---------------------------------------+
@ -463,4 +484,3 @@ Python Imaging Library
http://mingw.org (compiler)
http://sebsauvage.net/python/mingw.html (build instructions)
http://sourceforge.net/projects/gnuwin32 (prebuilt libraries)

View File

@ -1202,7 +1202,7 @@ PySane_get_devices(PyObject *self, PyObject *args)
const SANE_Device *dev;
SANE_Status st;
PyObject *list;
int local_only, i;
int local_only = 0, i;
if (!PyArg_ParseTuple(args, "|i", &local_only))
{

BIN
Tests/images/l_trns.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -113,6 +113,13 @@ def test_optimize():
assert_image_equal(im1, im2)
assert_true(im1.bytes >= im2.bytes)
def test_optimize_large_buffer():
#https://github.com/python-imaging/Pillow/issues/148
f = tempfile('temp.jpg')
# this requires ~ 1.5x Image.MAXBLOCK
im = Image.new("RGB", (4096,4096), 0xff3333)
im.save(f, format="JPEG", optimize=True)
def test_progressive():
im1 = roundtrip(lena())
im2 = roundtrip(lena(), progressive=1)

View File

@ -128,6 +128,34 @@ def test_load_transparent_p():
# image has 124 uniqe qlpha values
assert_equal(len(im.split()[3].getcolors()), 124)
def test_save_p_transparent_palette():
in_file = "Tests/images/pil123p.png"
im = Image.open(in_file)
file = tempfile("temp.png")
assert_no_exception(lambda: im.save(file))
def test_save_p_single_transparency():
in_file = "Tests/images/p_trns_single.png"
im = Image.open(in_file)
file = tempfile("temp.png")
assert_no_exception(lambda: im.save(file))
def test_save_l_transparency():
in_file = "Tests/images/l_trns.png"
im = Image.open(in_file)
file = tempfile("temp.png")
assert_no_exception(lambda: im.save(file))
def test_save_rgb_single_transparency():
in_file = "Tests/images/caption_6_33_22.png"
im = Image.open(in_file)
file = tempfile("temp.png")
assert_no_exception(lambda: im.save(file))
def test_load_verify():
# Check open/load/verify exception (@PIL150)

View File

@ -126,7 +126,7 @@ def test_g4_write():
file = "Tests/images/lena_g4_500.tif"
orig = Image.open(file)
out = "temp.tif"
out = tempfile("temp.tif")
rot = orig.transpose(Image.ROTATE_90)
assert_equal(rot.size,(500,500))
rot.save(out)

View File

@ -2,6 +2,11 @@ from tester import *
from PIL import Image
try:
import _webp
except:
skip('webp support not installed')
def test_read():
""" Can we write a webp without error. Does it have the bits we expect?"""
@ -37,7 +42,18 @@ def test_write():
assert_no_exception(lambda: im.load())
assert_no_exception(lambda: im.getdata())
# If we're using the exact same version of webp, this test should pass.
# but it doesn't if the webp is generated on Ubuntu and tested on Fedora.
# generated with: dwebp -ppm temp.webp -o lena_webp_write.ppm
target = Image.open('Tests/images/lena_webp_write.ppm')
assert_image_equal(im, target)
#target = Image.open('Tests/images/lena_webp_write.ppm')
#assert_image_equal(im, target)
# This test asserts that the images are similar. If the average pixel difference
# between the two images is less than the epsilon value, then we're going to
# accept that it's a reasonable lossy version of the image. The included lena images
# for webp are showing ~16 on Ubuntu, the jpegs are showing ~18.
target = lena('RGB')
assert_image_similar(im, target, 20.0)

View File

@ -10,8 +10,8 @@ def test_toarray():
return ai["shape"], ai["typestr"], len(ai["data"])
# assert_equal(test("1"), ((100, 128), '|b1', 1600))
assert_equal(test("L"), ((100, 128), '|u1', 12800))
assert_equal(test("I"), ((100, 128), '<i4', 51200)) # FIXME: wrong?
assert_equal(test("F"), ((100, 128), '<f4', 51200)) # FIXME: wrong?
assert_equal(test("I"), ((100, 128), Image._ENDIAN + 'i4', 51200)) # FIXME: wrong?
assert_equal(test("F"), ((100, 128), Image._ENDIAN + 'f4', 51200)) # FIXME: wrong?
assert_equal(test("RGB"), ((100, 128, 3), '|u1', 38400))
assert_equal(test("RGBA"), ((100, 128, 4), '|u1', 51200))
assert_equal(test("RGBX"), ((100, 128, 4), '|u1', 51200))

View File

@ -18,6 +18,8 @@ def test_pack():
else:
return [ord(c) for c in im.tobytes("raw", rawmode)]
order = 1 if Image._ENDIAN == '<' else -1
assert_equal(pack("1", "1"), [128])
assert_equal(pack("1", "1;I"), [0])
assert_equal(pack("1", "1;R"), [1])
@ -25,9 +27,9 @@ def test_pack():
assert_equal(pack("L", "L"), [1])
assert_equal(pack("I", "I"), [1, 0, 0, 0])
assert_equal(pack("I", "I"), [1, 0, 0, 0][::order])
assert_equal(pack("F", "F"), [0, 0, 128, 63])
assert_equal(pack("F", "F"), [0, 0, 128, 63][::order])
assert_equal(pack("LA", "LA"), [1, 2])

View File

@ -84,10 +84,12 @@ def test_tobytes():
def tobytes(mode):
return Image.new(mode, (1, 1), 1).tobytes()
order = 1 if Image._ENDIAN == '<' else -1
assert_equal(tobytes("L"), b"\x01")
assert_equal(tobytes("I;16"), b"\x01\x00")
assert_equal(tobytes("I;16B"), b"\x00\x01")
assert_equal(tobytes("I"), b"\x01\x00\x00\x00")
assert_equal(tobytes("I"), b"\x01\x00\x00\x00"[::order])
def test_convert():

View File

@ -150,6 +150,26 @@ def assert_image_equal(a, b, msg=None):
else:
success()
def assert_image_similar(a, b, epsilon, msg=None):
epsilon = float(epsilon)
if a.mode != b.mode:
return failure(msg or "got mode %r, expected %r" % (a.mode, b.mode))
elif a.size != b.size:
return failure(msg or "got size %r, expected %r" % (a.size, b.size))
diff = 0
try:
ord(b'0')
for abyte,bbyte in zip(a.tobytes(),b.tobytes()):
diff += abs(ord(abyte)-ord(bbyte))
except:
for abyte,bbyte in zip(a.tobytes(),b.tobytes()):
diff += abs(abyte-bbyte)
ave_diff = float(diff)/(a.size[0]*a.size[1])
if epsilon < ave_diff:
failure(msg or "average pixel value difference %.4f > epsilon %.4f" %(ave_diff, epsilon))
else:
success()
def tempfile(template, *extra):
import os, sys
files = []

File diff suppressed because it is too large Load Diff

View File

@ -282,7 +282,7 @@ font_render(FontObject* self, PyObject* args)
{
int i, x, y;
Imaging im;
int index, error, ascender;
int index, error, ascender, descender;
int load_flags;
unsigned char *source;
FT_ULong ch;
@ -332,6 +332,7 @@ font_render(FontObject* self, PyObject* args)
int xx, x0, x1;
source = (unsigned char*) glyph->bitmap.buffer;
ascender = PIXEL(self->face->size->metrics.ascender);
descender = PIXEL(self->face->size->metrics.descender);
xx = x + glyph->bitmap_left;
x0 = 0;
x1 = glyph->bitmap.width;
@ -340,7 +341,7 @@ font_render(FontObject* self, PyObject* args)
if (xx + x1 > im->xsize)
x1 = im->xsize - xx;
for (y = 0; y < glyph->bitmap.rows; y++) {
int yy = y + ascender - glyph->bitmap_top;
int yy = y + ascender + descender - glyph->bitmap_top;
if (yy >= 0 && yy < im->ysize) {
/* blend this glyph into the buffer */
unsigned char *target = im->image8[yy] + xx;
@ -361,6 +362,7 @@ font_render(FontObject* self, PyObject* args)
int xx, x0, x1;
source = (unsigned char*) glyph->bitmap.buffer;
ascender = PIXEL(self->face->size->metrics.ascender);
descender = PIXEL(self->face->size->metrics.descender);
xx = x + glyph->bitmap_left;
x0 = 0;
x1 = glyph->bitmap.width;
@ -369,7 +371,7 @@ font_render(FontObject* self, PyObject* args)
if (xx + x1 > im->xsize)
x1 = im->xsize - xx;
for (y = 0; y < glyph->bitmap.rows; y++) {
int yy = y + ascender - glyph->bitmap_top;
int yy = y + ascender + descender - glyph->bitmap_top;
if (yy >= 0 && yy < im->ysize) {
/* blend this glyph into the buffer */
int i;

View File

@ -12,81 +12,85 @@
#include "Imaging.h"
typedef struct
{
UINT8 r;
UINT8 g;
UINT8 b;
UINT8 a;
} rgba8;
Imaging
ImagingAlphaComposite(Imaging imDst, Imaging imSrc)
{
Imaging imOut;
int x, y;
float dstR, dstG, dstB, dstA;
float srcR, srcG, srcB, srcA;
float outR, outG, outB, outA;
/* Check arguments */
if (!imDst || !imSrc ||
strcmp(imDst->mode, "RGBA") ||
imDst->type != IMAGING_TYPE_UINT8 ||
imDst->bands != 4)
return ImagingError_ModeError();
strcmp(imDst->mode, "RGBA") ||
imDst->type != IMAGING_TYPE_UINT8 ||
imDst->bands != 4)
return ImagingError_ModeError();
if (strcmp(imDst->mode, imSrc->mode) ||
imDst->type != imSrc->type ||
imDst->bands != imSrc->bands ||
imDst->xsize != imSrc->xsize ||
imDst->ysize != imSrc->ysize)
return ImagingError_Mismatch();
imDst->type != imSrc->type ||
imDst->bands != imSrc->bands ||
imDst->xsize != imSrc->xsize ||
imDst->ysize != imSrc->ysize)
return ImagingError_Mismatch();
imOut = ImagingNew(imDst->mode, imDst->xsize, imDst->ysize);
if (!imOut)
return NULL;
return NULL;
ImagingCopyInfo(imOut, imDst);
for (y = 0; y < imDst->ysize; y++) {
UINT8* dst = (UINT8*) imDst->image[y];
UINT8* src = (UINT8*) imSrc->image[y];
UINT8* out = (UINT8*) imOut->image[y];
rgba8* dst = (rgba8*) imDst->image[y];
rgba8* src = (rgba8*) imSrc->image[y];
rgba8* out = (rgba8*) imOut->image[y];
for (x = 0; x < imDst->linesize; x += 4) {
for (x = 0; x < imDst->xsize; x ++) {
dstR = dst[x + 0] / 255.0;
dstG = dst[x + 1] / 255.0;
dstB = dst[x + 2] / 255.0;
dstA = dst[x + 3] / 255.0;
if (src->a == 0) {
// Copy 4 bytes at once.
*out = *dst;
} else {
// Integer implementation with increased precision.
// Each variable has extra meaningful bits.
// Divisions are rounded.
srcR = src[x + 0] / 255.0;
srcG = src[x + 1] / 255.0;
srcB = src[x + 2] / 255.0;
srcA = src[x + 3] / 255.0;
// This code uses trick from Paste.c:
// (a + (2 << (n-1)) - 1) / ((2 << n)-1)
// almost equivalent to:
// tmp = a + (2 << (n-1)), ((tmp >> n) + tmp) >> n
if (dstA == 1.0) {
outR = srcR * srcA + dstR * (1.0 - srcA);
outG = srcG * srcA + dstG * (1.0 - srcA);
outB = srcB * srcA + dstB * (1.0 - srcA);
outA = 1.0;
} else if (srcA == 0.0) {
outR = dstR;
outG = dstG;
outB = dstB;
outA = dstA;
} else {
outA = srcA + dstA * (1.0 - srcA);
if (outA == 0.0) {
outR = 0.0;
outG = 0.0;
outB = 0.0;
} else {
outR = (srcR * srcA + dstR * dstA * (1.0 - srcA)) / outA;
outG = (srcG * srcA + dstG * dstA * (1.0 - srcA)) / outA;
outB = (srcB * srcA + dstB * dstA * (1.0 - srcA)) / outA;
}
}
UINT32 tmpr, tmpg, tmpb;
UINT16 blend = dst->a * (255 - src->a);
UINT16 outa255 = src->a * 255 + blend;
// There we use 7 bits for precision.
// We could use more, but we go beyond 32 bits.
UINT16 coef1 = src->a * 255 * 255 * 128 / outa255;
UINT16 coef2 = 255 * 128 - coef1;
out[x + 0] = (UINT8) (255.0 * outR + 0.5);
out[x + 1] = (UINT8) (255.0 * outG + 0.5);
out[x + 2] = (UINT8) (255.0 * outB + 0.5);
out[x + 3] = (UINT8) (255.0 * outA + 0.5);
#define SHIFTFORDIV255(a)\
((((a) >> 8) + a) >> 8)
}
tmpr = src->r * coef1 + dst->r * coef2 + (0x80 << 7);
out->r = SHIFTFORDIV255(tmpr) >> 7;
tmpg = src->g * coef1 + dst->g * coef2 + (0x80 << 7);
out->g = SHIFTFORDIV255(tmpg) >> 7;
tmpb = src->b * coef1 + dst->b * coef2 + (0x80 << 7);
out->b = SHIFTFORDIV255(tmpb) >> 7;
out->a = SHIFTFORDIV255(outa255 + 0x80);
}
dst++; src++; out++;
}
}

View File

@ -25,17 +25,15 @@
#include <memory.h>
#include <time.h>
#include "Quant.h"
#include "QuantTypes.h"
#include "QuantOctree.h"
#include "QuantDefines.h"
#include "QuantHash.h"
#include "QuantHeap.h"
#define NO_OUTPUT
typedef struct {
unsigned long scale;
uint32_t scale;
} PixelHashData;
typedef struct _PixelList {
@ -50,7 +48,7 @@ typedef struct _BoxNode {
PixelList *head[3],*tail[3];
int axis;
int volume;
unsigned long pixelCount;
uint32_t pixelCount;
} BoxNode;
#define _SQR(x) ((x)*(x))
@ -76,104 +74,92 @@ typedef struct _BoxNode {
((q)->c.g=(p)->c.g>>(s)), \
((q)->c.b=(p)->c.b>>(s))
static unsigned long
unshifted_pixel_hash(const HashTable h, const void *p)
static uint32_t
unshifted_pixel_hash(const HashTable *h, const Pixel pixel)
{
Pixel *pixel=(Pixel *)&p;
unsigned long hash=PIXEL_HASH(pixel->c.r,
pixel->c.g,
pixel->c.b);
return hash;
return PIXEL_HASH(pixel.c.r, pixel.c.g, pixel.c.b);
}
static int
unshifted_pixel_cmp(const HashTable h, const void *a, const void *b)
unshifted_pixel_cmp(const HashTable *h, const Pixel pixel1, const Pixel pixel2)
{
Pixel *pixel1=(Pixel *)&a;
Pixel *pixel2=(Pixel *)&b;
if (pixel1->c.r==pixel2->c.r) {
if (pixel1->c.g==pixel2->c.g) {
if (pixel1->c.b==pixel2->c.b) {
if (pixel1.c.r==pixel2.c.r) {
if (pixel1.c.g==pixel2.c.g) {
if (pixel1.c.b==pixel2.c.b) {
return 0;
} else {
return (int)(pixel1->c.b)-(int)(pixel2->c.b);
return (int)(pixel1.c.b)-(int)(pixel2.c.b);
}
} else {
return (int)(pixel1->c.g)-(int)(pixel2->c.g);
return (int)(pixel1.c.g)-(int)(pixel2.c.g);
}
} else {
return (int)(pixel1->c.r)-(int)(pixel2->c.r);
return (int)(pixel1.c.r)-(int)(pixel2.c.r);
}
}
static unsigned long
pixel_hash(const HashTable h,const void *p)
static uint32_t
pixel_hash(const HashTable *h,const Pixel pixel)
{
PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
Pixel *pixel=(Pixel *)&p;
unsigned long hash=PIXEL_HASH(pixel->c.r>>d->scale,
pixel->c.g>>d->scale,
pixel->c.b>>d->scale);
return hash;
return PIXEL_HASH(pixel.c.r>>d->scale, pixel.c.g>>d->scale, pixel.c.b>>d->scale);
}
static int
pixel_cmp(const HashTable h,const void *a,const void *b)
pixel_cmp(const HashTable *h,const Pixel pixel1, const Pixel pixel2)
{
PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
Pixel *pixel1=(Pixel *)&a;
Pixel *pixel2=(Pixel *)&b;
unsigned long A,B;
A=PIXEL_HASH(pixel1->c.r>>d->scale,
pixel1->c.g>>d->scale,
pixel1->c.b>>d->scale);
B=PIXEL_HASH(pixel2->c.r>>d->scale,
pixel2->c.g>>d->scale,
pixel2->c.b>>d->scale);
uint32_t A,B;
A=PIXEL_HASH(pixel1.c.r>>d->scale, pixel1.c.g>>d->scale, pixel1.c.b>>d->scale);
B=PIXEL_HASH(pixel2.c.r>>d->scale, pixel2.c.g>>d->scale, pixel2.c.b>>d->scale);
return (A==B)?0:((A<B)?-1:1);
}
static void
exists_count_func(const HashTable h, const void *key, void **val)
exists_count_func(const HashTable *h, const Pixel key, uint32_t *val)
{
*(unsigned long*)val+=1;
*val+=1;
}
static void
new_count_func(const HashTable h, const void *key, void **val)
new_count_func(const HashTable *h, const Pixel key, uint32_t *val)
{
*(unsigned long*)val=1;
*val=1;
}
static void
rehash_collide(HashTable h,
void **keyp,
void **valp,
void *newkey,
void *newval)
rehash_collide(const HashTable *h,
Pixel *keyp,
uint32_t *valp,
Pixel newkey,
uint32_t newval)
{
*valp = (void *)(((unsigned long) *valp) + ((unsigned long) newval));
*valp += newval;
}
/* %% */
static HashTable
create_pixel_hash(Pixel *pixelData,unsigned long nPixels)
static HashTable *
create_pixel_hash(Pixel *pixelData,uint32_t nPixels)
{
PixelHashData *d;
HashTable *hash;
unsigned long i;
unsigned long timer,timer2,timer3;
uint32_t i;
#ifndef NO_OUTPUT
uint32_t timer,timer2,timer3;
#endif
d=malloc(sizeof(PixelHashData));
if (!d) return NULL;
hash=hashtable_new(pixel_hash,pixel_cmp);
hashtable_set_user_data(hash,d);
d->scale=0;
#ifndef NO_OUTPUT
timer=timer3=clock();
#endif
for (i=0;i<nPixels;i++) {
if (!hashtable_insert_or_update_computed(hash,
(void *)pixelData[i].v,
pixelData[i],
new_count_func,
exists_count_func)) {;
}
@ -181,14 +167,14 @@ create_pixel_hash(Pixel *pixelData,unsigned long nPixels)
d->scale++;
#ifndef NO_OUTPUT
printf ("rehashing - new scale: %d\n",(int)d->scale);
#endif
timer2=clock();
hashtable_rehash_compute(hash,rehash_collide);
timer2=clock()-timer2;
#ifndef NO_OUTPUT
printf ("rehash took %f sec\n",timer2/(double)CLOCKS_PER_SEC);
#endif
hashtable_rehash_compute(hash,rehash_collide);
#ifndef NO_OUTPUT
timer2=clock()-timer2;
printf ("rehash took %f sec\n",timer2/(double)CLOCKS_PER_SEC);
timer+=timer2;
#endif
}
}
#ifndef NO_OUTPUT
@ -201,7 +187,7 @@ create_pixel_hash(Pixel *pixelData,unsigned long nPixels)
}
static void
destroy_pixel_hash(HashTable hash)
destroy_pixel_hash(HashTable *hash)
{
PixelHashData *d=(PixelHashData *)hashtable_get_user_data(hash);
if (d) free(d);
@ -237,17 +223,15 @@ compute_box_volume(BoxNode *b)
}
static void
hash_to_list(HashTable h, const void *key, const void *val, void *u)
hash_to_list(const HashTable *h, const Pixel pixel, const uint32_t count, void *u)
{
PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
PixelList **pl=(PixelList **)u;
PixelList *p;
Pixel *pixel=(Pixel *)&key;
int i;
Pixel q;
int count=(unsigned long) val;
PIXEL_SCALE(pixel,&q,d->scale);
PIXEL_SCALE(&pixel,&q,d->scale);
p=malloc(sizeof(PixelList));
if (!p) return;
@ -327,7 +311,7 @@ test_sorted(PixelList *pl[3])
#endif
static int
box_heap_cmp(const Heap h, const void *A, const void *B)
box_heap_cmp(const Heap *h, const void *A, const void *B)
{
BoxNode *a=(BoxNode *)A;
BoxNode *b=(BoxNode *)B;
@ -341,11 +325,11 @@ splitlists(PixelList *h[3],
PixelList *t[3],
PixelList *nh[2][3],
PixelList *nt[2][3],
unsigned long nCount[2],
uint32_t nCount[2],
int axis,
unsigned long pixelCount)
uint32_t pixelCount)
{
unsigned long left;
uint32_t left;
PixelList *l,*r,*c,*n;
int i;
@ -476,7 +460,7 @@ split(BoxNode *node)
int i;
PixelList *heads[2][3];
PixelList *tails[2][3];
unsigned long newCounts[2];
uint32_t newCounts[2];
BoxNode *left,*right;
rh=node->head[0]->p.c.r;
@ -618,13 +602,13 @@ split(BoxNode *node)
static BoxNode *
median_cut(PixelList *hl[3],
unsigned long imPixelCount,
uint32_t imPixelCount,
int nPixels)
{
PixelList *tl[3];
int i;
BoxNode *root;
Heap h;
Heap* h;
BoxNode *thisNode;
h=ImagingQuantHeapNew(box_heap_cmp);
@ -701,7 +685,7 @@ checkContained(BoxNode *n,Pixel *pp)
#endif
static int
annotate_hash_table(BoxNode *n,HashTable h,unsigned long *box)
annotate_hash_table(BoxNode *n,HashTable *h,uint32_t *box)
{
PixelList *p;
PixelHashData *d=(PixelHashData *)hashtable_get_user_data(h);
@ -717,7 +701,7 @@ annotate_hash_table(BoxNode *n,HashTable h,unsigned long *box)
}
for (p=n->head[0];p;p=p->next[0]) {
PIXEL_UNSCALE(&(p->p),&q,d->scale);
if (!hashtable_insert(h,(void *)q.v,(void *)*box)) {
if (!hashtable_insert(h,q,*box)) {
#ifndef NO_OUTPUT
printf ("hashtable insert failed\n");
#endif
@ -731,20 +715,20 @@ annotate_hash_table(BoxNode *n,HashTable h,unsigned long *box)
static int
_sort_ulong_ptr_keys(const void *a, const void *b)
{
unsigned long A=**(unsigned long **)a;
unsigned long B=**(unsigned long **)b;
uint32_t A=**(uint32_t **)a;
uint32_t B=**(uint32_t **)b;
return (A==B)?0:((A<B)?-1:+1);
}
static int
resort_distance_tables(unsigned long *avgDist,
unsigned long **avgDistSortKey,
resort_distance_tables(uint32_t *avgDist,
uint32_t **avgDistSortKey,
Pixel *p,
unsigned long nEntries)
uint32_t nEntries)
{
unsigned long i,j,k;
unsigned long **skRow;
unsigned long *skElt;
uint32_t i,j,k;
uint32_t **skRow;
uint32_t *skElt;
for (i=0;i<nEntries;i++) {
avgDist[i*nEntries+i]=0;
@ -767,12 +751,12 @@ resort_distance_tables(unsigned long *avgDist,
}
static int
build_distance_tables(unsigned long *avgDist,
unsigned long **avgDistSortKey,
build_distance_tables(uint32_t *avgDist,
uint32_t **avgDistSortKey,
Pixel *p,
unsigned long nEntries)
uint32_t nEntries)
{
unsigned long i,j;
uint32_t i,j;
for (i=0;i<nEntries;i++) {
avgDist[i*nEntries+i]=0;
@ -787,7 +771,7 @@ build_distance_tables(unsigned long *avgDist,
for (i=0;i<nEntries;i++) {
qsort(avgDistSortKey+i*nEntries,
nEntries,
sizeof(unsigned long *),
sizeof(uint32_t *),
_sort_ulong_ptr_keys);
}
return 1;
@ -795,23 +779,23 @@ build_distance_tables(unsigned long *avgDist,
static int
map_image_pixels(Pixel *pixelData,
unsigned long nPixels,
uint32_t nPixels,
Pixel *paletteData,
unsigned long nPaletteEntries,
unsigned long *avgDist,
unsigned long **avgDistSortKey,
unsigned long *pixelArray)
uint32_t nPaletteEntries,
uint32_t *avgDist,
uint32_t **avgDistSortKey,
uint32_t *pixelArray)
{
unsigned long *aD,**aDSK;
unsigned long idx;
unsigned long i,j;
unsigned long bestdist,bestmatch,dist;
unsigned long initialdist;
HashTable h2;
uint32_t *aD,**aDSK;
uint32_t idx;
uint32_t i,j;
uint32_t bestdist,bestmatch,dist;
uint32_t initialdist;
HashTable *h2;
h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
for (i=0;i<nPixels;i++) {
if (!hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&bestmatch)) {
if (!hashtable_lookup(h2,pixelData[i],&bestmatch)) {
bestmatch=0;
initialdist=_DISTSQR(paletteData+bestmatch,pixelData+i);
bestdist=initialdist;
@ -830,7 +814,7 @@ map_image_pixels(Pixel *pixelData,
break;
}
}
hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch);
hashtable_insert(h2,pixelData[i],bestmatch);
}
pixelArray[i]=bestmatch;
}
@ -841,26 +825,26 @@ map_image_pixels(Pixel *pixelData,
static int
map_image_pixels_from_quantized_pixels(
Pixel *pixelData,
unsigned long nPixels,
uint32_t nPixels,
Pixel *paletteData,
unsigned long nPaletteEntries,
unsigned long *avgDist,
unsigned long **avgDistSortKey,
unsigned long *pixelArray,
unsigned long *avg[3],
unsigned long *count)
uint32_t nPaletteEntries,
uint32_t *avgDist,
uint32_t **avgDistSortKey,
uint32_t *pixelArray,
uint32_t *avg[3],
uint32_t *count)
{
unsigned long *aD,**aDSK;
unsigned long idx;
unsigned long i,j;
unsigned long bestdist,bestmatch,dist;
unsigned long initialdist;
HashTable h2;
uint32_t *aD,**aDSK;
uint32_t idx;
uint32_t i,j;
uint32_t bestdist,bestmatch,dist;
uint32_t initialdist;
HashTable *h2;
int changes=0;
h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
for (i=0;i<nPixels;i++) {
if (!hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&bestmatch)) {
if (!hashtable_lookup(h2,pixelData[i],&bestmatch)) {
bestmatch=pixelArray[i];
initialdist=_DISTSQR(paletteData+bestmatch,pixelData+i);
bestdist=initialdist;
@ -879,7 +863,7 @@ map_image_pixels_from_quantized_pixels(
break;
}
}
hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch);
hashtable_insert(h2,pixelData[i],bestmatch);
}
if (pixelArray[i]!=bestmatch) {
changes++;
@ -901,29 +885,29 @@ map_image_pixels_from_quantized_pixels(
static int
map_image_pixels_from_median_box(
Pixel *pixelData,
unsigned long nPixels,
uint32_t nPixels,
Pixel *paletteData,
unsigned long nPaletteEntries,
uint32_t nPaletteEntries,
HashTable *medianBoxHash,
unsigned long *avgDist,
unsigned long **avgDistSortKey,
unsigned long *pixelArray)
uint32_t *avgDist,
uint32_t **avgDistSortKey,
uint32_t *pixelArray)
{
unsigned long *aD,**aDSK;
unsigned long idx;
unsigned long i,j;
unsigned long bestdist,bestmatch,dist;
unsigned long initialdist;
HashTable h2;
unsigned long pixelVal;
uint32_t *aD,**aDSK;
uint32_t idx;
uint32_t i,j;
uint32_t bestdist,bestmatch,dist;
uint32_t initialdist;
HashTable *h2;
uint32_t pixelVal;
h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
for (i=0;i<nPixels;i++) {
if (hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&pixelVal)) {
if (hashtable_lookup(h2,pixelData[i],&pixelVal)) {
pixelArray[i]=pixelVal;
continue;
}
if (!hashtable_lookup(medianBoxHash,(void *)pixelData[i].v,(void **)&pixelVal)) {
if (!hashtable_lookup(medianBoxHash,pixelData[i],&pixelVal)) {
#ifndef NO_OUTPUT
printf ("pixel lookup failed\n");
#endif
@ -948,7 +932,7 @@ map_image_pixels_from_median_box(
}
}
pixelArray[i]=bestmatch;
hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch);
hashtable_insert(h2,pixelData[i],bestmatch);
}
hashtable_free(h2);
return 1;
@ -957,27 +941,27 @@ map_image_pixels_from_median_box(
static int
compute_palette_from_median_cut(
Pixel *pixelData,
unsigned long nPixels,
HashTable medianBoxHash,
uint32_t nPixels,
HashTable *medianBoxHash,
Pixel **palette,
unsigned long nPaletteEntries)
uint32_t nPaletteEntries)
{
unsigned long i;
unsigned long paletteEntry;
uint32_t i;
uint32_t paletteEntry;
Pixel *p;
unsigned long *avg[3];
unsigned long *count;
uint32_t *avg[3];
uint32_t *count;
*palette=NULL;
if (!(count=malloc(sizeof(unsigned long)*nPaletteEntries))) {
if (!(count=malloc(sizeof(uint32_t)*nPaletteEntries))) {
return 0;
}
memset(count,0,sizeof(unsigned long)*nPaletteEntries);
memset(count,0,sizeof(uint32_t)*nPaletteEntries);
for(i=0;i<3;i++) {
avg[i]=NULL;
}
for(i=0;i<3;i++) {
if (!(avg[i]=malloc(sizeof(unsigned long)*nPaletteEntries))) {
if (!(avg[i]=malloc(sizeof(uint32_t)*nPaletteEntries))) {
for(i=0;i<3;i++) {
if (avg[i]) free (avg[i]);
}
@ -986,7 +970,7 @@ compute_palette_from_median_cut(
}
}
for(i=0;i<3;i++) {
memset(avg[i],0,sizeof(unsigned long)*nPaletteEntries);
memset(avg[i],0,sizeof(uint32_t)*nPaletteEntries);
}
for (i=0;i<nPixels;i++) {
#ifdef TEST_SPLIT_INTEGRITY
@ -998,7 +982,7 @@ compute_palette_from_median_cut(
return 0;
}
#endif
if (!hashtable_lookup(medianBoxHash,(void *)pixelData[i].v,(void **)&paletteEntry)) {
if (!hashtable_lookup(medianBoxHash,pixelData[i],&paletteEntry)) {
#ifndef NO_OUTPUT
printf ("pixel lookup failed\n");
#endif
@ -1039,11 +1023,11 @@ compute_palette_from_median_cut(
static int
recompute_palette_from_averages(
Pixel *palette,
unsigned long nPaletteEntries,
unsigned long *avg[3],
unsigned long *count)
uint32_t nPaletteEntries,
uint32_t *avg[3],
uint32_t *count)
{
unsigned long i;
uint32_t i;
for (i=0;i<nPaletteEntries;i++) {
palette[i].c.r=(int)(.5+(double)avg[0][i]/(double)count[i]);
@ -1056,18 +1040,18 @@ recompute_palette_from_averages(
static int
compute_palette_from_quantized_pixels(
Pixel *pixelData,
unsigned long nPixels,
uint32_t nPixels,
Pixel *palette,
unsigned long nPaletteEntries,
unsigned long *avg[3],
unsigned long *count,
unsigned long *qp)
uint32_t nPaletteEntries,
uint32_t *avg[3],
uint32_t *count,
uint32_t *qp)
{
unsigned long i;
uint32_t i;
memset(count,0,sizeof(unsigned long)*nPaletteEntries);
memset(count,0,sizeof(uint32_t)*nPaletteEntries);
for(i=0;i<3;i++) {
memset(avg[i],0,sizeof(unsigned long)*nPaletteEntries);
memset(avg[i],0,sizeof(uint32_t)*nPaletteEntries);
}
for (i=0;i<nPixels;i++) {
if (qp[i]>=nPaletteEntries) {
@ -1091,35 +1075,35 @@ compute_palette_from_quantized_pixels(
static int
k_means(Pixel *pixelData,
unsigned long nPixels,
uint32_t nPixels,
Pixel *paletteData,
unsigned long nPaletteEntries,
unsigned long *qp,
uint32_t nPaletteEntries,
uint32_t *qp,
int threshold)
{
unsigned long *avg[3];
unsigned long *count;
unsigned long i;
unsigned long *avgDist;
unsigned long **avgDistSortKey;
uint32_t *avg[3];
uint32_t *count;
uint32_t i;
uint32_t *avgDist;
uint32_t **avgDistSortKey;
int changes;
int built=0;
if (!(count=malloc(sizeof(unsigned long)*nPaletteEntries))) {
if (!(count=malloc(sizeof(uint32_t)*nPaletteEntries))) {
return 0;
}
for(i=0;i<3;i++) {
avg[i]=NULL;
}
for(i=0;i<3;i++) {
if (!(avg[i]=malloc(sizeof(unsigned long)*nPaletteEntries))) {
if (!(avg[i]=malloc(sizeof(uint32_t)*nPaletteEntries))) {
goto error_1;
}
}
avgDist=malloc(sizeof(unsigned long)*nPaletteEntries*nPaletteEntries);
avgDist=malloc(sizeof(uint32_t)*nPaletteEntries*nPaletteEntries);
if (!avgDist) { goto error_1; }
avgDistSortKey=malloc(sizeof(unsigned long *)*nPaletteEntries*nPaletteEntries);
avgDistSortKey=malloc(sizeof(uint32_t *)*nPaletteEntries*nPaletteEntries);
if (!avgDistSortKey) { goto error_2; }
#ifndef NO_OUTPUT
@ -1172,26 +1156,26 @@ error_1:
int
quantize(Pixel *pixelData,
unsigned long nPixels,
unsigned long nQuantPixels,
uint32_t nPixels,
uint32_t nQuantPixels,
Pixel **palette,
unsigned long *paletteLength,
unsigned long **quantizedPixels,
uint32_t *paletteLength,
uint32_t **quantizedPixels,
int kmeans)
{
PixelList *hl[3];
HashTable h;
HashTable *h;
BoxNode *root;
unsigned long i;
unsigned long *qp;
unsigned long nPaletteEntries;
uint32_t i;
uint32_t *qp;
uint32_t nPaletteEntries;
unsigned long *avgDist;
unsigned long **avgDistSortKey;
uint32_t *avgDist;
uint32_t **avgDistSortKey;
Pixel *p;
#ifndef NO_OUTPUT
unsigned long timer,timer2;
uint32_t timer,timer2;
#endif
#ifndef NO_OUTPUT
@ -1266,13 +1250,13 @@ quantize(Pixel *pixelData,
free_box_tree(root);
root=NULL;
qp=malloc(sizeof(unsigned long)*nPixels);
qp=malloc(sizeof(uint32_t)*nPixels);
if (!qp) { goto error_4; }
avgDist=malloc(sizeof(unsigned long)*nPaletteEntries*nPaletteEntries);
avgDist=malloc(sizeof(uint32_t)*nPaletteEntries*nPaletteEntries);
if (!avgDist) { goto error_5; }
avgDistSortKey=malloc(sizeof(unsigned long *)*nPaletteEntries*nPaletteEntries);
avgDistSortKey=malloc(sizeof(uint32_t *)*nPaletteEntries*nPaletteEntries);
if (!avgDistSortKey) { goto error_6; }
if (!build_distance_tables(avgDist,avgDistSortKey,p,nPaletteEntries)) {
@ -1286,12 +1270,12 @@ quantize(Pixel *pixelData,
#ifdef TEST_NEAREST_NEIGHBOUR
#include <math.h>
{
unsigned long bestmatch,bestdist,dist;
HashTable h2;
uint32_t bestmatch,bestdist,dist;
HashTable *h2;
printf ("nearest neighbour search (full search)..."); fflush(stdout); timer=clock();
h2=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
for (i=0;i<nPixels;i++) {
if (hashtable_lookup(h2,(void *)pixelData[i].v,(void **)&paletteEntry)) {
if (hashtable_lookup(h2,pixelData[i],&paletteEntry)) {
bestmatch=paletteEntry;
} else {
bestmatch=0;
@ -1312,7 +1296,7 @@ quantize(Pixel *pixelData,
bestmatch=j;
}
}
hashtable_insert(h2,(void *)pixelData[i].v,(void *)bestmatch);
hashtable_insert(h2,pixelData[i],bestmatch);
}
if (qp[i]!=bestmatch ) {
printf ("discrepancy in matching algorithms pixel %d [%d %d] %f %f\n",
@ -1375,53 +1359,52 @@ error_0:
typedef struct {
Pixel new;
Pixel furthest;
unsigned long furthestDistance;
uint32_t furthestDistance;
int secondPixel;
} DistanceData;
static void
compute_distances(const HashTable h, const void *key, void **val, void *u)
compute_distances(const HashTable *h, const Pixel pixel, uint32_t *dist, void *u)
{
DistanceData *data=(DistanceData *)u;
Pixel *pixel=(Pixel *)&key;
unsigned long oldDist=*(unsigned long *)val;
unsigned long newDist;
newDist=_DISTSQR(&(data->new),pixel);
uint32_t oldDist=*dist;
uint32_t newDist;
newDist=_DISTSQR(&(data->new),&pixel);
if (data->secondPixel || newDist<oldDist) {
*(unsigned long *)val=newDist;
*dist=newDist;
oldDist=newDist;
}
if (oldDist>data->furthestDistance) {
data->furthestDistance=oldDist;
data->furthest.v=pixel->v;
data->furthest.v=pixel.v;
}
}
int
quantize2(Pixel *pixelData,
unsigned long nPixels,
unsigned long nQuantPixels,
uint32_t nPixels,
uint32_t nQuantPixels,
Pixel **palette,
unsigned long *paletteLength,
unsigned long **quantizedPixels,
uint32_t *paletteLength,
uint32_t **quantizedPixels,
int kmeans)
{
HashTable h;
unsigned long i;
unsigned long mean[3];
HashTable *h;
uint32_t i;
uint32_t mean[3];
Pixel *p;
DistanceData data;
unsigned long *qp;
unsigned long *avgDist;
unsigned long **avgDistSortKey;
uint32_t *qp;
uint32_t *avgDist;
uint32_t **avgDistSortKey;
p=malloc(sizeof(Pixel)*nQuantPixels);
if (!p) return 0;
mean[0]=mean[1]=mean[2]=0;
h=hashtable_new(unshifted_pixel_hash,unshifted_pixel_cmp);
for (i=0;i<nPixels;i++) {
hashtable_insert(h,(void *)pixelData[i].v,(void *)0xffffffff);
hashtable_insert(h,pixelData[i],0xffffffff);
mean[0]+=pixelData[i].c.r;
mean[1]+=pixelData[i].c.g;
mean[2]+=pixelData[i].c.b;
@ -1438,13 +1421,13 @@ quantize2(Pixel *pixelData,
}
hashtable_free(h);
qp=malloc(sizeof(unsigned long)*nPixels);
qp=malloc(sizeof(uint32_t)*nPixels);
if (!qp) { goto error_1; }
avgDist=malloc(sizeof(unsigned long)*nQuantPixels*nQuantPixels);
avgDist=malloc(sizeof(uint32_t)*nQuantPixels*nQuantPixels);
if (!avgDist) { goto error_2; }
avgDistSortKey=malloc(sizeof(unsigned long *)*nQuantPixels*nQuantPixels);
avgDistSortKey=malloc(sizeof(uint32_t *)*nQuantPixels*nQuantPixels);
if (!avgDistSortKey) { goto error_3; }
if (!build_distance_tables(avgDist,avgDistSortKey,p,nQuantPixels)) {
@ -1482,9 +1465,9 @@ ImagingQuantize(Imaging im, int colors, int mode, int kmeans)
UINT8* pp;
Pixel* p;
Pixel* palette;
unsigned long paletteLength;
uint32_t paletteLength;
int result;
unsigned long* newData;
uint32_t* newData;
Imaging imOut;
int withAlpha = 0;
ImagingSectionCookie cookie;

View File

@ -1,40 +0,0 @@
/*
* The Python Imaging Library
* $Id$
*
* image quantizer
*
* Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
*
* See the README file for information on usage and redistribution.
*/
#ifndef __QUANT_H__
#define __QUANT_H__
typedef union {
struct {
unsigned char r,g,b,a;
} c;
struct {
unsigned char v[4];
} a;
unsigned long v;
} Pixel;
int quantize(Pixel *,
unsigned long,
unsigned long,
Pixel **,
unsigned long *,
unsigned long **,
int);
int quantize2(Pixel *,
unsigned long,
unsigned long,
Pixel **,
unsigned long *,
unsigned long **,
int);
#endif

View File

@ -1,25 +0,0 @@
/*
* The Python Imaging Library
* $Id$
*
* image quantizer
*
* Written by Toby J Sargeant <tjs@longford.cs.monash.edu.au>.
*
* See the README file for information on usage and redistribution.
*/
#ifndef __DEFINES_H__
#define __DEFINES_H__
#if 0
void *newMalloc(size_t,const char *,const char *,int);
void newFree(void *,const char *,const char *,int);
void print_malloc_stats();
#define malloc(x) newMalloc(x,__FILE__,__FUNCTION__,__LINE__)
#define free(x) newFree(x,__FILE__,__FUNCTION__,__LINE__)
#endif
#endif

View File

@ -22,35 +22,35 @@
#include <math.h>
#include "QuantHash.h"
#include "QuantDefines.h"
typedef struct _IntHashNode {
struct _IntHashNode *next;
void *key,*value;
} IntHashNode;
typedef struct _HashNode {
struct _HashNode *next;
HashKey_t key;
HashVal_t value;
} HashNode;
typedef struct _IntHashTable {
IntHashNode **table;
unsigned long length;
unsigned long count;
typedef struct _HashTable {
HashNode **table;
uint32_t length;
uint32_t count;
HashFunc hashFunc;
HashCmpFunc cmpFunc;
DestroyFunc keyDestroyFunc;
DestroyFunc valDestroyFunc;
KeyDestroyFunc keyDestroyFunc;
ValDestroyFunc valDestroyFunc;
void *userData;
} IntHashTable;
} HashTable;
#define MIN_LENGTH 11
#define RESIZE_FACTOR 3
static int _hashtable_insert_node(IntHashTable *,IntHashNode *,int,int,CollisionFunc);
static int _hashtable_insert_node(HashTable *,HashNode *,int,int,CollisionFunc);
#if 0
static int _hashtable_test(IntHashTable *);
static int _hashtable_test(HashTable *);
#endif
HashTable hashtable_new(HashFunc hf,HashCmpFunc cf) {
IntHashTable *h;
h=malloc(sizeof(IntHashTable));
HashTable *hashtable_new(HashFunc hf,HashCmpFunc cf) {
HashTable *h;
h=malloc(sizeof(HashTable));
if (!h) { return NULL; }
h->hashFunc=hf;
h->cmpFunc=cf;
@ -59,25 +59,24 @@ HashTable hashtable_new(HashFunc hf,HashCmpFunc cf) {
h->length=MIN_LENGTH;
h->count=0;
h->userData=NULL;
h->table=malloc(sizeof(IntHashNode *)*h->length);
h->table=malloc(sizeof(HashNode *)*h->length);
if (!h->table) { free(h); return NULL; }
memset (h->table,0,sizeof(IntHashNode *)*h->length);
return (HashTable)h;
memset (h->table,0,sizeof(HashNode *)*h->length);
return h;
}
static void _hashtable_destroy(HashTable H,const void *key,const void *val,void *u) {
IntHashTable *h=(IntHashTable *)H;
if (h->keyDestroyFunc&&key) {
h->keyDestroyFunc((HashTable)h,(void *)key);
static void _hashtable_destroy(const HashTable *h,const HashKey_t key,const HashVal_t val,void *u) {
if (h->keyDestroyFunc) {
h->keyDestroyFunc(h,key);
}
if (h->valDestroyFunc&&val) {
h->valDestroyFunc((HashTable)h,(void *)val);
if (h->valDestroyFunc) {
h->valDestroyFunc(h,val);
}
}
static unsigned long _findPrime(unsigned long start,int dir) {
static uint32_t _findPrime(uint32_t start,int dir) {
static int unit[]={0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0};
unsigned long t;
uint32_t t;
while (start>1) {
if (!unit[start&0x0f]) {
start+=dir;
@ -94,22 +93,20 @@ static unsigned long _findPrime(unsigned long start,int dir) {
return start;
}
static void _hashtable_rehash(IntHashTable *h,
CollisionFunc cf,
unsigned long newSize) {
IntHashNode **oldTable=h->table;
unsigned long i;
IntHashNode *n,*nn;
unsigned long oldSize;
static void _hashtable_rehash(HashTable *h,CollisionFunc cf,uint32_t newSize) {
HashNode **oldTable=h->table;
uint32_t i;
HashNode *n,*nn;
uint32_t oldSize;
oldSize=h->length;
h->table=malloc(sizeof(IntHashNode *)*newSize);
h->table=malloc(sizeof(HashNode *)*newSize);
if (!h->table) {
h->table=oldTable;
return;
}
h->length=newSize;
h->count=0;
memset (h->table,0,sizeof(IntHashNode *)*h->length);
memset (h->table,0,sizeof(HashNode *)*h->length);
for (i=0;i<oldSize;i++) {
for (n=oldTable[i];n;n=nn) {
nn=n->next;
@ -119,9 +116,9 @@ static void _hashtable_rehash(IntHashTable *h,
free(oldTable);
}
static void _hashtable_resize(IntHashTable *h) {
unsigned long newSize;
unsigned long oldSize;
static void _hashtable_resize(HashTable *h) {
uint32_t newSize;
uint32_t oldSize;
oldSize=h->length;
newSize=oldSize;
if (h->count*RESIZE_FACTOR<h->length) {
@ -136,13 +133,13 @@ static void _hashtable_resize(IntHashTable *h) {
}
#if 0
static int _hashtable_test(IntHashTable *h) {
unsigned long i;
static int _hashtable_test(HashTable *h) {
uint32_t i;
int j;
IntHashNode *n;
HashNode *n;
for (i=0;i<h->length;i++) {
for (n=h->table[i];n&&n->next;n=n->next) {
j=h->cmpFunc((HashTable)h,n->key,n->next->key);
j=h->cmpFunc(h,n->key,n->next->key);
printf ("%c",j?(j<0?'-':'+'):'=');
}
printf ("\n");
@ -151,26 +148,26 @@ static int _hashtable_test(IntHashTable *h) {
}
#endif
static int _hashtable_insert_node(IntHashTable *h,IntHashNode *node,int resize,int update,CollisionFunc cf) {
unsigned long hash=h->hashFunc((HashTable)h,node->key)%h->length;
IntHashNode **n,*nv;
static int _hashtable_insert_node(HashTable *h,HashNode *node,int resize,int update,CollisionFunc cf) {
uint32_t hash=h->hashFunc(h,node->key)%h->length;
HashNode **n,*nv;
int i;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
nv=*n;
i=h->cmpFunc((HashTable)h,nv->key,node->key);
i=h->cmpFunc(h,nv->key,node->key);
if (!i) {
if (cf) {
nv->key=node->key;
cf((HashTable)h,&(nv->key),&(nv->value),node->key,node->value);
cf(h,&(nv->key),&(nv->value),node->key,node->value);
free(node);
return 1;
} else {
if (h->valDestroyFunc) {
h->valDestroyFunc((HashTable)h,nv->value);
h->valDestroyFunc(h,nv->value);
}
if (h->keyDestroyFunc) {
h->keyDestroyFunc((HashTable)h,nv->key);
h->keyDestroyFunc(h,nv->key);
}
nv->key=node->key;
nv->value=node->value;
@ -192,17 +189,17 @@ static int _hashtable_insert_node(IntHashTable *h,IntHashNode *node,int resize,i
}
}
static int _hashtable_insert(IntHashTable *h,void *key,void *val,int resize,int update) {
IntHashNode **n,*nv;
IntHashNode *t;
static int _hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val,int resize,int update) {
HashNode **n,*nv;
HashNode *t;
int i;
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
uint32_t hash=h->hashFunc(h,key)%h->length;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
nv=*n;
i=h->cmpFunc((HashTable)h,nv->key,key);
i=h->cmpFunc(h,nv->key,key);
if (!i) {
if (h->valDestroyFunc) { h->valDestroyFunc((HashTable)h,nv->value); }
if (h->valDestroyFunc) { h->valDestroyFunc(h,nv->value); }
nv->value=val;
return 1;
} else if (i>0) {
@ -210,7 +207,7 @@ static int _hashtable_insert(IntHashTable *h,void *key,void *val,int resize,int
}
}
if (!update) {
t=malloc(sizeof(IntHashNode));
t=malloc(sizeof(HashNode));
if (!t) return 0;
t->next=*n;
*n=t;
@ -224,15 +221,15 @@ static int _hashtable_insert(IntHashTable *h,void *key,void *val,int resize,int
}
}
static int _hashtable_lookup_or_insert(IntHashTable *h,void *key,void **retVal,void *newVal,int resize) {
IntHashNode **n,*nv;
IntHashNode *t;
static int _hashtable_lookup_or_insert(HashTable *h,HashKey_t key,HashVal_t *retVal,HashVal_t newVal,int resize) {
HashNode **n,*nv;
HashNode *t;
int i;
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
uint32_t hash=h->hashFunc(h,key)%h->length;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
nv=*n;
i=h->cmpFunc((HashTable)h,nv->key,key);
i=h->cmpFunc(h,nv->key,key);
if (!i) {
*retVal=nv->value;
return 1;
@ -240,7 +237,7 @@ static int _hashtable_lookup_or_insert(IntHashTable *h,void *key,void **retVal,v
break;
}
}
t=malloc(sizeof(IntHashNode));
t=malloc(sizeof(HashNode));
if (!t) return 0;
t->next=*n;
*n=t;
@ -252,26 +249,25 @@ static int _hashtable_lookup_or_insert(IntHashTable *h,void *key,void **retVal,v
return 1;
}
int hashtable_insert_or_update_computed(HashTable H,
void *key,
int hashtable_insert_or_update_computed(HashTable *h,
HashKey_t key,
ComputeFunc newFunc,
ComputeFunc existsFunc) {
IntHashTable *h=(IntHashTable *)H;
IntHashNode **n,*nv;
IntHashNode *t;
HashNode **n,*nv;
HashNode *t;
int i;
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
uint32_t hash=h->hashFunc(h,key)%h->length;
for (n=&(h->table[hash]);*n;n=&((*n)->next)) {
nv=*n;
i=h->cmpFunc((HashTable)h,nv->key,key);
i=h->cmpFunc(h,nv->key,key);
if (!i) {
void *old=nv->value;
HashVal_t old=nv->value;
if (existsFunc) {
existsFunc(H,nv->key,&(nv->value));
existsFunc(h,nv->key,&(nv->value));
if (nv->value!=old) {
if (h->valDestroyFunc) {
h->valDestroyFunc((HashTable)h,old);
h->valDestroyFunc(h,old);
}
}
} else {
@ -282,13 +278,13 @@ int hashtable_insert_or_update_computed(HashTable H,
break;
}
}
t=malloc(sizeof(IntHashNode));
t=malloc(sizeof(HashNode));
if (!t) return 0;
t->key=key;
t->next=*n;
*n=t;
if (newFunc) {
newFunc(H,t->key,&(t->value));
newFunc(h,t->key,&(t->value));
} else {
free(t);
return 0;
@ -298,52 +294,47 @@ int hashtable_insert_or_update_computed(HashTable H,
return 1;
}
int hashtable_update(HashTable H,void *key,void *val) {
IntHashTable *h=(IntHashTable *)H;
int hashtable_update(HashTable *h,HashKey_t key,HashVal_t val) {
return _hashtable_insert(h,key,val,1,0);
}
int hashtable_insert(HashTable H,void *key,void *val) {
IntHashTable *h=(IntHashTable *)H;
int hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val) {
return _hashtable_insert(h,key,val,1,0);
}
void hashtable_foreach_update(HashTable H,IteratorUpdateFunc i,void *u) {
IntHashTable *h=(IntHashTable *)H;
IntHashNode *n;
unsigned long x;
void hashtable_foreach_update(HashTable *h,IteratorUpdateFunc i,void *u) {
HashNode *n;
uint32_t x;
if (h->table) {
for (x=0;x<h->length;x++) {
for (n=h->table[x];n;n=n->next) {
i((HashTable)h,n->key,(void **)&(n->value),u);
i(h,n->key,&(n->value),u);
}
}
}
}
void hashtable_foreach(HashTable H,IteratorFunc i,void *u) {
IntHashTable *h=(IntHashTable *)H;
IntHashNode *n;
unsigned long x;
void hashtable_foreach(HashTable *h,IteratorFunc i,void *u) {
HashNode *n;
uint32_t x;
if (h->table) {
for (x=0;x<h->length;x++) {
for (n=h->table[x];n;n=n->next) {
i((HashTable)h,n->key,n->value,u);
i(h,n->key,n->value,u);
}
}
}
}
void hashtable_free(HashTable H) {
IntHashTable *h=(IntHashTable *)H;
IntHashNode *n,*nn;
unsigned long i;
void hashtable_free(HashTable *h) {
HashNode *n,*nn;
uint32_t i;
if (h->table) {
if (h->keyDestroyFunc || h->keyDestroyFunc) {
hashtable_foreach(H,_hashtable_destroy,NULL);
hashtable_foreach(h,_hashtable_destroy,NULL);
}
for (i=0;i<h->length;i++) {
for (n=h->table[i];n;n=nn) {
@ -356,31 +347,29 @@ void hashtable_free(HashTable H) {
free(h);
}
DestroyFunc hashtable_set_value_destroy_func(HashTable H,DestroyFunc d) {
IntHashTable *h=(IntHashTable *)H;
DestroyFunc r=h->valDestroyFunc;
ValDestroyFunc hashtable_set_value_destroy_func(HashTable *h,ValDestroyFunc d) {
ValDestroyFunc r=h->valDestroyFunc;
h->valDestroyFunc=d;
return r;
}
DestroyFunc hashtable_set_key_destroy_func(HashTable H,DestroyFunc d) {
IntHashTable *h=(IntHashTable *)H;
DestroyFunc r=h->keyDestroyFunc;
KeyDestroyFunc hashtable_set_key_destroy_func(HashTable *h,KeyDestroyFunc d) {
KeyDestroyFunc r=h->keyDestroyFunc;
h->keyDestroyFunc=d;
return r;
}
static int _hashtable_remove(IntHashTable *h,
const void *key,
void **keyRet,
void **valRet,
static int _hashtable_remove(HashTable *h,
const HashKey_t key,
HashKey_t *keyRet,
HashVal_t *valRet,
int resize) {
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
IntHashNode *n,*p;
uint32_t hash=h->hashFunc(h,key)%h->length;
HashNode *n,*p;
int i;
for (p=NULL,n=h->table[hash];n;p=n,n=n->next) {
i=h->cmpFunc((HashTable)h,n->key,key);
i=h->cmpFunc(h,n->key,key);
if (!i) {
if (p) p=n->next; else h->table[hash]=n->next;
*keyRet=n->key;
@ -395,17 +384,17 @@ static int _hashtable_remove(IntHashTable *h,
return 0;
}
static int _hashtable_delete(IntHashTable *h,const void *key,int resize) {
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
IntHashNode *n,*p;
static int _hashtable_delete(HashTable *h,const HashKey_t key,int resize) {
uint32_t hash=h->hashFunc(h,key)%h->length;
HashNode *n,*p;
int i;
for (p=NULL,n=h->table[hash];n;p=n,n=n->next) {
i=h->cmpFunc((HashTable)h,n->key,key);
i=h->cmpFunc(h,n->key,key);
if (!i) {
if (p) p=n->next; else h->table[hash]=n->next;
if (h->valDestroyFunc) { h->valDestroyFunc((HashTable)h,n->value); }
if (h->keyDestroyFunc) { h->keyDestroyFunc((HashTable)h,n->key); }
if (h->valDestroyFunc) { h->valDestroyFunc(h,n->value); }
if (h->keyDestroyFunc) { h->keyDestroyFunc(h,n->key); }
free(n);
h->count++;
return 1;
@ -416,39 +405,33 @@ static int _hashtable_delete(IntHashTable *h,const void *key,int resize) {
return 0;
}
int hashtable_remove(HashTable H,const void *key,void **keyRet,void **valRet) {
IntHashTable *h=(IntHashTable *)H;
int hashtable_remove(HashTable *h,const HashKey_t key,HashKey_t *keyRet,HashVal_t *valRet) {
return _hashtable_remove(h,key,keyRet,valRet,1);
}
int hashtable_delete(HashTable H,const void *key) {
IntHashTable *h=(IntHashTable *)H;
int hashtable_delete(HashTable *h,const HashKey_t key) {
return _hashtable_delete(h,key,1);
}
void hashtable_rehash_compute(HashTable H,CollisionFunc cf) {
IntHashTable *h=(IntHashTable *)H;
void hashtable_rehash_compute(HashTable *h,CollisionFunc cf) {
_hashtable_rehash(h,cf,h->length);
}
void hashtable_rehash(HashTable H) {
IntHashTable *h=(IntHashTable *)H;
void hashtable_rehash(HashTable *h) {
_hashtable_rehash(h,NULL,h->length);
}
int hashtable_lookup_or_insert(HashTable H,void *key,void **valp,void *val) {
IntHashTable *h=(IntHashTable *)H;
int hashtable_lookup_or_insert(HashTable *h,HashKey_t key,HashVal_t *valp,HashVal_t val) {
return _hashtable_lookup_or_insert(h,key,valp,val,1);
}
int hashtable_lookup(const HashTable H,const void *key,void **valp) {
IntHashTable *h=(IntHashTable *)H;
unsigned long hash=h->hashFunc((HashTable)h,key)%h->length;
IntHashNode *n;
int hashtable_lookup(const HashTable *h,const HashKey_t key,HashVal_t *valp) {
uint32_t hash=h->hashFunc(h,key)%h->length;
HashNode *n;
int i;
for (n=h->table[hash];n;n=n->next) {
i=h->cmpFunc((HashTable)h,n->key,key);
i=h->cmpFunc(h,n->key,key);
if (!i) {
*valp=n->value;
return 1;
@ -459,18 +442,15 @@ int hashtable_lookup(const HashTable H,const void *key,void **valp) {
return 0;
}
unsigned long hashtable_get_count(const HashTable H) {
IntHashTable *h=(IntHashTable *)H;
uint32_t hashtable_get_count(const HashTable *h) {
return h->count;
}
void *hashtable_get_user_data(const HashTable H) {
IntHashTable *h=(IntHashTable *)H;
void *hashtable_get_user_data(const HashTable *h) {
return h->userData;
}
void *hashtable_set_user_data(HashTable H,void *data) {
IntHashTable *h=(IntHashTable *)H;
void *hashtable_set_user_data(HashTable *h,void *data) {
void *r=h->userData;
h->userData=data;
return r;

View File

@ -9,28 +9,41 @@
* See the README file for information on usage and redistribution.
*/
#ifndef __HASH_H__
#define __HASH_H__
#ifndef __QUANTHASH_H__
#define __QUANTHASH_H__
#include "QuantTypes.h"
HashTable hashtable_new(HashFunc,HashCmpFunc);
void hashtable_free(HashTable);
void hashtable_foreach(HashTable,IteratorFunc,void *);
void hashtable_foreach_update(HashTable,IteratorUpdateFunc,void *);
int hashtable_insert(HashTable,void *,void *);
int hashtable_update(HashTable,void *,void *);
int hashtable_lookup(const HashTable,const void *,void **);
int hashtable_lookup_or_insert(HashTable,void *,void **,void *);
int hashtable_insert_or_update_computed(HashTable,void *,ComputeFunc,ComputeFunc);
int hashtable_delete(HashTable,const void *);
int hashtable_remove(HashTable,const void *,void **,void **);
void *hashtable_set_user_data(HashTable,void *);
void *hashtable_get_user_data(const HashTable);
DestroyFunc hashtable_set_key_destroy_func(HashTable,DestroyFunc);
DestroyFunc hashtable_set_value_destroy_func(HashTable,DestroyFunc);
unsigned long hashtable_get_count(const HashTable);
void hashtable_rehash(HashTable);
void hashtable_rehash_compute(HashTable,CollisionFunc);
typedef struct _HashTable HashTable;
typedef Pixel HashKey_t;
typedef uint32_t HashVal_t;
#endif
typedef uint32_t (*HashFunc)(const HashTable *,const HashKey_t);
typedef int (*HashCmpFunc)(const HashTable *,const HashKey_t,const HashKey_t);
typedef void (*IteratorFunc)(const HashTable *,const HashKey_t,const HashVal_t,void *);
typedef void (*IteratorUpdateFunc)(const HashTable *,const HashKey_t,HashVal_t *,void *);
typedef void (*KeyDestroyFunc)(const HashTable *,HashKey_t);
typedef void (*ValDestroyFunc)(const HashTable *,HashVal_t);
typedef void (*ComputeFunc)(const HashTable *,const HashKey_t,HashVal_t *);
typedef void (*CollisionFunc)(const HashTable *,HashKey_t *,HashVal_t *,HashKey_t,HashVal_t);
HashTable * hashtable_new(HashFunc hf,HashCmpFunc cf);
void hashtable_free(HashTable *h);
void hashtable_foreach(HashTable *h,IteratorFunc i,void *u);
void hashtable_foreach_update(HashTable *h,IteratorUpdateFunc i,void *u);
int hashtable_insert(HashTable *h,HashKey_t key,HashVal_t val);
int hashtable_update(HashTable *h,HashKey_t key,HashVal_t val);
int hashtable_lookup(const HashTable *h,const HashKey_t key,HashVal_t *valp);
int hashtable_lookup_or_insert(HashTable *h,HashKey_t key,HashVal_t *valp,HashVal_t val);
int hashtable_insert_or_update_computed(HashTable *h,HashKey_t key,ComputeFunc newFunc,ComputeFunc existsFunc);
int hashtable_delete(HashTable *h,const HashKey_t key);
int hashtable_remove(HashTable *h,const HashKey_t key,HashKey_t *keyRet,HashVal_t *valRet);
void *hashtable_set_user_data(HashTable *h,void *data);
void *hashtable_get_user_data(const HashTable *h);
KeyDestroyFunc hashtable_set_key_destroy_func(HashTable *,KeyDestroyFunc d);
ValDestroyFunc hashtable_set_value_destroy_func(HashTable *,ValDestroyFunc d);
uint32_t hashtable_get_count(const HashTable *h);
void hashtable_rehash(HashTable *h);
void hashtable_rehash_compute(HashTable *h,CollisionFunc cf);
#endif // __QUANTHASH_H__

View File

@ -21,31 +21,29 @@
#include <string.h>
#include <math.h>
#include "QuantHash.h"
#include "QuantDefines.h"
#include "QuantHeap.h"
typedef struct {
typedef struct _Heap {
void **heap;
int heapsize;
int heapcount;
HeapCmpFunc cf;
} IntHeap;
} Heap;
#define INITIAL_SIZE 256
#define DEBUG
// #define DEBUG
#ifdef DEBUG
static int _heap_test(Heap);
static int _heap_test(Heap *);
#endif
void ImagingQuantHeapFree(Heap H) {
IntHeap *h=(IntHeap *)H;
void ImagingQuantHeapFree(Heap *h) {
free(h->heap);
free(h);
}
static int _heap_grow(IntHeap *h,int newsize) {
static int _heap_grow(Heap *h,int newsize) {
void *newheap;
if (!newsize) newsize=h->heapsize<<1;
if (newsize<h->heapsize) return 0;
@ -59,15 +57,14 @@ static int _heap_grow(IntHeap *h,int newsize) {
}
#ifdef DEBUG
static int _heap_test(Heap H) {
IntHeap *h=(IntHeap *)H;
static int _heap_test(Heap *h) {
int k;
for (k=1;k*2<=h->heapcount;k++) {
if (h->cf(H,h->heap[k],h->heap[k*2])<0) {
if (h->cf(h,h->heap[k],h->heap[k*2])<0) {
printf ("heap is bad\n");
return 0;
}
if (k*2+1<=h->heapcount && h->cf(H,h->heap[k],h->heap[k*2+1])<0) {
if (k*2+1<=h->heapcount && h->cf(h,h->heap[k],h->heap[k*2+1])<0) {
printf ("heap is bad\n");
return 0;
}
@ -76,8 +73,7 @@ static int _heap_test(Heap H) {
}
#endif
int ImagingQuantHeapRemove(Heap H,void **r) {
IntHeap *h=(IntHeap *)H;
int ImagingQuantHeapRemove(Heap* h,void **r) {
int k,l;
void *v;
@ -89,31 +85,30 @@ int ImagingQuantHeapRemove(Heap H,void **r) {
for (k=1;k*2<=h->heapcount;k=l) {
l=k*2;
if (l<h->heapcount) {
if (h->cf(H,h->heap[l],h->heap[l+1])<0) {
if (h->cf(h,h->heap[l],h->heap[l+1])<0) {
l++;
}
}
if (h->cf(H,v,h->heap[l])>0) {
if (h->cf(h,v,h->heap[l])>0) {
break;
}
h->heap[k]=h->heap[l];
}
h->heap[k]=v;
#ifdef DEBUG
if (!_heap_test(H)) { printf ("oops - heap_remove messed up the heap\n"); exit(1); }
if (!_heap_test(h)) { printf ("oops - heap_remove messed up the heap\n"); exit(1); }
#endif
return 1;
}
int ImagingQuantHeapAdd(Heap H,void *val) {
IntHeap *h=(IntHeap *)H;
int ImagingQuantHeapAdd(Heap *h,void *val) {
int k;
if (h->heapcount==h->heapsize-1) {
_heap_grow(h,0);
}
k=++h->heapcount;
while (k!=1) {
if (h->cf(H,val,h->heap[k/2])<=0) {
if (h->cf(h,val,h->heap[k/2])<=0) {
break;
}
h->heap[k]=h->heap[k/2];
@ -121,13 +116,12 @@ int ImagingQuantHeapAdd(Heap H,void *val) {
}
h->heap[k]=val;
#ifdef DEBUG
if (!_heap_test(H)) { printf ("oops - heap_add messed up the heap\n"); exit(1); }
if (!_heap_test(h)) { printf ("oops - heap_add messed up the heap\n"); exit(1); }
#endif
return 1;
}
int ImagingQuantHeapTop(Heap H,void **r) {
IntHeap *h=(IntHeap *)H;
int ImagingQuantHeapTop(Heap *h,void **r) {
if (!h->heapcount) {
return 0;
}
@ -136,15 +130,14 @@ int ImagingQuantHeapTop(Heap H,void **r) {
}
Heap *ImagingQuantHeapNew(HeapCmpFunc cf) {
IntHeap *h;
Heap *h;
h=malloc(sizeof(IntHeap));
h=malloc(sizeof(Heap));
if (!h) return NULL;
h->heapsize=INITIAL_SIZE;
h->heap=malloc(sizeof(void *)*h->heapsize);
if (!h->heap) { free(h); return NULL; }
h->heapcount=0;
h->cf=cf;
return (Heap)h;
return h;
}

View File

@ -9,15 +9,19 @@
* See the README file for information on usage and redistribution.
*/
#ifndef __HEAP_H__
#define __HEAP_H__
#ifndef __QUANTHEAP_H__
#define __QUANTHEAP_H__
#include "QuantTypes.h"
void ImagingQuantHeapFree(Heap);
int ImagingQuantHeapRemove(Heap,void **);
int ImagingQuantHeapAdd(Heap,void *);
int ImagingQuantHeapTop(Heap,void **);
typedef struct _Heap Heap;
typedef int (*HeapCmpFunc)(const Heap *,const void *,const void *);
void ImagingQuantHeapFree(Heap *);
int ImagingQuantHeapRemove(Heap *,void **);
int ImagingQuantHeapAdd(Heap *,void *);
int ImagingQuantHeapTop(Heap *,void **);
Heap *ImagingQuantHeapNew(HeapCmpFunc);
#endif
#endif // __QUANTHEAP_H__

View File

@ -27,15 +27,15 @@
#include <stdlib.h>
#include <string.h>
#include "Quant.h"
#include "QuantOctree.h"
typedef struct _ColorBucket{
/* contains palette index when used for look up cube */
unsigned long count;
unsigned long r;
unsigned long g;
unsigned long b;
unsigned long a;
uint32_t count;
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
} *ColorBucket;
typedef struct _ColorCube{
@ -262,7 +262,7 @@ set_lookup_value(const ColorCube cube, const Pixel *p, long value) {
bucket->count = value;
}
unsigned long
uint32_t
lookup_color(const ColorCube cube, const Pixel *p) {
ColorBucket bucket = color_bucket_from_cube(cube, p);
return bucket->count;
@ -302,9 +302,9 @@ create_palette_array(const ColorBucket palette, unsigned int paletteLength) {
static void
map_image_pixels(const Pixel *pixelData,
unsigned long nPixels,
uint32_t nPixels,
const ColorCube lookupCube,
unsigned long *pixelArray)
uint32_t *pixelArray)
{
long i;
for (i=0; i<nPixels; i++) {
@ -316,11 +316,11 @@ const int CUBE_LEVELS[8] = {4, 4, 4, 0, 2, 2, 2, 0};
const int CUBE_LEVELS_ALPHA[8] = {3, 4, 3, 3, 2, 2, 2, 2};
int quantize_octree(Pixel *pixelData,
unsigned long nPixels,
unsigned long nQuantPixels,
uint32_t nPixels,
uint32_t nQuantPixels,
Pixel **palette,
unsigned long *paletteLength,
unsigned long **quantizedPixels,
uint32_t *paletteLength,
uint32_t **quantizedPixels,
int withAlpha)
{
ColorCube fineCube = NULL;
@ -330,7 +330,7 @@ int quantize_octree(Pixel *pixelData,
ColorBucket paletteBucketsCoarse = NULL;
ColorBucket paletteBucketsFine = NULL;
ColorBucket paletteBuckets = NULL;
unsigned long *qp = NULL;
uint32_t *qp = NULL;
long i;
long nCoarseColors, nFineColors, nAlreadySubtracted;
const int *cubeBits;

View File

@ -1,12 +1,14 @@
#ifndef __QUANT_OCTREE_H__
#define __QUANT_OCTREE_H__
#include "QuantTypes.h"
int quantize_octree(Pixel *,
unsigned long,
unsigned long,
uint32_t,
uint32_t,
Pixel **,
unsigned long *,
unsigned long **,
uint32_t *,
uint32_t **,
int);
#endif
#endif

View File

@ -12,17 +12,20 @@
#ifndef __TYPES_H__
#define __TYPES_H__
typedef void *HashTable;
typedef void *Heap;
#ifdef _MSC_VER
typedef unsigned __int32 uint32_t;
#else
#include <stdint.h>
#endif
typedef unsigned long (*HashFunc)(const HashTable,const void *);
typedef int (*HashCmpFunc)(const HashTable,const void *,const void *);
typedef void (*IteratorFunc)(const HashTable,const void *,const void *,void *);
typedef void (*IteratorUpdateFunc)(const HashTable,const void *,void **,void *);
typedef void (*DestroyFunc)(const HashTable,void *);
typedef void (*ComputeFunc)(const HashTable,const void *,void **);
typedef void (*CollisionFunc)(const HashTable,void **,void **,void *,void *);
typedef int (*HeapCmpFunc)(const Heap,const void *,const void *);
typedef union {
struct {
unsigned char r,g,b,a;
} c;
struct {
unsigned char v[4];
} a;
uint32_t v;
} Pixel;
#endif

View File

@ -453,8 +453,6 @@ class pil_build_ext(build_ext):
tmpfile = os.path.join(self.build_temp, 'multiarch')
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)
ret = os.system('dpkg-architecture -qDEB_HOST_MULTIARCH > %s' %
tmpfile)
ret = os.system(
'dpkg-architecture -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
tmpfile)