diff --git a/src/PIL/BlpImagePlugin.py b/src/PIL/BlpImagePlugin.py index f0fbc8cc2..95e807781 100644 --- a/src/PIL/BlpImagePlugin.py +++ b/src/PIL/BlpImagePlugin.py @@ -341,7 +341,7 @@ class BLP1Decoder(_BLPBaseDecoder): if self._blp_encoding in (4, 5): palette = self._read_palette() data = self._read_bgra(palette) - self.set_as_raw(bytes(data)) + self.set_as_raw(data) else: msg = f"Unsupported BLP encoding {repr(self._blp_encoding)}" raise BLPFormatError(msg) @@ -412,7 +412,7 @@ class BLP2Decoder(_BLPBaseDecoder): msg = f"Unknown BLP compression {repr(self._blp_compression)}" raise BLPFormatError(msg) - self.set_as_raw(bytes(data)) + self.set_as_raw(data) class BLPEncoder(ImageFile.PyEncoder): diff --git a/src/PIL/BmpImagePlugin.py b/src/PIL/BmpImagePlugin.py index 6f730cfef..9947f439b 100644 --- a/src/PIL/BmpImagePlugin.py +++ b/src/PIL/BmpImagePlugin.py @@ -291,7 +291,8 @@ class BmpRleDecoder(ImageFile.PyDecoder): rle4 = self.args[1] data = bytearray() x = 0 - while len(data) < self.state.xsize * self.state.ysize: + dest_length = self.state.xsize * self.state.ysize + while len(data) < dest_length: pixels = self.fd.read(1) byte = self.fd.read(1) if not pixels or not byte: diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index be17f4223..93c8e341d 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -497,7 +497,8 @@ class DdsRgbDecoder(ImageFile.PyDecoder): data = bytearray() bytecount = bitcount // 8 - while len(data) < self.state.xsize * self.state.ysize * len(masks): + dest_length = self.state.xsize * self.state.ysize * len(masks) + while len(data) < dest_length: value = int.from_bytes(self.fd.read(bytecount), "little") for i, mask in enumerate(masks): masked_value = value & mask @@ -505,7 +506,7 @@ class DdsRgbDecoder(ImageFile.PyDecoder): data += o8( int(((masked_value >> mask_offsets[i]) / mask_totals[i]) * 255) ) - self.set_as_raw(bytes(data)) + self.set_as_raw(data) return -1, 0 diff --git a/src/PIL/PpmImagePlugin.py b/src/PIL/PpmImagePlugin.py index bca3018c3..94bf430b8 100644 --- a/src/PIL/PpmImagePlugin.py +++ b/src/PIL/PpmImagePlugin.py @@ -307,7 +307,8 @@ class PpmDecoder(ImageFile.PyDecoder): out_byte_count = 4 if self.mode == "I" else 1 out_max = 65535 if self.mode == "I" else 255 bands = Image.getmodebands(self.mode) - while len(data) < self.state.xsize * self.state.ysize * bands * out_byte_count: + dest_length = self.state.xsize * self.state.ysize * bands * out_byte_count + while len(data) < dest_length: pixels = self.fd.read(in_byte_count * bands) if len(pixels) < in_byte_count * bands: # eof diff --git a/src/PIL/QoiImagePlugin.py b/src/PIL/QoiImagePlugin.py index a7b9d4a9e..f8aa720c1 100644 --- a/src/PIL/QoiImagePlugin.py +++ b/src/PIL/QoiImagePlugin.py @@ -11,7 +11,6 @@ import os from . import Image, ImageFile from ._binary import i32be as i32 -from ._binary import o8 def _accept(prefix): @@ -49,41 +48,48 @@ class QoiDecoder(ImageFile.PyDecoder): def decode(self, buffer): self._previously_seen_pixels = {} self._previous_pixel = None - self._add_to_previous_pixels(b"".join(o8(i) for i in (0, 0, 0, 255))) + self._add_to_previous_pixels(bytearray((0, 0, 0, 255))) data = bytearray() bands = Image.getmodebands(self.mode) - while len(data) < self.state.xsize * self.state.ysize * bands: + dest_length = self.state.xsize * self.state.ysize * bands + while len(data) < dest_length: byte = self.fd.read(1)[0] if byte == 0b11111110: # QOI_OP_RGB - value = self.fd.read(3) + self._previous_pixel[3:] + value = bytearray(self.fd.read(3)) + self._previous_pixel[3:] elif byte == 0b11111111: # QOI_OP_RGBA value = self.fd.read(4) else: op = byte >> 6 if op == 0: # QOI_OP_INDEX op_index = byte & 0b00111111 - value = self._previously_seen_pixels.get(op_index, (0, 0, 0, 0)) - elif op == 1: # QOI_OP_DIFF - value = ( - (self._previous_pixel[0] + ((byte & 0b00110000) >> 4) - 2) - % 256, - (self._previous_pixel[1] + ((byte & 0b00001100) >> 2) - 2) - % 256, - (self._previous_pixel[2] + (byte & 0b00000011) - 2) % 256, + value = self._previously_seen_pixels.get( + op_index, bytearray((0, 0, 0, 0)) + ) + elif op == 1: # QOI_OP_DIFF + value = bytearray( + ( + (self._previous_pixel[0] + ((byte & 0b00110000) >> 4) - 2) + % 256, + (self._previous_pixel[1] + ((byte & 0b00001100) >> 2) - 2) + % 256, + (self._previous_pixel[2] + (byte & 0b00000011) - 2) % 256, + self._previous_pixel[3], + ) ) - value += (self._previous_pixel[3],) elif op == 2: # QOI_OP_LUMA second_byte = self.fd.read(1)[0] diff_green = (byte & 0b00111111) - 32 diff_red = ((second_byte & 0b11110000) >> 4) - 8 diff_blue = (second_byte & 0b00001111) - 8 - value = tuple( - (self._previous_pixel[i] + diff_green + diff) % 256 - for i, diff in enumerate((diff_red, 0, diff_blue)) + value = bytearray( + tuple( + (self._previous_pixel[i] + diff_green + diff) % 256 + for i, diff in enumerate((diff_red, 0, diff_blue)) + ) ) - value += (self._previous_pixel[3],) + value += self._previous_pixel[3:] elif op == 3: # QOI_OP_RUN run_length = (byte & 0b00111111) + 1 value = self._previous_pixel @@ -91,13 +97,12 @@ class QoiDecoder(ImageFile.PyDecoder): value = value[:3] data += value * run_length continue - value = b"".join(o8(i) for i in value) self._add_to_previous_pixels(value) if bands == 3: value = value[:3] data += value - self.set_as_raw(bytes(data)) + self.set_as_raw(data) return -1, 0