mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 07:57:27 +03:00 
			
		
		
		
	Merge branch 'master' of https://github.com/etienned/Pillow into etienned-master
This commit is contained in:
		
						commit
						b03abf2e58
					
				|  | @ -36,6 +36,7 @@ __version__ = "0.6" | |||
| 
 | ||||
| import array, struct | ||||
| from PIL import Image, ImageFile, _binary | ||||
| from JpegPresets import presets | ||||
| 
 | ||||
| i8 = _binary.i8 | ||||
| o8 = _binary.o8 | ||||
|  | @ -416,6 +417,31 @@ RAWMODE = { | |||
|     "YCbCr": "YCbCr", | ||||
| } | ||||
| 
 | ||||
| zigzag_index = ( 0,  1,  5,  6, 14, 15, 27, 28, | ||||
|                  2,  4,  7, 13, 16, 26, 29, 42, | ||||
|                  3,  8, 12, 17, 25, 30, 41, 43, | ||||
|                  9, 11, 18, 24, 31, 40, 44, 53, | ||||
|                 10, 19, 23, 32, 39, 45, 52, 54, | ||||
|                 20, 22, 33, 38, 46, 51, 55, 60, | ||||
|                 21, 34, 37, 47, 50, 56, 59, 61, | ||||
|                 35, 36, 48, 49, 57, 58, 62, 63) | ||||
| 
 | ||||
| samplings = { | ||||
|              (1, 1, 1, 1, 1, 1): 0, | ||||
|              (2, 1, 1, 1, 1, 1): 1, | ||||
|              (2, 2, 1, 1, 1, 1): 2, | ||||
|             } | ||||
| 
 | ||||
| def convert_dict_qtables(qtables): | ||||
|     qtables = [qtables[key] for key in xrange(len(qtables)) if qtables.has_key(key)] | ||||
|     for idx, table in enumerate(qtables): | ||||
|         qtables[idx] = [table[i] for i in zigzag_index] | ||||
|     return qtables | ||||
| 
 | ||||
| def get_sampling(im): | ||||
|     sampling = im.layer[0][1:3] + im.layer[1][1:3] + im.layer[2][1:3] | ||||
|     return samplings.get(sampling, -1) | ||||
| 
 | ||||
| def _save(im, fp, filename): | ||||
| 
 | ||||
|     try: | ||||
|  | @ -427,13 +453,72 @@ def _save(im, fp, filename): | |||
| 
 | ||||
|     dpi = info.get("dpi", (0, 0)) | ||||
| 
 | ||||
|     quality = info.get("quality", 0) | ||||
|     subsampling = info.get("subsampling", -1) | ||||
|     qtables = info.get("qtables") | ||||
| 
 | ||||
|     if quality == "keep": | ||||
|         quality = 0 | ||||
|         subsampling = "keep" | ||||
|         qtables = "keep" | ||||
|     elif quality in presets: | ||||
|         preset = presets[quality] | ||||
|         quality = 0 | ||||
|         subsampling = preset.get('subsampling', -1) | ||||
|         qtables = preset.get('quantization') | ||||
|     elif not isinstance(quality, int): | ||||
|         raise ValueError("Invalid quality setting") | ||||
|     else: | ||||
|         if subsampling in presets: | ||||
|             subsampling = presets[subsampling].get('subsampling', -1) | ||||
|         if qtables in presets: | ||||
|             qtables = presets[qtables].get('quantization') | ||||
| 
 | ||||
|     if subsampling == "4:4:4": | ||||
|         subsampling = 0 | ||||
|     elif subsampling == "4:2:2": | ||||
|         subsampling = 1 | ||||
|     elif subsampling == "4:1:1": | ||||
|         subsampling = 2 | ||||
|     elif subsampling == "keep": | ||||
|         if im.format != "JPEG": | ||||
|             raise ValueError("Cannot use 'keep' when original image is not a JPEG") | ||||
|         subsampling = get_sampling(im)     | ||||
| 
 | ||||
|     def validate_qtables(qtables): | ||||
|         if qtables is None: | ||||
|             return qtables | ||||
|         if isinstance(qtables, basestring): | ||||
|             try: | ||||
|                 lines = [int(num) for line in qtables.splitlines() | ||||
|                          for num in line.split('#', 1)[0].split()] | ||||
|             except ValueError: | ||||
|                 raise ValueError("Invalid quantization table") | ||||
|             else: | ||||
|                 qtables = [lines[s:s+64] for s in xrange(0, len(lines), 64)] | ||||
|         if isinstance(qtables, (tuple, list, dict)): | ||||
|             if isinstance(qtables, dict): | ||||
|                 qtables = convert_dict_qtables(qtables) | ||||
|             elif isinstance(qtables, tuple): | ||||
|                 qtables = list(qtables) | ||||
|             if not (0 < len(qtables) < 5): | ||||
|                 raise ValueError("None or too many quantization tables") | ||||
|             for idx, table in enumerate(qtables): | ||||
|                 try: | ||||
|                     if len(table) != 64: | ||||
|                         raise | ||||
|                     table = array.array('b', table) | ||||
|                 except TypeError: | ||||
|                     raise ValueError("Invalid quantization table") | ||||
|                 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") | ||||
|         qtables = getattr(im, "quantization", None) | ||||
|     qtables = validate_qtables(qtables) | ||||
| 
 | ||||
|     extra = b"" | ||||
| 
 | ||||
|  | @ -454,7 +539,7 @@ def _save(im, fp, filename): | |||
| 
 | ||||
|     # get keyword arguments | ||||
|     im.encoderconfig = ( | ||||
|         info.get("quality", 0), | ||||
|         quality, | ||||
|         # "progressive" is the official name, but older documentation | ||||
|         # says "progression" | ||||
|         # FIXME: issue a warning if the wrong form is used (post-1.1.7) | ||||
|  | @ -464,6 +549,7 @@ def _save(im, fp, filename): | |||
|         info.get("streamtype", 0), | ||||
|         dpi[0], dpi[1], | ||||
|         subsampling, | ||||
|         qtables, | ||||
|         extra, | ||||
|         info.get("exif", b"") | ||||
|         ) | ||||
|  |  | |||
							
								
								
									
										250
									
								
								PIL/JpegPresets.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								PIL/JpegPresets.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,250 @@ | |||
| """ | ||||
| JPEG quality settings equivalent to the Photoshop settings. | ||||
| 
 | ||||
| More presets can be added to the presets dict if needed. | ||||
| 
 | ||||
| Can be use when saving JPEG file. | ||||
| 
 | ||||
| To apply the preset, specify: | ||||
| 
 | ||||
|  - quality=preset name | ||||
|   | ||||
| To apply only the quantization table: | ||||
| 
 | ||||
| - qtables=preset name | ||||
| 
 | ||||
| To apply only the subsampling setting: | ||||
| 
 | ||||
| - subsampling=preset name | ||||
| 
 | ||||
| Example: | ||||
| 
 | ||||
|     im.save("image_name.jpg", quality="web_high") | ||||
| 
 | ||||
| 
 | ||||
| Subsampling | ||||
| ----------- | ||||
| 
 | ||||
| Subsampling is the practice of encoding images by implementing less resolution | ||||
| for chroma information than for luma information. | ||||
| (ref.: http://en.wikipedia.org/wiki/Chroma_subsampling) | ||||
|      | ||||
| Possible subsampling values are 0, 1 and 2 that correspond to 4:4:4, 4:2:2 and | ||||
| 4:1:1 (or 4:2:0?). | ||||
| 
 | ||||
| You can get the subsampling of a JPEG with the | ||||
| `JpegImagePlugin.get_subsampling(im)` function. | ||||
| 
 | ||||
| 
 | ||||
| Quantization tables | ||||
| ------------------- | ||||
| 
 | ||||
| They are values use by the DCT (Discrete cosine transform) to remove | ||||
| *unnecessary* information from the image (the lossy part of the compression). | ||||
| (ref.: http://en.wikipedia.org/wiki/Quantization_matrix#Quantization_matrices, | ||||
|        http://en.wikipedia.org/wiki/JPEG#Quantization) | ||||
| 
 | ||||
| You can get the quantization tables of a JPEG with: | ||||
| 
 | ||||
|     im.quantization | ||||
|      | ||||
| This will return a dict with a number of arrays. You can pass this dict directly | ||||
| as the qtables argument when saving a JPEG. | ||||
| 
 | ||||
| The tables format between im.quantization and quantization in presets differ in | ||||
| 3 ways: | ||||
| 
 | ||||
|  1. The base container of the preset is a list with sublists instead of dict. | ||||
|     dict[0] -> list[0], dict[1] -> list[1], ... | ||||
|      | ||||
|  2. Each table in a preset is a list instead of an array. | ||||
|   | ||||
|  3. The zigzag order is remove in the preset (needed by libjpeg >= 6a). | ||||
|   | ||||
| You can convert the dict format to the preset format with the | ||||
| `JpegImagePlugin.convert_dict_qtables(dict_qtables)` function. | ||||
| 
 | ||||
| Libjpeg ref.: http://www.jpegcameras.com/libjpeg/libjpeg-3.html | ||||
| 
 | ||||
| """ | ||||
| 
 | ||||
| presets = {  | ||||
|             'web_low':      {'subsampling':  2, # "4:1:1" | ||||
|                             'quantization': [ | ||||
|                                [20, 16, 25, 39, 50, 46, 62, 68, | ||||
|                                 16, 18, 23, 38, 38, 53, 65, 68, | ||||
|                                 25, 23, 31, 38, 53, 65, 68, 68, | ||||
|                                 39, 38, 38, 53, 65, 68, 68, 68, | ||||
|                                 50, 38, 53, 65, 68, 68, 68, 68, | ||||
|                                 46, 53, 65, 68, 68, 68, 68, 68, | ||||
|                                 62, 65, 68, 68, 68, 68, 68, 68, | ||||
|                                 68, 68, 68, 68, 68, 68, 68, 68], | ||||
|                                [21, 25, 32, 38, 54, 68, 68, 68, | ||||
|                                 25, 28, 24, 38, 54, 68, 68, 68, | ||||
|                                 32, 24, 32, 43, 66, 68, 68, 68, | ||||
|                                 38, 38, 43, 53, 68, 68, 68, 68, | ||||
|                                 54, 54, 66, 68, 68, 68, 68, 68, | ||||
|                                 68, 68, 68, 68, 68, 68, 68, 68, | ||||
|                                 68, 68, 68, 68, 68, 68, 68, 68, | ||||
|                                 68, 68, 68, 68, 68, 68, 68, 68] | ||||
|                             ]}, | ||||
|                              | ||||
|             'web_medium':   {'subsampling':  2, # "4:1:1" | ||||
|                             'quantization': [ | ||||
|                                [16, 11, 11, 16, 23, 27, 31, 30, | ||||
|                                 11, 12, 12, 15, 20, 23, 23, 30, | ||||
|                                 11, 12, 13, 16, 23, 26, 35, 47, | ||||
|                                 16, 15, 16, 23, 26, 37, 47, 64, | ||||
|                                 23, 20, 23, 26, 39, 51, 64, 64, | ||||
|                                 27, 23, 26, 37, 51, 64, 64, 64, | ||||
|                                 31, 23, 35, 47, 64, 64, 64, 64, | ||||
|                                 30, 30, 47, 64, 64, 64, 64, 64], | ||||
|                                [17, 15, 17, 21, 20, 26, 38, 48, | ||||
|                                 15, 19, 18, 17, 20, 26, 35, 43, | ||||
|                                 17, 18, 20, 22, 26, 30, 46, 53, | ||||
|                                 21, 17, 22, 28, 30, 39, 53, 64, | ||||
|                                 20, 20, 26, 30, 39, 48, 64, 64, | ||||
|                                 26, 26, 30, 39, 48, 63, 64, 64, | ||||
|                                 38, 35, 46, 53, 64, 64, 64, 64, | ||||
|                                 48, 43, 53, 64, 64, 64, 64, 64] | ||||
|                             ]}, | ||||
|                              | ||||
|             'web_high':     {'subsampling':  0, # "4:4:4" | ||||
|                             'quantization': [ | ||||
|                                [ 6,  4,  4,  6,  9, 11, 12, 16, | ||||
|                                  4,  5,  5,  6,  8, 10, 12, 12, | ||||
|                                  4,  5,  5,  6, 10, 12, 14, 19, | ||||
|                                  6,  6,  6, 11, 12, 15, 19, 28, | ||||
|                                  9,  8, 10, 12, 16, 20, 27, 31, | ||||
|                                 11, 10, 12, 15, 20, 27, 31, 31, | ||||
|                                 12, 12, 14, 19, 27, 31, 31, 31, | ||||
|                                 16, 12, 19, 28, 31, 31, 31, 31], | ||||
|                                [ 7,  7, 13, 24, 26, 31, 31, 31, | ||||
|                                  7, 12, 16, 21, 31, 31, 31, 31, | ||||
|                                 13, 16, 17, 31, 31, 31, 31, 31, | ||||
|                                 24, 21, 31, 31, 31, 31, 31, 31, | ||||
|                                 26, 31, 31, 31, 31, 31, 31, 31, | ||||
|                                 31, 31, 31, 31, 31, 31, 31, 31, | ||||
|                                 31, 31, 31, 31, 31, 31, 31, 31, | ||||
|                                 31, 31, 31, 31, 31, 31, 31, 31] | ||||
|                             ]}, | ||||
|                              | ||||
|             'web_very_high': {'subsampling':  0, # "4:4:4" | ||||
|                             'quantization': [ | ||||
|                                [ 2,  2,  2,  2,  3,  4,  5,  6, | ||||
|                                  2,  2,  2,  2,  3,  4,  5,  6, | ||||
|                                  2,  2,  2,  2,  4,  5,  7,  9, | ||||
|                                  2,  2,  2,  4,  5,  7,  9, 12, | ||||
|                                  3,  3,  4,  5,  8, 10, 12, 12, | ||||
|                                  4,  4,  5,  7, 10, 12, 12, 12, | ||||
|                                  5,  5,  7,  9, 12, 12, 12, 12, | ||||
|                                  6,  6,  9, 12, 12, 12, 12, 12], | ||||
|                                [ 3,  3,  5,  9, 13, 15, 15, 15, | ||||
|                                  3,  4,  6, 11, 14, 12, 12, 12, | ||||
|                                  5,  6,  9, 14, 12, 12, 12, 12, | ||||
|                                  9, 11, 14, 12, 12, 12, 12, 12, | ||||
|                                 13, 14, 12, 12, 12, 12, 12, 12, | ||||
|                                 15, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 15, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 15, 12, 12, 12, 12, 12, 12, 12] | ||||
|                             ]}, | ||||
|                              | ||||
|             'web_maximum':  {'subsampling':  0, # "4:4:4" | ||||
|                             'quantization': [ | ||||
|                                [ 1,  1,  1,  1,  1,  1,  1,  1,  | ||||
|                                  1,  1,  1,  1,  1,  1,  1,  1,  | ||||
|                                  1,  1,  1,  1,  1,  1,  1,  2,  | ||||
|                                  1,  1,  1,  1,  1,  1,  2,  2,  | ||||
|                                  1,  1,  1,  1,  1,  2,  2,  3,  | ||||
|                                  1,  1,  1,  1,  2,  2,  3,  3,  | ||||
|                                  1,  1,  1,  2,  2,  3,  3,  3,  | ||||
|                                  1,  1,  2,  2,  3,  3,  3,  3], | ||||
|                                [ 1,  1,  1,  2,  2,  3,  3,  3, | ||||
|                                  1,  1,  1,  2,  3,  3,  3,  3, | ||||
|                                  1,  1,  1,  3,  3,  3,  3,  3, | ||||
|                                  2,  2,  3,  3,  3,  3,  3,  3, | ||||
|                                  2,  3,  3,  3,  3,  3,  3,  3, | ||||
|                                  3,  3,  3,  3,  3,  3,  3,  3, | ||||
|                                  3,  3,  3,  3,  3,  3,  3,  3,  | ||||
|                                  3,  3,  3,  3,  3,  3,  3,  3] | ||||
|                             ]}, | ||||
|                              | ||||
|             'low':          {'subsampling':  2, # "4:1:1" | ||||
|                             'quantization': [ | ||||
|                                [18, 14, 14, 21, 30, 35, 34, 17, | ||||
|                                 14, 16, 16, 19, 26, 23, 12, 12, | ||||
|                                 14, 16, 17, 21, 23, 12, 12, 12, | ||||
|                                 21, 19, 21, 23, 12, 12, 12, 12, | ||||
|                                 30, 26, 23, 12, 12, 12, 12, 12, | ||||
|                                 35, 23, 12, 12, 12, 12, 12, 12, | ||||
|                                 34, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 17, 12, 12, 12, 12, 12, 12, 12], | ||||
|                                [20, 19, 22, 27, 20, 20, 17, 17, | ||||
|                                 19, 25, 23, 14, 14, 12, 12, 12, | ||||
|                                 22, 23, 14, 14, 12, 12, 12, 12, | ||||
|                                 27, 14, 14, 12, 12, 12, 12, 12, | ||||
|                                 20, 14, 12, 12, 12, 12, 12, 12, | ||||
|                                 20, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 17, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 17, 12, 12, 12, 12, 12, 12, 12] | ||||
|                             ]}, | ||||
|             'medium':       {'subsampling':  2, # "4:1:1" | ||||
|                             'quantization': [ | ||||
|                                [12,  8,  8, 12, 17, 21, 24, 17, | ||||
|                                  8,  9,  9, 11, 15, 19, 12, 12, | ||||
|                                  8,  9, 10, 12, 19, 12, 12, 12, | ||||
|                                 12, 11, 12, 21, 12, 12, 12, 12, | ||||
|                                 17, 15, 19, 12, 12, 12, 12, 12, | ||||
|                                 21, 19, 12, 12, 12, 12, 12, 12, | ||||
|                                 24, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 17, 12, 12, 12, 12, 12, 12, 12], | ||||
|                                [13, 11, 13, 16, 20, 20, 17, 17, | ||||
|                                 11, 14, 14, 14, 14, 12, 12, 12, | ||||
|                                 13, 14, 14, 14, 12, 12, 12, 12, | ||||
|                                 16, 14, 14, 12, 12, 12, 12, 12, | ||||
|                                 20, 14, 12, 12, 12, 12, 12, 12, | ||||
|                                 20, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 17, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 17, 12, 12, 12, 12, 12, 12, 12] | ||||
|                             ]}, | ||||
|                              | ||||
|             'high':         {'subsampling':  0, # "4:4:4" | ||||
|                             'quantization': [ | ||||
|                                [ 6,  4,  4,  6,  9, 11, 12, 16, | ||||
|                                  4,  5,  5,  6,  8, 10, 12, 12,  | ||||
|                                  4,  5,  5,  6, 10, 12, 12, 12, | ||||
|                                  6,  6,  6, 11, 12, 12, 12, 12, | ||||
|                                  9,  8, 10, 12, 12, 12, 12, 12, | ||||
|                                 11, 10, 12, 12, 12, 12, 12, 12, | ||||
|                                 12, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 16, 12, 12, 12, 12, 12, 12, 12], | ||||
|                                [ 7,  7, 13, 24, 20, 20, 17, 17, | ||||
|                                  7, 12, 16, 14, 14, 12, 12, 12, | ||||
|                                 13, 16, 14, 14, 12, 12, 12, 12, | ||||
|                                 24, 14, 14, 12, 12, 12, 12, 12, | ||||
|                                 20, 14, 12, 12, 12, 12, 12, 12, | ||||
|                                 20, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 17, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 17, 12, 12, 12, 12, 12, 12, 12] | ||||
|                             ]}, | ||||
|                              | ||||
|             'maximum':      {'subsampling':  0, # "4:4:4" | ||||
|                             'quantization': [ | ||||
|                                [ 2,  2,  2,  2,  3,  4,  5,  6, | ||||
|                                  2,  2,  2,  2,  3,  4,  5,  6, | ||||
|                                  2,  2,  2,  2,  4,  5,  7,  9, | ||||
|                                  2,  2,  2,  4,  5,  7,  9, 12, | ||||
|                                  3,  3,  4,  5,  8, 10, 12, 12, | ||||
|                                  4,  4,  5,  7, 10, 12, 12, 12, | ||||
|                                  5,  5,  7,  9, 12, 12, 12, 12, | ||||
|                                  6,  6,  9, 12, 12, 12, 12, 12], | ||||
|                                [ 3,  3,  5,  9, 13, 15, 15, 15, | ||||
|                                  3,  4,  6, 10, 14, 12, 12, 12, | ||||
|                                  5,  6,  9, 14, 12, 12, 12, 12, | ||||
|                                  9, 10, 14, 12, 12, 12, 12, 12, | ||||
|                                 13, 14, 12, 12, 12, 12, 12, 12, | ||||
|                                 15, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 15, 12, 12, 12, 12, 12, 12, 12, | ||||
|                                 15, 12, 12, 12, 12, 12, 12, 12] | ||||
|                             ]}, | ||||
|             } | ||||
							
								
								
									
										72
									
								
								encode.c
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								encode.c
									
									
									
									
									
								
							|  | @ -506,6 +506,69 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args) | |||
| 
 | ||||
| #include "Jpeg.h" | ||||
| 
 | ||||
| static unsigned int** get_qtables_arrays(PyObject* qtables) { | ||||
|     PyObject* tables; | ||||
|     PyObject* table; | ||||
|     PyObject* table_data; | ||||
|     int i, j, num_tables; | ||||
|     unsigned int **qarrays; | ||||
|      | ||||
|     if (qtables == Py_None) { | ||||
|         return NULL; | ||||
|     } | ||||
|      | ||||
|     if (!PySequence_Check(qtables)) { | ||||
|         PyErr_SetString(PyExc_ValueError, "Invalid quantization tables"); | ||||
|         return NULL; | ||||
|     } | ||||
|      | ||||
|     tables = PySequence_Fast(qtables, "expected a sequence"); | ||||
|     num_tables = PySequence_Size(qtables); | ||||
|     if (num_tables < 2 || num_tables > NUM_QUANT_TBLS) { | ||||
|         PyErr_SetString(PyExc_ValueError, "Not a valid numbers of quantization tables. Should be between 2 and 4."); | ||||
|         return NULL; | ||||
|     } | ||||
|     qarrays = (unsigned int**) PyMem_Malloc(num_tables * sizeof(unsigned int)); | ||||
|     if (!qarrays) { | ||||
|         Py_DECREF(tables); | ||||
|         PyErr_NoMemory(); | ||||
|         return NULL; | ||||
|     } | ||||
|     for (i = 0; i < num_tables; i++) { | ||||
|         table = PySequence_Fast_GET_ITEM(tables, i); | ||||
|         if (!PySequence_Check(table)) { | ||||
|             Py_DECREF(tables); | ||||
|             PyErr_SetString(PyExc_ValueError, "Invalid quantization tables"); | ||||
|             return NULL; | ||||
|         } | ||||
|         if (PySequence_Size(table) != DCTSIZE2) { | ||||
|             Py_DECREF(tables); | ||||
|             PyErr_SetString(PyExc_ValueError, "Invalid quantization tables"); | ||||
|             return NULL; | ||||
|         } | ||||
|         table_data = PySequence_Fast(table, "expected a sequence"); | ||||
|         qarrays[i] = (unsigned int*) PyMem_Malloc(DCTSIZE2 * sizeof(unsigned int)); | ||||
|         if (!qarrays[i]) { | ||||
|             Py_DECREF(tables); | ||||
|             PyErr_NoMemory(); | ||||
|             return NULL; | ||||
|         } | ||||
|         for (j = 0; j < DCTSIZE2; j++) { | ||||
|             qarrays[i][j] = PyInt_AS_LONG(PySequence_Fast_GET_ITEM(table_data, j)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Py_DECREF(tables); | ||||
| 
 | ||||
|     if (PyErr_Occurred()) { | ||||
|         PyMem_Free(qarrays); | ||||
|         qarrays = NULL; | ||||
|     } | ||||
| 
 | ||||
|     return qarrays; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| PyObject* | ||||
| PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) | ||||
| { | ||||
|  | @ -520,15 +583,17 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) | |||
|     int streamtype = 0; /* 0=interchange, 1=tables only, 2=image only */ | ||||
|     int xdpi = 0, ydpi = 0; | ||||
|     int subsampling = -1; /* -1=default, 0=none, 1=medium, 2=high */ | ||||
|     PyObject* qtables; | ||||
|     unsigned int **qarrays = NULL; | ||||
|     char* extra = NULL; | ||||
|     int extra_size; | ||||
|     char* rawExif = NULL; | ||||
|     int rawExifLen = 0; | ||||
| 
 | ||||
|     if (!PyArg_ParseTuple(args, "ss|iiiiiiii"PY_ARG_BYTES_LENGTH""PY_ARG_BYTES_LENGTH, | ||||
|     if (!PyArg_ParseTuple(args, "ss|iiiiiiiiO"PY_ARG_BYTES_LENGTH""PY_ARG_BYTES_LENGTH, | ||||
|                           &mode, &rawmode, &quality, | ||||
|                           &progressive, &smooth, &optimize, &streamtype, | ||||
|                           &xdpi, &ydpi, &subsampling, &extra, &extra_size, | ||||
|                           &xdpi, &ydpi, &subsampling, &qtables, &extra, &extra_size, | ||||
|                           &rawExif, &rawExifLen)) | ||||
| 	return NULL; | ||||
| 
 | ||||
|  | @ -539,6 +604,8 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) | |||
|     if (get_packer(encoder, mode, rawmode) < 0) | ||||
| 	return NULL; | ||||
| 
 | ||||
|     qarrays = get_qtables_arrays(qtables); | ||||
| 
 | ||||
|     if (extra && extra_size > 0) { | ||||
|         char* p = malloc(extra_size); | ||||
|         if (!p) | ||||
|  | @ -560,6 +627,7 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args) | |||
|     encoder->encode = ImagingJpegEncode; | ||||
| 
 | ||||
|     ((JPEGENCODERSTATE*)encoder->state.context)->quality = quality; | ||||
|     ((JPEGENCODERSTATE*)encoder->state.context)->qtables = qarrays; | ||||
|     ((JPEGENCODERSTATE*)encoder->state.context)->subsampling = subsampling; | ||||
|     ((JPEGENCODERSTATE*)encoder->state.context)->progressive = progressive; | ||||
|     ((JPEGENCODERSTATE*)encoder->state.context)->smooth = smooth; | ||||
|  |  | |||
|  | @ -88,6 +88,9 @@ typedef struct { | |||
|     /* Chroma Subsampling (-1=default, 0=none, 1=medium, 2=high) */ | ||||
|     int subsampling; | ||||
| 
 | ||||
|     /* Custom quantization tables () */ | ||||
|     unsigned int **qtables; | ||||
| 
 | ||||
|     /* Extra data (to be injected after header) */ | ||||
|     char* extra; int extra_size; | ||||
| 
 | ||||
|  |  | |||
|  | @ -143,8 +143,22 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) | |||
| 
 | ||||
| 	/* Compressor configuration */ | ||||
| 	jpeg_set_defaults(&context->cinfo); | ||||
| 	if (context->quality > 0) | ||||
| 
 | ||||
| 	/* Use custom quantization tables */ | ||||
| 	if (context->qtables) { | ||||
|         int i; | ||||
|         int quality = 100; | ||||
|         if (context->quality > 0) { | ||||
|             quality = context->quality; | ||||
|         } | ||||
|         for (i = 0; i < sizeof(context->qtables)/sizeof(unsigned int); i++) { | ||||
|              // TODO: Should add support for none baseline
 | ||||
|             jpeg_add_quant_table(&context->cinfo, i, context->qtables[i], | ||||
|                 quality, TRUE); | ||||
|         } | ||||
| 	} else if (context->quality > 0) { | ||||
| 	    jpeg_set_quality(&context->cinfo, context->quality, 1); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Set subsampling options */ | ||||
| 	switch (context->subsampling) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user