mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 09:57:43 +03:00 
			
		
		
		
	Merge pull request #417 from wiredfool/libtiff-save2
Updates for saving color tiffs w/compression using libtiff
This commit is contained in:
		
						commit
						f5fb2d7e7d
					
				| 
						 | 
				
			
			@ -54,7 +54,9 @@ import collections
 | 
			
		|||
import itertools
 | 
			
		||||
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)
 | 
			
		||||
MM = b"MM" # big-endian (motorola-style)
 | 
			
		||||
| 
						 | 
				
			
			@ -149,6 +151,7 @@ OPEN_INFO = {
 | 
			
		|||
    (II, 1, 1, 1, (8,), ()): ("L", "L"),
 | 
			
		||||
    (II, 1, 1, 1, (8,8), (2,)): ("LA", "LA"),
 | 
			
		||||
    (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, 2, 1, (16,), ()): ("I;16S", "I;16S"),
 | 
			
		||||
    (II, 1, 1, 1, (32,), ()): ("I", "I;32N"),
 | 
			
		||||
| 
						 | 
				
			
			@ -675,8 +678,8 @@ class TiffImageFile(ImageFile.ImageFile):
 | 
			
		|||
        return args
 | 
			
		||||
 | 
			
		||||
    def _load_libtiff(self):
 | 
			
		||||
        """ Overload method triggered when we detect a g3/g4 tiff
 | 
			
		||||
            Calls out to lib tiff """
 | 
			
		||||
        """ Overload method triggered when we detect a compressed tiff
 | 
			
		||||
            Calls out to libtiff """
 | 
			
		||||
 | 
			
		||||
        pixel = Image.Image.load(self)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -691,7 +694,7 @@ class TiffImageFile(ImageFile.ImageFile):
 | 
			
		|||
            raise IOError("Not exactly one tile")
 | 
			
		||||
 | 
			
		||||
        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:
 | 
			
		||||
            d.setimage(self.im, e)
 | 
			
		||||
        except ValueError:
 | 
			
		||||
| 
						 | 
				
			
			@ -817,7 +820,7 @@ class TiffImageFile(ImageFile.ImageFile):
 | 
			
		|||
            offsets = self.tag[STRIPOFFSETS]
 | 
			
		||||
            h = getscalar(ROWSPERSTRIP, ysize)
 | 
			
		||||
            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_thunderscan", "tiff_deflate",
 | 
			
		||||
                                                     "tiff_sgilog", "tiff_sgilog24",
 | 
			
		||||
| 
						 | 
				
			
			@ -868,7 +871,7 @@ 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'):
 | 
			
		||||
                if self.mode in ('I;16B', 'I;16') and 'I;16' in rawmode:
 | 
			
		||||
                    rawmode = 'I;16N'
 | 
			
		||||
 | 
			
		||||
                # Offset in the tile tuple is 0, we go from 0,0 to
 | 
			
		||||
| 
						 | 
				
			
			@ -975,12 +978,16 @@ def _save(im, fp, filename):
 | 
			
		|||
    ifd = ImageFileDirectory(prefix)
 | 
			
		||||
 | 
			
		||||
    compression = im.encoderinfo.get('compression',im.info.get('compression','raw'))
 | 
			
		||||
    libtiff = compression in ["tiff_ccitt", "group3", "group4",
 | 
			
		||||
 | 
			
		||||
    libtiff = WRITE_LIBTIFF or compression in ["tiff_ccitt", "group3", "group4",
 | 
			
		||||
                                               "tiff_jpeg", "tiff_adobe_deflate",
 | 
			
		||||
                                               "tiff_thunderscan", "tiff_deflate",
 | 
			
		||||
                                               "tiff_sgilog", "tiff_sgilog24",
 | 
			
		||||
                                               "tiff_raw_16"]
 | 
			
		||||
 | 
			
		||||
    # required for color libtiff images
 | 
			
		||||
    ifd[PLANAR_CONFIGURATION] = getattr(im, '_planar_configuration', 1)
 | 
			
		||||
    
 | 
			
		||||
    # -- multi-page -- skip TIFF header on subsequent pages
 | 
			
		||||
    if not libtiff and fp.tell() == 0:
 | 
			
		||||
        # tiff header (write via IFD to get everything right)
 | 
			
		||||
| 
						 | 
				
			
			@ -1083,6 +1090,8 @@ def _save(im, fp, filename):
 | 
			
		|||
 | 
			
		||||
        blocklist =  [STRIPOFFSETS, STRIPBYTECOUNTS, ROWSPERSTRIP, ICCPROFILE] # ICC Profile crashes.
 | 
			
		||||
        atts={}
 | 
			
		||||
        # bits per sample is a single short in the tiff directory, not a list. 
 | 
			
		||||
        atts[BITSPERSAMPLE] = bits[0]
 | 
			
		||||
        # Merge the ones that we have with (optional) more bits from
 | 
			
		||||
        # the original file, e.g x,y resolution so that we can
 | 
			
		||||
        # save(load('')) == original file.
 | 
			
		||||
| 
						 | 
				
			
			@ -1100,8 +1109,8 @@ def _save(im, fp, filename):
 | 
			
		|||
                    continue
 | 
			
		||||
                if type(v) == tuple and len(v) > 2:
 | 
			
		||||
                    # List of ints?
 | 
			
		||||
                    # BitsPerSample is one example, I get (8,8,8)
 | 
			
		||||
                    # UNDONE
 | 
			
		||||
                    if type(v[0]) in (int, float):
 | 
			
		||||
                        atts[k] = list(v)
 | 
			
		||||
                    continue
 | 
			
		||||
                if type(v) == tuple and len(v) == 2:
 | 
			
		||||
                    # one rational tuple
 | 
			
		||||
| 
						 | 
				
			
			@ -1121,8 +1130,8 @@ def _save(im, fp, filename):
 | 
			
		|||
        if Image.DEBUG:
 | 
			
		||||
            print (atts)
 | 
			
		||||
 | 
			
		||||
        # libtiff always returns the bytes in native order.
 | 
			
		||||
        # we're expecting image byte order. So, if the rawmode
 | 
			
		||||
        # libtiff always expects the bytes in native order.
 | 
			
		||||
        # we're storing image byte order. So, if the rawmode
 | 
			
		||||
        # contains I;16, we need to convert from native to image
 | 
			
		||||
        # byte order.
 | 
			
		||||
        if im.mode in ('I;16B', 'I;16'):
 | 
			
		||||
| 
						 | 
				
			
			@ -1130,7 +1139,7 @@ def _save(im, fp, filename):
 | 
			
		|||
 | 
			
		||||
        a = (rawmode, compression, _fp, filename, atts)
 | 
			
		||||
        # 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)
 | 
			
		||||
        while 1:
 | 
			
		||||
            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.
										
									
								
							| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
from tester import *
 | 
			
		||||
 | 
			
		||||
from PIL import Image
 | 
			
		||||
from PIL import Image, TiffImagePlugin
 | 
			
		||||
 | 
			
		||||
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")
 | 
			
		||||
 | 
			
		||||
def _assert_noerr(im):
 | 
			
		||||
| 
						 | 
				
			
			@ -141,7 +141,7 @@ def test_g3_compression():
 | 
			
		|||
    assert_image_equal(reread, i)
 | 
			
		||||
 | 
			
		||||
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.mode, 'I;16')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +156,7 @@ def test_little_endian():
 | 
			
		|||
        
 | 
			
		||||
 | 
			
		||||
    out = tempfile("temp.tif")
 | 
			
		||||
    out = "temp.le.tif"
 | 
			
		||||
    #out = "temp.le.tif"
 | 
			
		||||
    im.save(out)
 | 
			
		||||
    reread = Image.open(out)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +166,7 @@ def test_little_endian():
 | 
			
		|||
    # on big endian, we'll get back mode = 'I;16B' here. 
 | 
			
		||||
    
 | 
			
		||||
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.mode, 'I;16B')
 | 
			
		||||
| 
						 | 
				
			
			@ -201,4 +201,87 @@ def test_g4_string_info():
 | 
			
		|||
    reread = Image.open(out)
 | 
			
		||||
    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():
 | 
			
		||||
    # test case from irc, how to do blur on b/w image and save to compressed tif. 
 | 
			
		||||
    from PIL import ImageFilter
 | 
			
		||||
    out = tempfile('temp.tif')
 | 
			
		||||
    im = Image.open('Tests/images/pport_g4.tif')
 | 
			
		||||
    im = im.convert('L')
 | 
			
		||||
 | 
			
		||||
    im=im.filter(ImageFilter.GaussianBlur(4))
 | 
			
		||||
    im.save(out, compression='tiff_adobe_deflate')
 | 
			
		||||
 | 
			
		||||
    im2 = Image.open(out)
 | 
			
		||||
    im2.load()
 | 
			
		||||
 | 
			
		||||
    assert_image_equal(im, im2)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_compressions():
 | 
			
		||||
    im = lena('RGB')
 | 
			
		||||
    out = tempfile('temp.tif')
 | 
			
		||||
 | 
			
		||||
    TiffImagePlugin.READ_LIBTIFF = True
 | 
			
		||||
    TiffImagePlugin.WRITE_LIBTIFF = True
 | 
			
		||||
 | 
			
		||||
    for compression in ('packbits', 'tiff_lzw'):
 | 
			
		||||
        im.save(out, compression=compression)
 | 
			
		||||
        im2 = Image.open(out)
 | 
			
		||||
        assert_image_equal(im, im2)
 | 
			
		||||
 | 
			
		||||
    im.save(out, compression='jpeg')
 | 
			
		||||
    im2 = Image.open(out)
 | 
			
		||||
    assert_image_similar(im, im2, 30)
 | 
			
		||||
                            
 | 
			
		||||
    TiffImagePlugin.READ_LIBTIFF = False
 | 
			
		||||
    TiffImagePlugin.WRITE_LIBTIFF = False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_cmyk_save():
 | 
			
		||||
    im = lena('CMYK')
 | 
			
		||||
    out = tempfile('temp.tif')
 | 
			
		||||
 | 
			
		||||
    im.save(out, compression='tiff_adobe_deflate')
 | 
			
		||||
    im2 = Image.open(out)
 | 
			
		||||
    assert_image_equal(im, im2)
 | 
			
		||||
 | 
			
		||||
def xtest_bw_compression_wRGB():
 | 
			
		||||
    """ This test passes, but when running all tests causes a failure due to
 | 
			
		||||
        output on stderr from the error thrown by libtiff. We need to capture that
 | 
			
		||||
        but not now"""
 | 
			
		||||
    
 | 
			
		||||
    im = lena('RGB')
 | 
			
		||||
    out = tempfile('temp.tif')
 | 
			
		||||
 | 
			
		||||
    assert_exception(IOError, lambda: im.save(out, compression='tiff_ccitt'))
 | 
			
		||||
    assert_exception(IOError, lambda: im.save(out, compression='group3'))
 | 
			
		||||
    assert_exception(IOError, lambda: im.save(out, compression='group4'))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ from test_file_libtiff import _assert_noerr
 | 
			
		|||
 | 
			
		||||
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")
 | 
			
		||||
 | 
			
		||||
""" The small lena image was failing on open in the libtiff
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,7 +74,7 @@ def test_xyres_tiff():
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
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.mode, 'I;16')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +89,7 @@ def test_little_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.mode, 'I;16B')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -102,3 +102,29 @@ def test_big_endian():
 | 
			
		|||
	else:
 | 
			
		||||
		assert_equal(b[0], b'\x01')
 | 
			
		||||
		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')
 | 
			
		||||
    _test_float_conversion(im.convert('L'))
 | 
			
		||||
 | 
			
		||||
def test_12bit():
 | 
			
		||||
    im = Image.open('Tests/images/12bit.cropped.tif')
 | 
			
		||||
def test_16bit():
 | 
			
		||||
    im = Image.open('Tests/images/16bit.cropped.tif')
 | 
			
		||||
    _test_float_conversion(im)
 | 
			
		||||
 | 
			
		||||
def test_12bit_workaround():
 | 
			
		||||
    im = Image.open('Tests/images/12bit.cropped.tif')
 | 
			
		||||
def test_16bit_workaround():
 | 
			
		||||
    im = Image.open('Tests/images/16bit.cropped.tif')
 | 
			
		||||
    _test_float_conversion(im.convert('I'))
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,7 +75,7 @@ def _test_img_equals_nparray(img, np):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
def test_16bit():
 | 
			
		||||
    img = Image.open('Tests/images/12bit.cropped.tif')
 | 
			
		||||
    img = Image.open('Tests/images/16bit.cropped.tif')
 | 
			
		||||
    np_img = numpy.array(img)
 | 
			
		||||
    _test_img_equals_nparray(img, np_img)
 | 
			
		||||
    assert_equal(np_img.dtype, numpy.dtype('<u2'))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										23
									
								
								_imaging.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								_imaging.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -3317,27 +3317,8 @@ static PyMethodDef functions[] = {
 | 
			
		|||
#endif
 | 
			
		||||
    {"tiff_lzw_decoder", (PyCFunction)PyImaging_TiffLzwDecoderNew, 1},
 | 
			
		||||
#ifdef HAVE_LIBTIFF
 | 
			
		||||
    {"tiff_ccitt_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
 | 
			
		||||
    {"group3_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 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},
 | 
			
		||||
    {"libtiff_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
 | 
			
		||||
    {"libtiff_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
 | 
			
		||||
#endif
 | 
			
		||||
    {"msp_decoder", (PyCFunction)PyImaging_MspDecoderNew, 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* rawmode;
 | 
			
		||||
    char* compname;
 | 
			
		||||
    int compression;
 | 
			
		||||
    int 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));
 | 
			
		||||
 | 
			
		||||
    /* 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));
 | 
			
		||||
    if (decoder == NULL)
 | 
			
		||||
        return NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -482,7 +441,7 @@ PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
 | 
			
		|||
    if (get_unpacker(decoder, mode, rawmode) < 0)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    if (! ImagingLibTiffInit(&decoder->state, compression, fp)) {
 | 
			
		||||
    if (! ImagingLibTiffInit(&decoder->state, fp)) {
 | 
			
		||||
        Py_DECREF(decoder);
 | 
			
		||||
        PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed");
 | 
			
		||||
        return NULL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										59
									
								
								encode.c
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								encode.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -673,7 +673,6 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
 | 
			
		|||
    char* rawmode;
 | 
			
		||||
    char* compname;
 | 
			
		||||
    char* filename;
 | 
			
		||||
    int compression;
 | 
			
		||||
    int fp;
 | 
			
		||||
 | 
			
		||||
    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));
 | 
			
		||||
 | 
			
		||||
    /* 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));
 | 
			
		||||
    if (encoder == NULL)
 | 
			
		||||
        return NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -780,8 +738,23 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
 | 
			
		|||
        } else if(PyList_Check(value)) {
 | 
			
		||||
            int len,i;
 | 
			
		||||
            float *floatav;
 | 
			
		||||
            int *intav;
 | 
			
		||||
            TRACE(("Setting from List: %d \n", (int)PyInt_AsLong(key)));
 | 
			
		||||
            len = (int)PyList_Size(value);
 | 
			
		||||
            if (len) {
 | 
			
		||||
                if (PyInt_Check(PyList_GetItem(value,0))) {
 | 
			
		||||
                    TRACE((" %d elements, setting as ints \n", len));
 | 
			
		||||
                    intav = malloc(sizeof(int)*len);
 | 
			
		||||
                    if (intav) {
 | 
			
		||||
                        for (i=0;i<len;i++) {
 | 
			
		||||
                            intav[i] = (int)PyInt_AsLong(PyList_GetItem(value,i));
 | 
			
		||||
                        }
 | 
			
		||||
                        status = ImagingLibTiffSetField(&encoder->state,
 | 
			
		||||
                                                        (ttag_t) PyInt_AsLong(key),
 | 
			
		||||
                                                        intav);
 | 
			
		||||
                        free(intav);
 | 
			
		||||
                    }       
 | 
			
		||||
                } else {
 | 
			
		||||
                    TRACE((" %d elements, setting as floats \n", len));
 | 
			
		||||
                    floatav = malloc(sizeof(float)*len);
 | 
			
		||||
                    if (floatav) {
 | 
			
		||||
| 
						 | 
				
			
			@ -793,6 +766,8 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
 | 
			
		|||
                                                        floatav);
 | 
			
		||||
                        free(floatav);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else if (PyFloat_Check(value)) {
 | 
			
		||||
            TRACE(("Setting from Float: %d, %f \n", (int)PyInt_AsLong(key),PyFloat_AsDouble(value)));
 | 
			
		||||
            status = ImagingLibTiffSetField(&encoder->state,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -142,11 +142,11 @@ void _tiffUnmapProc(thandle_t hdata, tdata_t base, toff_t 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;
 | 
			
		||||
 | 
			
		||||
    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,
 | 
			
		||||
		   state->x, state->y, state->ystep));
 | 
			
		||||
	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 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
 | 
			
		||||
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;16B", 	"I;16N",	    16,	    unpackI16N_I16B},
 | 
			
		||||
 | 
			
		||||
    {"I;16", 	"I;12",	        12,	    unpackI12_I16}, // 12 bit Tiffs stored in 16bits.
 | 
			
		||||
 | 
			
		||||
    {NULL} /* sentinel */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user