mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-12 18:26:17 +03:00
Merge from 12-bit-tiff
This commit is contained in:
commit
94e3c75179
|
@ -475,7 +475,7 @@ class Image:
|
||||||
new.mode = im.mode
|
new.mode = im.mode
|
||||||
new.size = im.size
|
new.size = im.size
|
||||||
new.palette = self.palette
|
new.palette = self.palette
|
||||||
if im.mode == "P":
|
if im.mode == "P" and not new.palette:
|
||||||
from PIL import ImagePalette
|
from PIL import ImagePalette
|
||||||
new.palette = ImagePalette.ImagePalette()
|
new.palette = ImagePalette.ImagePalette()
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -54,6 +54,10 @@ import collections
|
||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
# Set these to true to force use of libtiff for reading or writing.
|
||||||
|
READ_LIBTIFF = False
|
||||||
|
WRITE_LIBTIFF= False
|
||||||
|
|
||||||
II = b"II" # little-endian (intel-style)
|
II = b"II" # little-endian (intel-style)
|
||||||
MM = b"MM" # big-endian (motorola-style)
|
MM = b"MM" # big-endian (motorola-style)
|
||||||
|
|
||||||
|
@ -147,6 +151,7 @@ OPEN_INFO = {
|
||||||
(II, 1, 1, 1, (8,), ()): ("L", "L"),
|
(II, 1, 1, 1, (8,), ()): ("L", "L"),
|
||||||
(II, 1, 1, 1, (8,8), (2,)): ("LA", "LA"),
|
(II, 1, 1, 1, (8,8), (2,)): ("LA", "LA"),
|
||||||
(II, 1, 1, 2, (8,), ()): ("L", "L;R"),
|
(II, 1, 1, 2, (8,), ()): ("L", "L;R"),
|
||||||
|
(II, 1, 1, 1, (12,), ()): ("I;16", "I;12"),
|
||||||
(II, 1, 1, 1, (16,), ()): ("I;16", "I;16"),
|
(II, 1, 1, 1, (16,), ()): ("I;16", "I;16"),
|
||||||
(II, 1, 2, 1, (16,), ()): ("I;16S", "I;16S"),
|
(II, 1, 2, 1, (16,), ()): ("I;16S", "I;16S"),
|
||||||
(II, 1, 1, 1, (32,), ()): ("I", "I;32N"),
|
(II, 1, 1, 1, (32,), ()): ("I", "I;32N"),
|
||||||
|
@ -617,8 +622,8 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
return args
|
return args
|
||||||
|
|
||||||
def _load_libtiff(self):
|
def _load_libtiff(self):
|
||||||
""" Overload method triggered when we detect a g3/g4 tiff
|
""" Overload method triggered when we detect a compressed tiff
|
||||||
Calls out to lib tiff """
|
Calls out to libtiff """
|
||||||
|
|
||||||
pixel = Image.Image.load(self)
|
pixel = Image.Image.load(self)
|
||||||
|
|
||||||
|
@ -633,7 +638,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
raise IOError("Not exactly one tile")
|
raise IOError("Not exactly one tile")
|
||||||
|
|
||||||
d, e, o, a = self.tile[0]
|
d, e, o, a = self.tile[0]
|
||||||
d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
|
d = Image._getdecoder(self.mode, 'libtiff', a, self.decoderconfig)
|
||||||
try:
|
try:
|
||||||
d.setimage(self.im, e)
|
d.setimage(self.im, e)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -759,11 +764,11 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
offsets = self.tag[STRIPOFFSETS]
|
offsets = self.tag[STRIPOFFSETS]
|
||||||
h = getscalar(ROWSPERSTRIP, ysize)
|
h = getscalar(ROWSPERSTRIP, ysize)
|
||||||
w = self.size[0]
|
w = self.size[0]
|
||||||
if self._compression in ["tiff_ccitt", "group3", "group4",
|
if READ_LIBTIFF or self._compression in ["tiff_ccitt", "group3", "group4",
|
||||||
"tiff_jpeg", "tiff_adobe_deflate",
|
"tiff_jpeg", "tiff_adobe_deflate",
|
||||||
"tiff_thunderscan", "tiff_deflate",
|
"tiff_thunderscan", "tiff_deflate",
|
||||||
"tiff_sgilog", "tiff_sgilog24",
|
"tiff_sgilog", "tiff_sgilog24",
|
||||||
"tiff_raw_16"]:
|
"tiff_raw_16"]:
|
||||||
## if Image.DEBUG:
|
## if Image.DEBUG:
|
||||||
## print "Activating g4 compression for whole file"
|
## print "Activating g4 compression for whole file"
|
||||||
|
|
||||||
|
@ -810,7 +815,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
# we're expecting image byte order. So, if the rawmode
|
# we're expecting image byte order. So, if the rawmode
|
||||||
# contains I;16, we need to convert from native to image
|
# contains I;16, we need to convert from native to image
|
||||||
# byte order.
|
# byte order.
|
||||||
if self.mode in ('I;16B', 'I;16'):
|
if self.mode in ('I;16B', 'I;16') and 'I;16' in rawmode:
|
||||||
rawmode = 'I;16N'
|
rawmode = 'I;16N'
|
||||||
|
|
||||||
# Offset in the tile tuple is 0, we go from 0,0 to
|
# Offset in the tile tuple is 0, we go from 0,0 to
|
||||||
|
@ -917,11 +922,12 @@ def _save(im, fp, filename):
|
||||||
ifd = ImageFileDirectory(prefix)
|
ifd = ImageFileDirectory(prefix)
|
||||||
|
|
||||||
compression = im.encoderinfo.get('compression',im.info.get('compression','raw'))
|
compression = im.encoderinfo.get('compression',im.info.get('compression','raw'))
|
||||||
libtiff = compression in ["tiff_ccitt", "group3", "group4",
|
|
||||||
"tiff_jpeg", "tiff_adobe_deflate",
|
libtiff = WRITE_LIBTIFF or compression in ["tiff_ccitt", "group3", "group4",
|
||||||
"tiff_thunderscan", "tiff_deflate",
|
"tiff_jpeg", "tiff_adobe_deflate",
|
||||||
"tiff_sgilog", "tiff_sgilog24",
|
"tiff_thunderscan", "tiff_deflate",
|
||||||
"tiff_raw_16"]
|
"tiff_sgilog", "tiff_sgilog24",
|
||||||
|
"tiff_raw_16"]
|
||||||
|
|
||||||
# required for color libtiff images
|
# required for color libtiff images
|
||||||
ifd[PLANAR_CONFIGURATION] = getattr(im, '_planar_configuration', 1)
|
ifd[PLANAR_CONFIGURATION] = getattr(im, '_planar_configuration', 1)
|
||||||
|
@ -1057,8 +1063,8 @@ def _save(im, fp, filename):
|
||||||
if Image.DEBUG:
|
if Image.DEBUG:
|
||||||
print (atts)
|
print (atts)
|
||||||
|
|
||||||
# libtiff always returns the bytes in native order.
|
# libtiff always expects the bytes in native order.
|
||||||
# we're expecting image byte order. So, if the rawmode
|
# we're storing image byte order. So, if the rawmode
|
||||||
# contains I;16, we need to convert from native to image
|
# contains I;16, we need to convert from native to image
|
||||||
# byte order.
|
# byte order.
|
||||||
if im.mode in ('I;16B', 'I;16'):
|
if im.mode in ('I;16B', 'I;16'):
|
||||||
|
@ -1066,7 +1072,7 @@ def _save(im, fp, filename):
|
||||||
|
|
||||||
a = (rawmode, compression, _fp, filename, atts)
|
a = (rawmode, compression, _fp, filename, atts)
|
||||||
# print (im.mode, compression, a, im.encoderconfig)
|
# print (im.mode, compression, a, im.encoderconfig)
|
||||||
e = Image._getencoder(im.mode, compression, a, im.encoderconfig)
|
e = Image._getencoder(im.mode, 'libtiff', a, im.encoderconfig)
|
||||||
e.setimage(im.im, (0,0)+im.size)
|
e.setimage(im.im, (0,0)+im.size)
|
||||||
while 1:
|
while 1:
|
||||||
l, s, d = e.encode(16*1024) # undone, change to self.decodermaxblock
|
l, s, d = e.encode(16*1024) # undone, change to self.decodermaxblock
|
||||||
|
|
Binary file not shown.
BIN
Tests/images/12in16bit.tif
Normal file
BIN
Tests/images/12in16bit.tif
Normal file
Binary file not shown.
BIN
Tests/images/16bit.cropped.tif
Normal file
BIN
Tests/images/16bit.cropped.tif
Normal file
Binary file not shown.
|
@ -27,3 +27,22 @@ def test_optimize():
|
||||||
return len(file.getvalue())
|
return len(file.getvalue())
|
||||||
assert_equal(test(0), 800)
|
assert_equal(test(0), 800)
|
||||||
assert_equal(test(1), 38)
|
assert_equal(test(1), 38)
|
||||||
|
|
||||||
|
def test_roundtrip():
|
||||||
|
out = tempfile('temp.gif')
|
||||||
|
im = lena()
|
||||||
|
im.save(out)
|
||||||
|
reread = Image.open(out)
|
||||||
|
|
||||||
|
assert_image_similar(reread.convert('RGB'), im, 50)
|
||||||
|
|
||||||
|
def test_roundtrip2():
|
||||||
|
#see https://github.com/python-imaging/Pillow/issues/403
|
||||||
|
out = 'temp.gif'#tempfile('temp.gif')
|
||||||
|
im = Image.open('Images/lena.gif')
|
||||||
|
im2 = im.copy()
|
||||||
|
im2.save(out)
|
||||||
|
reread = Image.open(out)
|
||||||
|
|
||||||
|
assert_image_similar(reread.convert('RGB'), lena(), 50)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from tester import *
|
from tester import *
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image, TiffImagePlugin
|
||||||
|
|
||||||
codecs = dir(Image.core)
|
codecs = dir(Image.core)
|
||||||
|
|
||||||
if "group4_encoder" not in codecs or "group4_decoder" not in codecs:
|
if "libtiff_encoder" not in codecs or "libtiff_decoder" not in codecs:
|
||||||
skip("tiff support not available")
|
skip("tiff support not available")
|
||||||
|
|
||||||
def _assert_noerr(im):
|
def _assert_noerr(im):
|
||||||
|
@ -118,7 +118,7 @@ def test_g3_compression():
|
||||||
assert_image_equal(reread, i)
|
assert_image_equal(reread, i)
|
||||||
|
|
||||||
def test_little_endian():
|
def test_little_endian():
|
||||||
im = Image.open('Tests/images/12bit.deflate.tif')
|
im = Image.open('Tests/images/16bit.deflate.tif')
|
||||||
assert_equal(im.getpixel((0,0)), 480)
|
assert_equal(im.getpixel((0,0)), 480)
|
||||||
assert_equal(im.mode, 'I;16')
|
assert_equal(im.mode, 'I;16')
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ def test_little_endian():
|
||||||
# on big endian, we'll get back mode = 'I;16B' here.
|
# on big endian, we'll get back mode = 'I;16B' here.
|
||||||
|
|
||||||
def test_big_endian():
|
def test_big_endian():
|
||||||
im = Image.open('Tests/images/12bit.MM.deflate.tif')
|
im = Image.open('Tests/images/16bit.MM.deflate.tif')
|
||||||
|
|
||||||
assert_equal(im.getpixel((0,0)), 480)
|
assert_equal(im.getpixel((0,0)), 480)
|
||||||
assert_equal(im.mode, 'I;16B')
|
assert_equal(im.mode, 'I;16B')
|
||||||
|
@ -178,6 +178,31 @@ def test_g4_string_info():
|
||||||
reread = Image.open(out)
|
reread = Image.open(out)
|
||||||
assert_equal('temp.tif', reread.tag[269])
|
assert_equal('temp.tif', reread.tag[269])
|
||||||
|
|
||||||
|
def test_12bit_rawmode():
|
||||||
|
""" Are we generating the same interpretation of the image as Imagemagick is? """
|
||||||
|
TiffImagePlugin.READ_LIBTIFF = True
|
||||||
|
#Image.DEBUG = True
|
||||||
|
im = Image.open('Tests/images/12bit.cropped.tif')
|
||||||
|
im.load()
|
||||||
|
TiffImagePlugin.READ_LIBTIFF = False
|
||||||
|
# to make the target --
|
||||||
|
# convert 12bit.cropped.tif -depth 16 tmp.tif
|
||||||
|
# convert tmp.tif -evaluate RightShift 4 12in16bit2.tif
|
||||||
|
# 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')
|
||||||
|
|
||||||
|
if Image.DEBUG:
|
||||||
|
print (im.getpixel((0,0)))
|
||||||
|
print (im.getpixel((0,1)))
|
||||||
|
print (im.getpixel((0,2)))
|
||||||
|
|
||||||
|
print (im2.getpixel((0,0)))
|
||||||
|
print (im2.getpixel((0,1)))
|
||||||
|
print (im2.getpixel((0,2)))
|
||||||
|
|
||||||
|
assert_image_equal(im, im2)
|
||||||
|
|
||||||
def test_blur():
|
def test_blur():
|
||||||
# test case from irc, how to do blur on b/w image and save to compressed tif.
|
# test case from irc, how to do blur on b/w image and save to compressed tif.
|
||||||
|
|
|
@ -6,7 +6,7 @@ from test_file_libtiff import _assert_noerr
|
||||||
|
|
||||||
codecs = dir(Image.core)
|
codecs = dir(Image.core)
|
||||||
|
|
||||||
if "group4_encoder" not in codecs or "group4_decoder" not in codecs:
|
if "libtiff_encoder" not in codecs or "libtiff_decoder" not in codecs:
|
||||||
skip("tiff support not available")
|
skip("tiff support not available")
|
||||||
|
|
||||||
""" The small lena image was failing on open in the libtiff
|
""" The small lena image was failing on open in the libtiff
|
||||||
|
|
|
@ -74,7 +74,7 @@ def test_xyres_tiff():
|
||||||
|
|
||||||
|
|
||||||
def test_little_endian():
|
def test_little_endian():
|
||||||
im = Image.open('Tests/images/12bit.cropped.tif')
|
im = Image.open('Tests/images/16bit.cropped.tif')
|
||||||
assert_equal(im.getpixel((0,0)), 480)
|
assert_equal(im.getpixel((0,0)), 480)
|
||||||
assert_equal(im.mode, 'I;16')
|
assert_equal(im.mode, 'I;16')
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ def test_little_endian():
|
||||||
|
|
||||||
|
|
||||||
def test_big_endian():
|
def test_big_endian():
|
||||||
im = Image.open('Tests/images/12bit.MM.cropped.tif')
|
im = Image.open('Tests/images/16bit.MM.cropped.tif')
|
||||||
assert_equal(im.getpixel((0,0)), 480)
|
assert_equal(im.getpixel((0,0)), 480)
|
||||||
assert_equal(im.mode, 'I;16B')
|
assert_equal(im.mode, 'I;16B')
|
||||||
|
|
||||||
|
@ -102,3 +102,29 @@ def test_big_endian():
|
||||||
else:
|
else:
|
||||||
assert_equal(b[0], b'\x01')
|
assert_equal(b[0], b'\x01')
|
||||||
assert_equal(b[1], b'\xe0')
|
assert_equal(b[1], b'\xe0')
|
||||||
|
|
||||||
|
|
||||||
|
def test_12bit_rawmode():
|
||||||
|
""" Are we generating the same interpretation of the image as Imagemagick is? """
|
||||||
|
|
||||||
|
#Image.DEBUG = True
|
||||||
|
im = Image.open('Tests/images/12bit.cropped.tif')
|
||||||
|
|
||||||
|
# to make the target --
|
||||||
|
# convert 12bit.cropped.tif -depth 16 tmp.tif
|
||||||
|
# convert tmp.tif -evaluate RightShift 4 12in16bit2.tif
|
||||||
|
# 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')
|
||||||
|
|
||||||
|
if Image.DEBUG:
|
||||||
|
print (im.getpixel((0,0)))
|
||||||
|
print (im.getpixel((0,1)))
|
||||||
|
print (im.getpixel((0,2)))
|
||||||
|
|
||||||
|
print (im2.getpixel((0,0)))
|
||||||
|
print (im2.getpixel((0,1)))
|
||||||
|
print (im2.getpixel((0,2)))
|
||||||
|
|
||||||
|
assert_image_equal(im, im2)
|
||||||
|
|
|
@ -38,12 +38,12 @@ def test_8bit():
|
||||||
im = Image.open('Images/lena.jpg')
|
im = Image.open('Images/lena.jpg')
|
||||||
_test_float_conversion(im.convert('L'))
|
_test_float_conversion(im.convert('L'))
|
||||||
|
|
||||||
def test_12bit():
|
def test_16bit():
|
||||||
im = Image.open('Tests/images/12bit.cropped.tif')
|
im = Image.open('Tests/images/16bit.cropped.tif')
|
||||||
_test_float_conversion(im)
|
_test_float_conversion(im)
|
||||||
|
|
||||||
def test_12bit_workaround():
|
def test_16bit_workaround():
|
||||||
im = Image.open('Tests/images/12bit.cropped.tif')
|
im = Image.open('Tests/images/16bit.cropped.tif')
|
||||||
_test_float_conversion(im.convert('I'))
|
_test_float_conversion(im.convert('I'))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ def _test_img_equals_nparray(img, np):
|
||||||
|
|
||||||
|
|
||||||
def test_16bit():
|
def test_16bit():
|
||||||
img = Image.open('Tests/images/12bit.cropped.tif')
|
img = Image.open('Tests/images/16bit.cropped.tif')
|
||||||
np_img = numpy.array(img)
|
np_img = numpy.array(img)
|
||||||
_test_img_equals_nparray(img, np_img)
|
_test_img_equals_nparray(img, np_img)
|
||||||
assert_equal(np_img.dtype, numpy.dtype('<u2'))
|
assert_equal(np_img.dtype, numpy.dtype('<u2'))
|
||||||
|
|
23
_imaging.c
23
_imaging.c
|
@ -3316,27 +3316,8 @@ static PyMethodDef functions[] = {
|
||||||
#endif
|
#endif
|
||||||
{"tiff_lzw_decoder", (PyCFunction)PyImaging_TiffLzwDecoderNew, 1},
|
{"tiff_lzw_decoder", (PyCFunction)PyImaging_TiffLzwDecoderNew, 1},
|
||||||
#ifdef HAVE_LIBTIFF
|
#ifdef HAVE_LIBTIFF
|
||||||
{"tiff_ccitt_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
{"libtiff_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
||||||
{"group3_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
{"libtiff_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
||||||
{"group4_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
|
||||||
{"tiff_jpeg_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
|
||||||
{"tiff_adobe_deflate_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
|
||||||
{"tiff_thunderscan_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
|
||||||
{"tiff_deflate_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
|
||||||
{"tiff_sgilog_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
|
||||||
{"tiff_sgilog24_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
|
||||||
{"tiff_raw_16_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
|
||||||
|
|
||||||
{"tiff_ccitt_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
|
||||||
{"group3_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
|
||||||
{"group4_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
|
||||||
{"tiff_jpeg_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
|
||||||
{"tiff_adobe_deflate_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
|
||||||
{"tiff_thunderscan_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
|
||||||
{"tiff_deflate_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
|
||||||
{"tiff_sgilog_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
|
||||||
{"tiff_sgilog24_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
|
||||||
{"tiff_raw_16_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
|
||||||
#endif
|
#endif
|
||||||
{"msp_decoder", (PyCFunction)PyImaging_MspDecoderNew, 1},
|
{"msp_decoder", (PyCFunction)PyImaging_MspDecoderNew, 1},
|
||||||
{"packbits_decoder", (PyCFunction)PyImaging_PackbitsDecoderNew, 1},
|
{"packbits_decoder", (PyCFunction)PyImaging_PackbitsDecoderNew, 1},
|
||||||
|
|
43
decode.c
43
decode.c
|
@ -427,7 +427,6 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
|
||||||
char* mode;
|
char* mode;
|
||||||
char* rawmode;
|
char* rawmode;
|
||||||
char* compname;
|
char* compname;
|
||||||
int compression;
|
|
||||||
int fp;
|
int fp;
|
||||||
|
|
||||||
if (! PyArg_ParseTuple(args, "sssi", &mode, &rawmode, &compname, &fp))
|
if (! PyArg_ParseTuple(args, "sssi", &mode, &rawmode, &compname, &fp))
|
||||||
|
@ -435,46 +434,6 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
|
||||||
|
|
||||||
TRACE(("new tiff decoder %s\n", compname));
|
TRACE(("new tiff decoder %s\n", compname));
|
||||||
|
|
||||||
/* UNDONE -- we can probably do almost any arbitrary compression here,
|
|
||||||
* since we're effective passing in the whole file in one shot and
|
|
||||||
* getting back the data row by row. V2 maybe
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (strcasecmp(compname, "tiff_ccitt") == 0) {
|
|
||||||
compression = COMPRESSION_CCITTRLE;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "group3") == 0) {
|
|
||||||
compression = COMPRESSION_CCITTFAX3;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "group4") == 0) {
|
|
||||||
compression = COMPRESSION_CCITTFAX4;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_jpeg") == 0) {
|
|
||||||
compression = COMPRESSION_OJPEG;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_adobe_deflate") == 0) {
|
|
||||||
compression = COMPRESSION_ADOBE_DEFLATE;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_thunderscan") == 0) {
|
|
||||||
compression = COMPRESSION_THUNDERSCAN;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_deflate") == 0) {
|
|
||||||
compression = COMPRESSION_DEFLATE;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_sgilog") == 0) {
|
|
||||||
compression = COMPRESSION_SGILOG;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_sgilog24") == 0) {
|
|
||||||
compression = COMPRESSION_SGILOG24;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_raw_16") == 0) {
|
|
||||||
compression = COMPRESSION_CCITTRLEW;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "unknown compession");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
decoder = PyImaging_DecoderNew(sizeof(TIFFSTATE));
|
decoder = PyImaging_DecoderNew(sizeof(TIFFSTATE));
|
||||||
if (decoder == NULL)
|
if (decoder == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -482,7 +441,7 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
|
||||||
if (get_unpacker(decoder, mode, rawmode) < 0)
|
if (get_unpacker(decoder, mode, rawmode) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (! ImagingLibTiffInit(&decoder->state, compression, fp)) {
|
if (! ImagingLibTiffInit(&decoder->state, fp)) {
|
||||||
Py_DECREF(decoder);
|
Py_DECREF(decoder);
|
||||||
PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed");
|
PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
42
encode.c
42
encode.c
|
@ -673,7 +673,6 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
|
||||||
char* rawmode;
|
char* rawmode;
|
||||||
char* compname;
|
char* compname;
|
||||||
char* filename;
|
char* filename;
|
||||||
int compression;
|
|
||||||
int fp;
|
int fp;
|
||||||
|
|
||||||
PyObject *dir;
|
PyObject *dir;
|
||||||
|
@ -706,47 +705,6 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
|
||||||
|
|
||||||
TRACE(("new tiff encoder %s fp: %d, filename: %s \n", compname, fp, filename));
|
TRACE(("new tiff encoder %s fp: %d, filename: %s \n", compname, fp, filename));
|
||||||
|
|
||||||
/* UNDONE -- we can probably do almost any arbitrary compression here,
|
|
||||||
* so long as we're doing row/stripe based actions and not tiles.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (strcasecmp(compname, "tiff_ccitt") == 0) {
|
|
||||||
compression = COMPRESSION_CCITTRLE;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "group3") == 0) {
|
|
||||||
compression = COMPRESSION_CCITTFAX3;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "group4") == 0) {
|
|
||||||
compression = COMPRESSION_CCITTFAX4;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_jpeg") == 0) {
|
|
||||||
compression = COMPRESSION_OJPEG;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_adobe_deflate") == 0) {
|
|
||||||
compression = COMPRESSION_ADOBE_DEFLATE;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_thunderscan") == 0) {
|
|
||||||
compression = COMPRESSION_THUNDERSCAN;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_deflate") == 0) {
|
|
||||||
compression = COMPRESSION_DEFLATE;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_sgilog") == 0) {
|
|
||||||
compression = COMPRESSION_SGILOG;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_sgilog24") == 0) {
|
|
||||||
compression = COMPRESSION_SGILOG24;
|
|
||||||
|
|
||||||
} else if (strcasecmp(compname, "tiff_raw_16") == 0) {
|
|
||||||
compression = COMPRESSION_CCITTRLEW;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "unknown compession");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE(("Found compression: %d\n", compression));
|
|
||||||
|
|
||||||
encoder = PyImaging_EncoderNew(sizeof(TIFFSTATE));
|
encoder = PyImaging_EncoderNew(sizeof(TIFFSTATE));
|
||||||
if (encoder == NULL)
|
if (encoder == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -142,11 +142,11 @@ void _tiffUnmapProc(thandle_t hdata, tdata_t base, toff_t size) {
|
||||||
(void) hdata; (void) base; (void) size;
|
(void) hdata; (void) base; (void) size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImagingLibTiffInit(ImagingCodecState state, int compression, int fp) {
|
int ImagingLibTiffInit(ImagingCodecState state, int fp) {
|
||||||
TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
|
TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
|
||||||
|
|
||||||
TRACE(("initing libtiff\n"));
|
TRACE(("initing libtiff\n"));
|
||||||
TRACE(("Compression: %d, filepointer: %d \n", compression, fp));
|
TRACE(("filepointer: %d \n", fp));
|
||||||
TRACE(("State: count %d, state %d, x %d, y %d, ystep %d\n", state->count, state->state,
|
TRACE(("State: count %d, state %d, x %d, y %d, ystep %d\n", state->count, state->state,
|
||||||
state->x, state->y, state->ystep));
|
state->x, state->y, state->ystep));
|
||||||
TRACE(("State: xsize %d, ysize %d, xoff %d, yoff %d \n", state->xsize, state->ysize,
|
TRACE(("State: xsize %d, ysize %d, xoff %d, yoff %d \n", state->xsize, state->ysize,
|
||||||
|
|
|
@ -38,7 +38,7 @@ typedef struct {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern int ImagingLibTiffInit(ImagingCodecState state, int compression, int fp);
|
extern int ImagingLibTiffInit(ImagingCodecState state, int fp);
|
||||||
extern int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp);
|
extern int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp);
|
||||||
extern int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...);
|
extern int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...);
|
||||||
|
|
||||||
|
|
|
@ -795,6 +795,60 @@ unpackI16N_I16(UINT8* out, const UINT8* in, int pixels){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unpackI12_I16(UINT8* out, const UINT8* in, int pixels){
|
||||||
|
/* Fillorder 1/MSB -> LittleEndian, for 12bit integer greyscale tiffs.
|
||||||
|
|
||||||
|
According to the TIFF spec:
|
||||||
|
|
||||||
|
FillOrder = 2 should be used only when BitsPerSample = 1 and
|
||||||
|
the data is either uncompressed or compressed using CCITT 1D
|
||||||
|
or 2D compression, to avoid potentially ambigous situations.
|
||||||
|
|
||||||
|
Yeah. I thought so. We'll see how well people read the spec.
|
||||||
|
We've got several fillorder=2 modes in TiffImagePlugin.py
|
||||||
|
|
||||||
|
There's no spec I can find. It appears that the in storage
|
||||||
|
layout is: 00 80 00 ... -> (128 , 0 ...). The samples are
|
||||||
|
stored in a single big bitian 12bit block, but need to be
|
||||||
|
pulled out to little endian format to be stored in a 2 byte
|
||||||
|
int.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int i;
|
||||||
|
UINT16 pixel;
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
UINT8* tmp = (UINT8 *)&pixel;
|
||||||
|
#endif
|
||||||
|
UINT16* out16 = (UINT16 *)out;
|
||||||
|
for (i = 0; i < pixels-1; i+=2) {
|
||||||
|
pixel = (((UINT16) in[0]) << 4 ) + (in[1] >>4);
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
out[0] = tmp[1]; out[1] = tmp[0];
|
||||||
|
#else
|
||||||
|
out16[0] = pixel;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pixel = (((UINT16) (in[1] & 0x0F)) << 8) + in[2];
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
out[2] = tmp[1]; out[3] = tmp[0];
|
||||||
|
#else
|
||||||
|
out16[1] = pixel;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
in += 3; out16 += 2; out+=4;
|
||||||
|
}
|
||||||
|
if (i == pixels-1) {
|
||||||
|
pixel = (((UINT16) in[0]) << 4 ) + (in[1] >>4);
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
out[0] = tmp[1]; out[1] = tmp[0];
|
||||||
|
#else
|
||||||
|
out16[0] = pixel;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
copy1(UINT8* out, const UINT8* in, int pixels)
|
copy1(UINT8* out, const UINT8* in, int pixels)
|
||||||
{
|
{
|
||||||
|
@ -1163,6 +1217,8 @@ static struct {
|
||||||
{"I;16L", "I;16N", 16, unpackI16N_I16}, // LibTiff native->image endian.
|
{"I;16L", "I;16N", 16, unpackI16N_I16}, // LibTiff native->image endian.
|
||||||
{"I;16B", "I;16N", 16, unpackI16N_I16B},
|
{"I;16B", "I;16N", 16, unpackI16N_I16B},
|
||||||
|
|
||||||
|
{"I;16", "I;12", 12, unpackI12_I16}, // 12 bit Tiffs stored in 16bits.
|
||||||
|
|
||||||
{NULL} /* sentinel */
|
{NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user