mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-30 23:47:27 +03:00 
			
		
		
		
	Implement streamtype=1 option for tables-only JPEG encoding
We already support streamtype=2 to skip producing JPEG tables, but streamtype=1, which skips everything but the tables, was never implemented. The streamtype=1 stub code dates to Git pre-history, so it's not immediately clear why. Implement the missing support. jpeg_write_tables() can't resume after a full output buffer (it fails with JERR_CANT_SUSPEND), so it might seem that Pillow needs to pre-compute the necessary buffer size. However, in the normal case of producing an interchange stream, the tables are written via the same libjpeg codepath during the first jpeg_write_scanlines() call, and table writes aren't resumable there either. Thus, any buffer large enough for the normal case will also be large enough for a tables-only file. The streamtype option isn't documented and this commit doesn't change that. It does add a test though. Co-authored-by: Andrew Murray <radarhere@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									d05ff5059f
								
							
						
					
					
						commit
						4d7372bfd0
					
				|  | @ -961,6 +961,28 @@ class TestFileJpeg: | ||||||
|             im.load() |             im.load() | ||||||
|             ImageFile.LOAD_TRUNCATED_IMAGES = False |             ImageFile.LOAD_TRUNCATED_IMAGES = False | ||||||
| 
 | 
 | ||||||
|  |     def test_separate_tables(self): | ||||||
|  |         im = hopper() | ||||||
|  |         data = []  # [interchange, tables-only, image-only] | ||||||
|  |         for streamtype in range(3): | ||||||
|  |             out = BytesIO() | ||||||
|  |             im.save(out, format="JPEG", streamtype=streamtype) | ||||||
|  |             data.append(out.getvalue()) | ||||||
|  | 
 | ||||||
|  |         # SOI, EOI | ||||||
|  |         for marker in b"\xff\xd8", b"\xff\xd9": | ||||||
|  |             assert marker in data[1] and marker in data[2] | ||||||
|  |         # DHT, DQT | ||||||
|  |         for marker in b"\xff\xc4", b"\xff\xdb": | ||||||
|  |             assert marker in data[1] and marker not in data[2] | ||||||
|  |         # SOF0, SOS, APP0 (JFIF header) | ||||||
|  |         for marker in b"\xff\xc0", b"\xff\xda", b"\xff\xe0": | ||||||
|  |             assert marker not in data[1] and marker in data[2] | ||||||
|  | 
 | ||||||
|  |         with Image.open(BytesIO(data[0])) as interchange_im: | ||||||
|  |             with Image.open(BytesIO(data[1] + data[2])) as combined_im: | ||||||
|  |                 assert_image_equal(interchange_im, combined_im) | ||||||
|  | 
 | ||||||
|     def test_repr_jpeg(self): |     def test_repr_jpeg(self): | ||||||
|         im = hopper() |         im = hopper() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -218,9 +218,9 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) { | ||||||
|             } |             } | ||||||
|             switch (context->streamtype) { |             switch (context->streamtype) { | ||||||
|                 case 1: |                 case 1: | ||||||
|                     /* tables only -- not yet implemented */ |                     /* tables only */ | ||||||
|                     state->errcode = IMAGING_CODEC_CONFIG; |                     jpeg_write_tables(&context->cinfo); | ||||||
|                     return -1; |                     goto cleanup; | ||||||
|                 case 2: |                 case 2: | ||||||
|                     /* image only */ |                     /* image only */ | ||||||
|                     jpeg_suppress_tables(&context->cinfo, TRUE); |                     jpeg_suppress_tables(&context->cinfo, TRUE); | ||||||
|  | @ -316,6 +316,7 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) { | ||||||
|             } |             } | ||||||
|             jpeg_finish_compress(&context->cinfo); |             jpeg_finish_compress(&context->cinfo); | ||||||
| 
 | 
 | ||||||
|  | cleanup: | ||||||
|             /* Clean up */ |             /* Clean up */ | ||||||
|             if (context->comment) { |             if (context->comment) { | ||||||
|                 free(context->comment); |                 free(context->comment); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user