mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-26 09:14:27 +03:00
Merge pull request #2899 from wiredfool/pr_2882
Run all compressed tiffs through libtiff
This commit is contained in:
commit
49bd3232e5
|
@ -1029,21 +1029,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
compression = self._compression
|
||||
if compression == "raw":
|
||||
args = (rawmode, 0, 1)
|
||||
elif compression == "jpeg":
|
||||
args = rawmode, ""
|
||||
if JPEGTABLES in self.tag_v2:
|
||||
# Hack to handle abbreviated JPEG headers
|
||||
# Definition of JPEGTABLES is that the count
|
||||
# is the number of bytes in the tables datastream
|
||||
# so, it should always be 1 in our tag info
|
||||
self.tile_prefix = self.tag_v2[JPEGTABLES]
|
||||
elif compression == "packbits":
|
||||
args = rawmode
|
||||
elif compression == "tiff_lzw":
|
||||
args = rawmode
|
||||
if PREDICTOR in self.tag_v2:
|
||||
# Section 14: Differencing Predictor
|
||||
self.decoderconfig = (self.tag_v2[PREDICTOR],)
|
||||
|
||||
return args
|
||||
|
||||
|
@ -1244,14 +1231,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
offsets = self.tag_v2[STRIPOFFSETS]
|
||||
h = self.tag_v2.get(ROWSPERSTRIP, ysize)
|
||||
w = self.size[0]
|
||||
if READ_LIBTIFF or self._compression in ["tiff_ccitt", "group3",
|
||||
"group4", "tiff_jpeg",
|
||||
"tiff_adobe_deflate",
|
||||
"tiff_thunderscan",
|
||||
"tiff_deflate",
|
||||
"tiff_sgilog",
|
||||
"tiff_sgilog24",
|
||||
"tiff_raw_16"]:
|
||||
if READ_LIBTIFF or self._compression != 'raw':
|
||||
# if DEBUG:
|
||||
# print("Activating g4 compression for whole file")
|
||||
|
||||
|
@ -1285,8 +1265,13 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
# we're expecting image byte order. So, if the rawmode
|
||||
# contains I;16, we need to convert from native to image
|
||||
# byte order.
|
||||
if self.mode in ('I;16B', 'I;16') and 'I;16' in rawmode:
|
||||
if rawmode == 'I;16':
|
||||
rawmode = 'I;16N'
|
||||
if ';16B' in rawmode:
|
||||
rawmode = rawmode.replace(';16B', ';16N')
|
||||
if ';16L' in rawmode:
|
||||
rawmode = rawmode.replace(';16L', ';16N')
|
||||
|
||||
|
||||
# Offset in the tile tuple is 0, we go from 0,0 to
|
||||
# w,h, and we only do this once -- eds
|
||||
|
|
|
@ -14,11 +14,22 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
|
||||
HAS_UPLOADER = False
|
||||
try:
|
||||
import test_image_results
|
||||
HAS_UPLOADER = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
if os.environ.get('SHOW_ERRORS', None):
|
||||
# local img.show for errors.
|
||||
HAS_UPLOADER=True
|
||||
class test_image_results:
|
||||
@classmethod
|
||||
def upload(self, a, b):
|
||||
a.show()
|
||||
b.show()
|
||||
else:
|
||||
try:
|
||||
import test_image_results
|
||||
HAS_UPLOADER = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def convert_to_comparable(a, b):
|
||||
|
@ -99,11 +110,17 @@ class PillowTestCase(unittest.TestCase):
|
|||
try:
|
||||
url = test_image_results.upload(a, b)
|
||||
logger.error("Url for test images: %s" % url)
|
||||
except:
|
||||
except Exception as msg:
|
||||
pass
|
||||
|
||||
self.fail(msg or "got different content")
|
||||
|
||||
def assert_image_equal_tofile(self, a, filename, msg=None, mode=None):
|
||||
with Image.open(filename) as img:
|
||||
if mode:
|
||||
img = img.convert(mode)
|
||||
self.assert_image_equal(a, img, msg)
|
||||
|
||||
def assert_image_similar(self, a, b, epsilon, msg=None):
|
||||
epsilon = float(epsilon)
|
||||
self.assertEqual(
|
||||
|
@ -136,6 +153,12 @@ class PillowTestCase(unittest.TestCase):
|
|||
pass
|
||||
raise e
|
||||
|
||||
def assert_image_similar_tofile(self, a, filename, epsilon, msg=None, mode=None):
|
||||
with Image.open(filename) as img:
|
||||
if mode:
|
||||
img = img.convert(mode)
|
||||
self.assert_image_similar(a, img, epsilon, msg)
|
||||
|
||||
def assert_warning(self, warn_class, func, *args, **kwargs):
|
||||
import warnings
|
||||
|
||||
|
|
BIN
Tests/images/copyleft.png
Normal file
BIN
Tests/images/copyleft.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
BIN
Tests/images/pil136.png
Normal file
BIN
Tests/images/pil136.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
Tests/images/pil168.png
Normal file
BIN
Tests/images/pil168.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.6 KiB |
BIN
Tests/images/tiff_16bit_RGBa_target.png
Normal file
BIN
Tests/images/tiff_16bit_RGBa_target.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
Tests/images/tiff_adobe_deflate.png
Normal file
BIN
Tests/images/tiff_adobe_deflate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 92 KiB |
|
@ -1,5 +1,6 @@
|
|||
from __future__ import print_function
|
||||
from helper import unittest, PillowTestCase, hopper, py3
|
||||
from PIL import features
|
||||
|
||||
from ctypes import c_float
|
||||
import io
|
||||
|
@ -15,9 +16,7 @@ logger = logging.getLogger(__name__)
|
|||
class LibTiffTestCase(PillowTestCase):
|
||||
|
||||
def setUp(self):
|
||||
codecs = dir(Image.core)
|
||||
|
||||
if "libtiff_encoder" not in codecs or "libtiff_decoder" not in codecs:
|
||||
if not features.check('libtiff'):
|
||||
self.skipTest("tiff support not available")
|
||||
|
||||
def _assert_noerr(self, im):
|
||||
|
@ -126,6 +125,8 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
im.tile[0][:3], ('tiff_adobe_deflate', (0, 0, 278, 374), 0))
|
||||
im.load()
|
||||
|
||||
self.assert_image_equal_tofile(im, 'Tests/images/tiff_adobe_deflate.png')
|
||||
|
||||
def test_write_metadata(self):
|
||||
""" Test metadata writing through libtiff """
|
||||
for legacy_api in [False, True]:
|
||||
|
@ -310,12 +311,7 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
# imagemagick will auto scale so that a 12bit FFF is 16bit FFF0,
|
||||
# so we need to unshift so that the integer values are the same.
|
||||
|
||||
im2 = Image.open('Tests/images/12in16bit.tif')
|
||||
|
||||
logger.debug("%s", [img.getpixel((0, idx))
|
||||
for img in [im, im2] for idx in range(3)])
|
||||
|
||||
self.assert_image_equal(im, im2)
|
||||
self.assert_image_equal_tofile(im, 'Tests/images/12in16bit.tif')
|
||||
|
||||
def test_blur(self):
|
||||
# test case from irc, how to do blur on b/w image
|
||||
|
@ -576,6 +572,51 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
# Should not raise UnicodeDecodeError or anything else
|
||||
im.save(outfile)
|
||||
|
||||
def test_16bit_RGBa_tiff(self):
|
||||
im = Image.open("Tests/images/tiff_16bit_RGBa.tiff")
|
||||
|
||||
self.assertEqual(im.mode, "RGBA")
|
||||
self.assertEqual(im.size, (100, 40))
|
||||
self.assertEqual(im.tile, [('tiff_lzw', (0, 0, 100, 40), 0, ('RGBa;16N', 'tiff_lzw', False))])
|
||||
im.load()
|
||||
|
||||
self.assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png")
|
||||
|
||||
def test_gimp_tiff(self):
|
||||
# Read TIFF JPEG images from GIMP [@PIL168]
|
||||
|
||||
codecs = dir(Image.core)
|
||||
if "jpeg_decoder" not in codecs:
|
||||
self.skipTest("jpeg support not available")
|
||||
|
||||
filename = "Tests/images/pil168.tif"
|
||||
im = Image.open(filename)
|
||||
|
||||
self.assertEqual(im.mode, "RGB")
|
||||
self.assertEqual(im.size, (256, 256))
|
||||
self.assertEqual(
|
||||
im.tile, [('jpeg', (0, 0, 256, 256), 0, ('RGB', 'jpeg', False))]
|
||||
)
|
||||
im.load()
|
||||
|
||||
self.assert_image_equal_tofile(im, "Tests/images/pil168.png")
|
||||
|
||||
def test_sampleformat(self):
|
||||
# https://github.com/python-pillow/Pillow/issues/1466
|
||||
im = Image.open("Tests/images/copyleft.tiff")
|
||||
self.assertEqual(im.mode, 'RGB')
|
||||
|
||||
self.assert_image_equal_tofile(im, "Tests/images/copyleft.png", mode='RGB')
|
||||
|
||||
def test_lzw(self):
|
||||
im = Image.open("Tests/images/hopper_lzw.tif")
|
||||
|
||||
self.assertEqual(im.mode, 'RGB')
|
||||
self.assertEqual(im.size, (128, 128))
|
||||
self.assertEqual(im.format, "TIFF")
|
||||
im2 = hopper()
|
||||
self.assert_image_similar(im, im2, 5)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from helper import unittest, PillowTestCase, hopper
|
||||
|
||||
from PIL import Image, ImagePalette
|
||||
from PIL import Image, ImagePalette, features
|
||||
|
||||
try:
|
||||
from PIL import MicImagePlugin
|
||||
|
@ -13,6 +13,7 @@ TEST_FILE = "Tests/images/hopper.mic"
|
|||
|
||||
|
||||
@unittest.skipUnless(olefile_installed, "olefile package not installed")
|
||||
@unittest.skipUnless(features.check('libtiff'), "libtiff not installed")
|
||||
class TestFileMic(PillowTestCase):
|
||||
|
||||
def test_sanity(self):
|
||||
|
|
|
@ -51,13 +51,7 @@ class TestFileTiff(PillowTestCase):
|
|||
self.assertEqual(im.tile, [('raw', (0, 0, 55, 43), 8, ('RGBa', 0, 1))])
|
||||
im.load()
|
||||
|
||||
def test_16bit_RGBa_tiff(self):
|
||||
im = Image.open("Tests/images/tiff_16bit_RGBa.tiff")
|
||||
|
||||
self.assertEqual(im.mode, "RGBA")
|
||||
self.assertEqual(im.size, (100, 40))
|
||||
self.assertEqual(im.tile, [('tiff_lzw', (0, 0, 100, 40), 50, 'RGBa;16B')])
|
||||
im.load()
|
||||
self.assert_image_similar_tofile(im, "Tests/images/pil136.png", 1)
|
||||
|
||||
def test_wrong_bits_per_sample(self):
|
||||
im = Image.open("Tests/images/tiff_wrong_bits_per_sample.tiff")
|
||||
|
@ -67,32 +61,6 @@ class TestFileTiff(PillowTestCase):
|
|||
self.assertEqual(im.tile, [('raw', (0, 0, 52, 53), 160, ('RGBA', 0, 1))])
|
||||
im.load()
|
||||
|
||||
def test_gimp_tiff(self):
|
||||
# Read TIFF JPEG images from GIMP [@PIL168]
|
||||
|
||||
codecs = dir(Image.core)
|
||||
if "jpeg_decoder" not in codecs:
|
||||
self.skipTest("jpeg support not available")
|
||||
|
||||
filename = "Tests/images/pil168.tif"
|
||||
im = Image.open(filename)
|
||||
|
||||
self.assertEqual(im.mode, "RGB")
|
||||
self.assertEqual(im.size, (256, 256))
|
||||
self.assertEqual(
|
||||
im.tile, [
|
||||
('jpeg', (0, 0, 256, 64), 8, ('RGB', '')),
|
||||
('jpeg', (0, 64, 256, 128), 1215, ('RGB', '')),
|
||||
('jpeg', (0, 128, 256, 192), 2550, ('RGB', '')),
|
||||
('jpeg', (0, 192, 256, 256), 3890, ('RGB', '')),
|
||||
])
|
||||
im.load()
|
||||
|
||||
def test_sampleformat(self):
|
||||
# https://github.com/python-pillow/Pillow/issues/1466
|
||||
im = Image.open("Tests/images/copyleft.tiff")
|
||||
self.assertEqual(im.mode, 'RGB')
|
||||
|
||||
def test_set_legacy_api(self):
|
||||
with self.assertRaises(Exception):
|
||||
ImageFileDirectory_v2.legacy_api = None
|
||||
|
@ -225,12 +193,7 @@ class TestFileTiff(PillowTestCase):
|
|||
# imagemagick will auto scale so that a 12bit FFF is 16bit FFF0,
|
||||
# so we need to unshift so that the integer values are the same.
|
||||
|
||||
im2 = Image.open('Tests/images/12in16bit.tif')
|
||||
|
||||
logger.debug("%s", [img.getpixel((0, idx))
|
||||
for img in [im, im2] for idx in range(3)])
|
||||
|
||||
self.assert_image_equal(im, im2)
|
||||
self.assert_image_equal_tofile(im, 'Tests/images/12in16bit.tif')
|
||||
|
||||
def test_32bit_float(self):
|
||||
# Issue 614, specific 32-bit float format
|
||||
|
@ -436,16 +399,6 @@ class TestFileTiff(PillowTestCase):
|
|||
self.assertEqual(im.tag_v2[X_RESOLUTION], 72)
|
||||
self.assertEqual(im.tag_v2[Y_RESOLUTION], 36)
|
||||
|
||||
def test_lzw(self):
|
||||
# Act
|
||||
im = Image.open("Tests/images/hopper_lzw.tif")
|
||||
|
||||
# Assert
|
||||
self.assertEqual(im.mode, 'RGB')
|
||||
self.assertEqual(im.size, (128, 128))
|
||||
self.assertEqual(im.format, "TIFF")
|
||||
im2 = hopper()
|
||||
self.assert_image_similar(im, im2, 5)
|
||||
|
||||
def test_roundtrip_tiff_uint16(self):
|
||||
# Test an image of all '0' values
|
||||
|
|
|
@ -3480,7 +3480,6 @@ extern PyObject* PyImaging_GifDecoderNew(PyObject* self, PyObject* args);
|
|||
extern PyObject* PyImaging_HexDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_JpegDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_Jpeg2KDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_TiffLzwDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_PcdDecoderNew(PyObject* self, PyObject* args);
|
||||
|
@ -3553,7 +3552,6 @@ static PyMethodDef functions[] = {
|
|||
{"jpeg2k_decoder", (PyCFunction)PyImaging_Jpeg2KDecoderNew, 1},
|
||||
{"jpeg2k_encoder", (PyCFunction)PyImaging_Jpeg2KEncoderNew, 1},
|
||||
#endif
|
||||
{"tiff_lzw_decoder", (PyCFunction)PyImaging_TiffLzwDecoderNew, 1},
|
||||
#ifdef HAVE_LIBTIFF
|
||||
{"libtiff_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
||||
{"libtiff_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
||||
|
|
30
decode.c
30
decode.c
|
@ -35,7 +35,6 @@
|
|||
#include "py3.h"
|
||||
|
||||
#include "Gif.h"
|
||||
#include "Lzw.h"
|
||||
#include "Raw.h"
|
||||
#include "Bit.h"
|
||||
#include "Sgi.h"
|
||||
|
@ -484,35 +483,6 @@ PyImaging_HexDecoderNew(PyObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* LZW */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
PyObject*
|
||||
PyImaging_TiffLzwDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
int filter = 0;
|
||||
if (!PyArg_ParseTuple(args, "ss|i", &mode, &rawmode, &filter))
|
||||
return NULL;
|
||||
|
||||
decoder = PyImaging_DecoderNew(sizeof(LZWSTATE));
|
||||
if (decoder == NULL)
|
||||
return NULL;
|
||||
|
||||
if (get_unpacker(decoder, mode, rawmode) < 0)
|
||||
return NULL;
|
||||
|
||||
decoder->decode = ImagingLzwDecode;
|
||||
|
||||
((LZWSTATE*)decoder->state.context)->filter = filter;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* LibTiff */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -549,13 +549,18 @@ For more information about the SPIDER image processing package, see the
|
|||
TIFF
|
||||
^^^^
|
||||
|
||||
PIL reads and writes TIFF files. It can read both striped and tiled images,
|
||||
pixel and plane interleaved multi-band images, and either uncompressed, or
|
||||
Packbits, LZW, or JPEG compressed images.
|
||||
Pillow reads and writes TIFF files. It can read both striped and tiled
|
||||
images, pixel and plane interleaved multi-band images. If you have
|
||||
libtiff and its headers installed, PIL can read and write many kinds
|
||||
of compressed TIFF files. If not, PIL will only read and write
|
||||
uncompressed files.
|
||||
|
||||
If you have libtiff and its headers installed, PIL can read and write many more
|
||||
kinds of compressed TIFF files. If not, PIL will always write uncompressed
|
||||
files.
|
||||
.. note::
|
||||
|
||||
Beginning in version 4.4.0, Pillow requires libtiff to read or
|
||||
write compressed files. Prior to that release, Pillow had buggy
|
||||
support for reading Packbits, LZW and JPEG compressed TIFFs
|
||||
without using libtiff.
|
||||
|
||||
The :py:meth:`~PIL.Image.Image.open` method sets the following
|
||||
:py:attr:`~PIL.Image.Image.info` properties:
|
||||
|
|
|
@ -440,8 +440,6 @@ extern int ImagingJpeg2KEncode(Imaging im, ImagingCodecState state,
|
|||
UINT8* buffer, int bytes);
|
||||
extern int ImagingJpeg2KEncodeCleanup(ImagingCodecState state);
|
||||
#endif
|
||||
extern int ImagingLzwDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
#ifdef HAVE_LIBTIFF
|
||||
extern int ImagingLibTiffDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* The Python Imaging Library.
|
||||
* $Id$
|
||||
*
|
||||
* declarations for the TIFF LZW decoder.
|
||||
*
|
||||
* Copyright (c) Fredrik Lundh 1995-96.
|
||||
*/
|
||||
|
||||
|
||||
/* Max size for LZW code words */
|
||||
|
||||
#define LZWBITS 12
|
||||
|
||||
#define LZWTABLE (1<<LZWBITS)
|
||||
#define LZWBUFFER (1<<LZWBITS)
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* CONFIGURATION */
|
||||
|
||||
/* Filter type */
|
||||
int filter;
|
||||
|
||||
/* PRIVATE CONTEXT (set by decoder) */
|
||||
|
||||
/* Input bit buffer */
|
||||
INT32 bitbuffer;
|
||||
int bitcount;
|
||||
|
||||
/* Code buffer */
|
||||
int codesize;
|
||||
int codemask;
|
||||
|
||||
/* Constant symbol codes */
|
||||
int clear, end;
|
||||
|
||||
/* Symbol history */
|
||||
int lastcode;
|
||||
unsigned char lastdata;
|
||||
|
||||
/* History buffer */
|
||||
int bufferindex;
|
||||
unsigned char buffer[LZWTABLE];
|
||||
|
||||
/* Symbol table */
|
||||
UINT16 link[LZWTABLE];
|
||||
unsigned char data[LZWTABLE];
|
||||
int next;
|
||||
|
||||
} LZWSTATE;
|
|
@ -1,230 +0,0 @@
|
|||
/*
|
||||
* The Python Imaging Library.
|
||||
* $Id$
|
||||
*
|
||||
* a fast, suspendable TIFF LZW decoder
|
||||
*
|
||||
* description:
|
||||
* This code is based on the GIF decoder. There are some
|
||||
* subtle differences between GIF and TIFF LZW, though:
|
||||
* - The fill order is different. In the TIFF file, you
|
||||
* must shift new bits in to the right, not to the left.
|
||||
* - There is no blocking in the input data stream.
|
||||
* - The code size is increased one step earlier than
|
||||
* for GIF
|
||||
* - Image data are seen as a byte stream, not a pixel
|
||||
* stream. This means that the code size will always
|
||||
* start at 9 bits.
|
||||
*
|
||||
* history:
|
||||
* 95-09-13 fl Created (derived from GifDecode.c)
|
||||
* 96-03-28 fl Revised API, integrated with PIL
|
||||
* 97-01-05 fl Added filter support, added extra consistency checks
|
||||
*
|
||||
* Copyright (c) Fredrik Lundh 1995-97.
|
||||
* Copyright (c) Secret Labs AB 1997.
|
||||
*
|
||||
* See the README file for information on usage and redistribution.
|
||||
*/
|
||||
|
||||
|
||||
#include "Imaging.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* memcpy() */
|
||||
|
||||
#include "Lzw.h"
|
||||
|
||||
|
||||
int
|
||||
ImagingLzwDecode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||
{
|
||||
UINT8* p;
|
||||
int c, i;
|
||||
int thiscode;
|
||||
LZWSTATE* context = (LZWSTATE*) state->context;
|
||||
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
if (!state->state) {
|
||||
|
||||
/* Clear code */
|
||||
context->clear = 1 << 8;
|
||||
|
||||
/* End code */
|
||||
context->end = context->clear + 1;
|
||||
|
||||
state->state = 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (state->state == 1) {
|
||||
|
||||
/* First free entry in table */
|
||||
context->next = context->clear + 2;
|
||||
|
||||
/* Initial code size */
|
||||
context->codesize = 8 + 1;
|
||||
context->codemask = (1 << context->codesize) - 1;
|
||||
|
||||
/* Buffer pointer. We fill the buffer from right, which
|
||||
allows us to return all of it in one operation. */
|
||||
context->bufferindex = LZWBUFFER;
|
||||
|
||||
state->state = 2;
|
||||
}
|
||||
|
||||
if (context->bufferindex < LZWBUFFER) {
|
||||
|
||||
/* Return whole buffer in one chunk */
|
||||
i = LZWBUFFER - context->bufferindex;
|
||||
p = &context->buffer[context->bufferindex];
|
||||
|
||||
context->bufferindex = LZWBUFFER;
|
||||
|
||||
} else {
|
||||
|
||||
/* Get current symbol */
|
||||
while (context->bitcount < context->codesize) {
|
||||
|
||||
if (bytes < 1)
|
||||
return ptr - buf;;
|
||||
|
||||
/* Read next byte */
|
||||
c = *ptr++; bytes--;
|
||||
|
||||
/* New bits are shifted in from from the right. */
|
||||
context->bitbuffer = (context->bitbuffer << 8) | c;
|
||||
context->bitcount += 8;
|
||||
|
||||
}
|
||||
|
||||
/* Extract current symbol from bit buffer. */
|
||||
c = (context->bitbuffer >> (context->bitcount -
|
||||
context->codesize))
|
||||
& context->codemask;
|
||||
|
||||
/* Adjust buffer */
|
||||
context->bitcount -= context->codesize;
|
||||
|
||||
/* If c is less than clear, it's a data byte. Otherwise,
|
||||
it's either clear/end or a code symbol which should be
|
||||
expanded. */
|
||||
|
||||
if (c == context->clear) {
|
||||
if (state->state != 2)
|
||||
state->state = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == context->end)
|
||||
break;
|
||||
|
||||
i = 1;
|
||||
p = &context->lastdata;
|
||||
|
||||
if (state->state == 2) {
|
||||
|
||||
/* First valid symbol after clear; use as is */
|
||||
if (c > context->clear) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
context->lastdata = context->lastcode = c;
|
||||
state->state = 3;
|
||||
|
||||
} else {
|
||||
|
||||
thiscode = c;
|
||||
|
||||
if (c > context->next) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (c == context->next) {
|
||||
|
||||
/* c == next is allowed, by some strange reason */
|
||||
if (context->bufferindex <= 0) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
context->buffer[--context->bufferindex] = context->lastdata;
|
||||
c = context->lastcode;
|
||||
}
|
||||
|
||||
while (c >= context->clear) {
|
||||
|
||||
/* Copy data string to buffer (beginning from right) */
|
||||
|
||||
if (context->bufferindex <= 0 || c >= LZWTABLE) {
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
context->buffer[--context->bufferindex] =
|
||||
context->data[c];
|
||||
c = context->link[c];
|
||||
}
|
||||
|
||||
context->lastdata = c;
|
||||
|
||||
if (context->next < LZWTABLE) {
|
||||
|
||||
/* While we still have room for it, add this
|
||||
symbol to the table. */
|
||||
context->data[context->next] = c;
|
||||
context->link[context->next] = context->lastcode;
|
||||
|
||||
context->next++;
|
||||
|
||||
if (context->next == context->codemask &&
|
||||
context->codesize < LZWBITS) {
|
||||
|
||||
/* Expand code size */
|
||||
context->codesize++;
|
||||
context->codemask = (1 << context->codesize) - 1;
|
||||
|
||||
}
|
||||
}
|
||||
context->lastcode = thiscode;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the output image */
|
||||
for (c = 0; c < i; c++) {
|
||||
|
||||
state->buffer[state->x] = p[c];
|
||||
|
||||
if (++state->x >= state->bytes) {
|
||||
|
||||
int x, bpp;
|
||||
|
||||
/* Apply filter */
|
||||
switch (context->filter) {
|
||||
case 2:
|
||||
/* Horizontal differing ("prior") */
|
||||
bpp = (state->bits + 7) / 8;
|
||||
for (x = bpp; x < state->bytes; x++)
|
||||
state->buffer[x] += state->buffer[x-bpp];
|
||||
}
|
||||
|
||||
/* Got a full line, unpack it */
|
||||
state->shuffle((UINT8*) im->image[state->y + state->yoff] +
|
||||
state->xoff * im->pixelsize, state->buffer,
|
||||
state->xsize);
|
||||
|
||||
state->x = 0;
|
||||
|
||||
if (++state->y >= state->ysize)
|
||||
/* End of file (errcode = 0) */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ptr - buf;
|
||||
}
|
|
@ -1301,6 +1301,19 @@ static struct {
|
|||
{"RGBA", "B", 8, band2},
|
||||
{"RGBA", "A", 8, band3},
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
{"RGB", "RGB;16N", 64, unpackRGB16B},
|
||||
{"RGBA", "RGBa;16N", 64, unpackRGBa16B},
|
||||
{"RGBA", "RGBA;16N", 64, unpackRGBA16B},
|
||||
{"RGBX", "RGBX;16N", 64, unpackRGBA16B},
|
||||
#else
|
||||
{"RGB", "RGB;16N", 64, unpackRGB16L},
|
||||
{"RGBA", "RGBa;16N", 64, unpackRGBa16L},
|
||||
{"RGBA", "RGBA;16N", 64, unpackRGBA16L},
|
||||
{"RGBX", "RGBX;16N", 64, unpackRGBA16B},
|
||||
#endif
|
||||
|
||||
|
||||
/* true colour w. alpha premultiplied */
|
||||
{"RGBa", "RGBa", 32, copy4},
|
||||
{"RGBa", "BGRa", 32, unpackBGRA},
|
||||
|
|
2
setup.py
2
setup.py
|
@ -43,7 +43,7 @@ _LIB_IMAGING = (
|
|||
"Blend", "Chops", "Convert", "ConvertYCbCr", "Copy", "Crc32", "Crop",
|
||||
"Dib", "Draw", "Effects", "EpsEncode", "File", "Fill", "Filter",
|
||||
"FliDecode", "Geometry", "GetBBox", "GifDecode", "GifEncode", "HexDecode",
|
||||
"Histo", "JpegDecode", "JpegEncode", "LzwDecode", "Matrix", "ModeFilter",
|
||||
"Histo", "JpegDecode", "JpegEncode", "Matrix", "ModeFilter",
|
||||
"Negative", "Offset", "Pack", "PackDecode", "Palette", "Paste", "Quant",
|
||||
"QuantOctree", "QuantHash", "QuantHeap", "PcdDecode", "PcxDecode",
|
||||
"PcxEncode", "Point", "RankFilter", "RawDecode", "RawEncode", "Storage",
|
||||
|
|
Loading…
Reference in New Issue
Block a user