Skip to content

Commit a18de2a

Browse files
Optimize and prevent OOM in apply_png_predictor (#1247)
Co-authored-by: codeflash-ai[bot] <148906541+codeflash-ai[bot]@users.noreply.github.com>
1 parent c04497d commit a18de2a

2 files changed

Lines changed: 12 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1010
### Fixed
1111

1212
- Reproducibility issue when generating cmap `.json.gz` files ([#1242](https://github.com/pdfminer/pdfminer.six/pull/1242))
13+
- Switch to `bytearray` in `apply_png_predictor` to avoid out of memory error (and speed it up) ([#1247](https://github.com/pdfminer/pdfminer.six/pull/1247))
1314
- Check the type of `N` when creating an `ICCBased` color space ([#1252](http3://github.com/pdfminer/pdfminer.six/pull/1253))
1415
- Endless recursion issue with circular or corrupted `Prev` chains in cross-refeerence tables ([#1253](https://github.com/pdfminer/pdfminer.six/pull/1253))
1516

pdfminer/utils.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -167,16 +167,16 @@ def apply_png_predictor(
167167

168168
nbytes = colors * columns * bitspercomponent // 8
169169
bpp = colors * bitspercomponent // 8 # number of bytes per complete pixel
170-
buf = []
171-
line_above = list(b"\x00" * columns)
170+
buf = bytearray()
171+
line_above = bytearray(columns)
172172
for scanline_i in range(0, len(data), nbytes + 1):
173173
filter_type = data[scanline_i]
174174
line_encoded = data[scanline_i + 1 : scanline_i + 1 + nbytes]
175-
raw = []
175+
raw = bytearray()
176176

177177
if filter_type == 0:
178178
# Filter type 0: None
179-
raw = list(line_encoded)
179+
raw = bytearray(line_encoded)
180180

181181
elif filter_type == 1:
182182
# Filter type 1: Sub
@@ -186,7 +186,7 @@ def apply_png_predictor(
186186
# (computed mod 256), where Raw() refers to the bytes already
187187
# decoded.
188188
for j, sub_x in enumerate(line_encoded):
189-
raw_x_bpp = 0 if j - bpp < 0 else int(raw[j - bpp])
189+
raw_x_bpp = 0 if j < bpp else raw[j - bpp]
190190
raw_x = (sub_x + raw_x_bpp) & 255
191191
raw.append(raw_x)
192192

@@ -211,8 +211,8 @@ def apply_png_predictor(
211211
# bytes already decoded, and Prior() refers to the decoded bytes of
212212
# the prior scanline.
213213
for j, average_x in enumerate(line_encoded):
214-
raw_x_bpp = 0 if j - bpp < 0 else int(raw[j - bpp])
215-
prior_x = int(line_above[j])
214+
raw_x_bpp = 0 if j < bpp else raw[j - bpp]
215+
prior_x = line_above[j]
216216
raw_x = (average_x + (raw_x_bpp + prior_x) // 2) & 255
217217
raw.append(raw_x)
218218

@@ -226,13 +226,13 @@ def apply_png_predictor(
226226
# already decoded. Exactly the same PaethPredictor() function is
227227
# used by both encoder and decoder.
228228
for j, paeth_x in enumerate(line_encoded):
229-
if j - bpp < 0:
229+
if j < bpp:
230230
raw_x_bpp = 0
231231
prior_x_bpp = 0
232232
else:
233-
raw_x_bpp = int(raw[j - bpp])
234-
prior_x_bpp = int(line_above[j - bpp])
235-
prior_x = int(line_above[j])
233+
raw_x_bpp = raw[j - bpp]
234+
prior_x_bpp = line_above[j - bpp]
235+
prior_x = line_above[j]
236236
paeth = paeth_predictor(raw_x_bpp, prior_x, prior_x_bpp)
237237
raw_x = (paeth_x + paeth) & 255
238238
raw.append(raw_x)

0 commit comments

Comments
 (0)