mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-26 09:14:27 +03:00
Merge pull request #4918 from gofr/4825-jpeg-16-bit-qt
This commit is contained in:
commit
1cb3e2f742
BIN
Tests/images/hopper_16bit_qtables.jpg
Normal file
BIN
Tests/images/hopper_16bit_qtables.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
|
@ -446,6 +446,7 @@ class TestFileJpeg:
|
|||
assert len(im.quantization) == n
|
||||
reloaded = self.roundtrip(im, qtables="keep")
|
||||
assert im.quantization == reloaded.quantization
|
||||
assert reloaded.quantization[0].typecode == "B"
|
||||
|
||||
with Image.open("Tests/images/hopper.jpg") as im:
|
||||
qtables = im.quantization
|
||||
|
@ -544,6 +545,30 @@ class TestFileJpeg:
|
|||
with pytest.raises(ValueError):
|
||||
self.roundtrip(im, qtables=[[1, 2, 3, 4]])
|
||||
|
||||
def test_load_16bit_qtables(self):
|
||||
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
|
||||
assert len(im.quantization) == 2
|
||||
assert len(im.quantization[0]) == 64
|
||||
assert max(im.quantization[0]) > 255
|
||||
|
||||
def test_save_multiple_16bit_qtables(self):
|
||||
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
|
||||
im2 = self.roundtrip(im, qtables="keep")
|
||||
assert im.quantization == im2.quantization
|
||||
|
||||
def test_save_single_16bit_qtable(self):
|
||||
with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
|
||||
im2 = self.roundtrip(im, qtables={0: im.quantization[0]})
|
||||
assert len(im2.quantization) == 1
|
||||
assert im2.quantization[0] == im.quantization[0]
|
||||
|
||||
def test_save_low_quality_baseline_qtables(self):
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im2 = self.roundtrip(im, quality=10)
|
||||
assert len(im2.quantization) == 2
|
||||
assert max(im2.quantization[0]) <= 255
|
||||
assert max(im2.quantization[1]) <= 255
|
||||
|
||||
@pytest.mark.skipif(not djpeg_available(), reason="djpeg not available")
|
||||
def test_load_djpeg(self):
|
||||
with Image.open(TEST_FILE) as img:
|
||||
|
|
|
@ -36,6 +36,7 @@ import io
|
|||
import os
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import warnings
|
||||
|
||||
|
@ -234,9 +235,8 @@ def SOF(self, marker):
|
|||
|
||||
def DQT(self, marker):
|
||||
#
|
||||
# Define quantization table. Support baseline 8-bit tables
|
||||
# only. Note that there might be more than one table in
|
||||
# each marker.
|
||||
# Define quantization table. Note that there might be more
|
||||
# than one table in each marker.
|
||||
|
||||
# FIXME: The quantization tables can be used to estimate the
|
||||
# compression quality.
|
||||
|
@ -244,15 +244,16 @@ def DQT(self, marker):
|
|||
n = i16(self.fp.read(2)) - 2
|
||||
s = ImageFile._safe_read(self.fp, n)
|
||||
while len(s):
|
||||
if len(s) < 65:
|
||||
raise SyntaxError("bad quantization table marker")
|
||||
v = i8(s[0])
|
||||
if v // 16 == 0:
|
||||
self.quantization[v & 15] = array.array("B", s[1:65])
|
||||
s = s[65:]
|
||||
else:
|
||||
return # FIXME: add code to read 16-bit tables!
|
||||
# raise SyntaxError, "bad quantization table element size"
|
||||
precision = 1 if (v // 16 == 0) else 2 # in bytes
|
||||
qt_length = 1 + precision * 64
|
||||
if len(s) < qt_length:
|
||||
raise SyntaxError("bad quantization table marker")
|
||||
data = array.array("B" if precision == 1 else "H", s[1:qt_length])
|
||||
if sys.byteorder == "little" and precision > 1:
|
||||
data.byteswap() # the values are always big-endian
|
||||
self.quantization[v & 15] = data
|
||||
s = s[qt_length:]
|
||||
|
||||
|
||||
#
|
||||
|
@ -676,7 +677,7 @@ def _save(im, fp, filename):
|
|||
try:
|
||||
if len(table) != 64:
|
||||
raise TypeError
|
||||
table = array.array("B", table)
|
||||
table = array.array("H", table)
|
||||
except TypeError as e:
|
||||
raise ValueError("Invalid quantization table") from e
|
||||
else:
|
||||
|
|
|
@ -159,22 +159,21 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
|||
quality = context->quality;
|
||||
}
|
||||
for (i = 0; i < context->qtablesLen; i++) {
|
||||
// TODO: Should add support for none baseline
|
||||
jpeg_add_quant_table(&context->cinfo, i, &context->qtables[i * DCTSIZE2],
|
||||
quality, TRUE);
|
||||
quality, FALSE);
|
||||
context->cinfo.comp_info[i].quant_tbl_no = i;
|
||||
last_q = i;
|
||||
}
|
||||
if (context->qtablesLen == 1) {
|
||||
// jpeg_set_defaults created two qtables internally, but we only wanted one.
|
||||
jpeg_add_quant_table(&context->cinfo, 1, &context->qtables[0],
|
||||
quality, TRUE);
|
||||
quality, FALSE);
|
||||
}
|
||||
for (i = last_q; i < context->cinfo.num_components; i++) {
|
||||
context->cinfo.comp_info[i].quant_tbl_no = last_q;
|
||||
}
|
||||
} else if (context->quality != -1) {
|
||||
jpeg_set_quality(&context->cinfo, context->quality, 1);
|
||||
jpeg_set_quality(&context->cinfo, context->quality, TRUE);
|
||||
}
|
||||
|
||||
/* Set subsampling options */
|
||||
|
|
Loading…
Reference in New Issue
Block a user