Skip to content

Commit 4c8807f

Browse files
ArcaneNibblemarcan
authored andcommitted
jpeg: Add RGB565 to decoder
Note that dithering does not get configured Signed-off-by: R <[email protected]>
1 parent 7350baf commit 4c8807f

1 file changed

Lines changed: 113 additions & 51 deletions

File tree

proxyclient/experiments/jpeg.py

Lines changed: 113 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ def divroundup(val, div):
2525
g.add_argument("-e", "--encode", action='store_true')
2626
g.add_argument("-d", "--decode", action='store_true')
2727
ap.add_argument("--raw-output", type=str, required=False)
28-
ap.add_argument("--decode-scale", type=int, required=False)
28+
ap.add_argument("--decode-scale", type=int, required=False, default=1)
29+
ap.add_argument("--decode-pixelfmt", type=str, required=False, default='RGBA')
30+
ap.add_argument("--decode-rgba-alpha", type=int, required=False, default=255)
2931
ap.add_argument("input", type=str)
3032
ap.add_argument("output", type=str)
3133
args = ap.parse_args()
@@ -34,12 +36,16 @@ def divroundup(val, div):
3436

3537
# Perform necessary pre-parsing
3638
if args.decode:
37-
if args.decode_scale is not None:
38-
assert args.decode_scale in [1, 2, 4, 8]
39-
decode_scale = args.decode_scale
40-
else:
41-
decode_scale = 1
42-
# TODO: finish implementing this
39+
assert args.decode_scale in [1, 2, 4, 8]
40+
decode_scale = args.decode_scale
41+
# FIXME: verify behavior on non-evenly-divisible sizes
42+
43+
assert args.decode_pixelfmt in [
44+
'RGBA',
45+
'BGRA',
46+
'RGB565',
47+
]
48+
pixfmt = args.decode_pixelfmt
4349

4450
with open(args.input, 'rb') as f:
4551
jpeg_data = f.read()
@@ -114,9 +120,14 @@ def divroundup(val, div):
114120
assert False
115121

116122
# FIXME: Exactly how much extra memory do we need to allocate?
117-
surface_W = divroundup(jpeg_W, macroblock_W) * macroblock_W
118-
surface_H = divroundup(jpeg_H, macroblock_H) * macroblock_H
119-
BYTESPP = 4
123+
surface_W = divroundup(jpeg_W // decode_scale, macroblock_W) * macroblock_W
124+
surface_H = divroundup(jpeg_H // decode_scale, macroblock_H) * macroblock_H
125+
if pixfmt in ['RGBA', 'BGRA']:
126+
BYTESPP = 4
127+
elif pixfmt == 'RGB565':
128+
BYTESPP = 2
129+
else:
130+
assert False
120131
surface_stride = surface_W * BYTESPP
121132

122133
input_mem_sz = align_up(len(jpeg_data))
@@ -311,11 +322,14 @@ def set_default_regs(param1=0):
311322
jpeg.CODEC.set(CODEC=E_CODEC._411)
312323
else:
313324
assert False
314-
jpeg.DECODE_PIXEL_FORMAT.set(FORMAT=E_DECODE_PIXEL_FORMAT.RGBA8888)
325+
if pixfmt == 'RGBA' or pixfmt == 'BGRA':
326+
jpeg.DECODE_PIXEL_FORMAT.set(FORMAT=E_DECODE_PIXEL_FORMAT.RGBA8888)
327+
elif pixfmt == 'RGB565':
328+
jpeg.DECODE_PIXEL_FORMAT.set(FORMAT=E_DECODE_PIXEL_FORMAT.RGB565)
315329

316330
jpeg.PX_USE_PLANE1 = 0
317-
jpeg.PX_PLANE0_WIDTH = jpeg_W*BYTESPP - 1
318-
jpeg.PX_PLANE0_HEIGHT = jpeg_H - 1
331+
jpeg.PX_PLANE0_WIDTH = jpeg_W*BYTESPP // decode_scale - 1
332+
jpeg.PX_PLANE0_HEIGHT = jpeg_H // decode_scale - 1
319333
# TODO P1
320334
jpeg.TIMEOUT = 266000000
321335

@@ -324,38 +338,64 @@ def set_default_regs(param1=0):
324338

325339
jpeg.DECODE_MACROBLOCKS_W = divroundup(jpeg_W, macroblock_W)
326340
jpeg.DECODE_MACROBLOCKS_H = divroundup(jpeg_H, macroblock_H)
327-
# right_edge_px = jpeg_W - divroundup(jpeg_W, 8)*8 + 8
328-
# bot_edge_px = jpeg_H - divroundup(jpeg_H, 8)*8 + 8
329-
# # XXX changing this does not seem to do anything
330-
# jpeg.RIGHT_EDGE_PIXELS.val = right_edge_px
331-
# jpeg.BOTTOM_EDGE_PIXELS.val = bot_edge_px
332-
# jpeg.RIGHT_EDGE_SAMPLES.val = right_edge_px // 2
333-
# jpeg.BOTTOM_EDGE_SAMPLES.val = bot_edge_px // 2
341+
right_edge_px = \
342+
jpeg_W - divroundup(jpeg_W, macroblock_W)*macroblock_W + macroblock_W
343+
bot_edge_px = \
344+
jpeg_H - divroundup(jpeg_H, macroblock_H)*macroblock_H + macroblock_H
345+
# XXX changing this does not seem to do anything
346+
jpeg.RIGHT_EDGE_PIXELS.val = right_edge_px
347+
jpeg.BOTTOM_EDGE_PIXELS.val = bot_edge_px
348+
jpeg.RIGHT_EDGE_SAMPLES.val = right_edge_px // (macroblock_W // 8)
349+
jpeg.BOTTOM_EDGE_SAMPLES.val = bot_edge_px // (macroblock_H // 8)
334350

335351
jpeg.PX_TILES_H = divroundup(jpeg_H, macroblock_H)
336-
jpeg.PX_TILES_W = divroundup(jpeg_W, macroblock_W)
337-
if jpeg_MODE == '444' or jpeg_MODE == '400':
338-
jpeg.PX_PLANE0_TILING_H = 4
339-
jpeg.PX_PLANE0_TILING_V = 8
340-
jpeg.PX_PLANE1_TILING_H = 1
341-
jpeg.PX_PLANE1_TILING_V = 1
342-
elif jpeg_MODE == '422':
343-
jpeg.PX_PLANE0_TILING_H = 8
344-
jpeg.PX_PLANE0_TILING_V = 8
345-
jpeg.PX_PLANE1_TILING_H = 1
346-
jpeg.PX_PLANE1_TILING_V = 1
347-
elif jpeg_MODE == '420':
348-
jpeg.PX_PLANE0_TILING_H = 8
349-
jpeg.PX_PLANE0_TILING_V = 16
350-
jpeg.PX_PLANE1_TILING_H = 0
351-
jpeg.PX_PLANE1_TILING_V = 0
352-
elif jpeg_MODE == '411':
353-
jpeg.PX_PLANE0_TILING_H = 16
354-
jpeg.PX_PLANE0_TILING_V = 8
355-
jpeg.PX_PLANE1_TILING_H = 0
356-
jpeg.PX_PLANE1_TILING_V = 0
357-
else:
358-
assert False
352+
jpeg.PX_TILES_W = divroundup(jpeg_W // decode_scale, macroblock_W)
353+
if pixfmt == 'RGBA' or pixfmt == 'BGRA':
354+
if jpeg_MODE == '444' or jpeg_MODE == '400':
355+
jpeg.PX_PLANE0_TILING_H = 4
356+
jpeg.PX_PLANE0_TILING_V = 8 // decode_scale
357+
jpeg.PX_PLANE1_TILING_H = 1
358+
jpeg.PX_PLANE1_TILING_V = 1
359+
elif jpeg_MODE == '422':
360+
jpeg.PX_PLANE0_TILING_H = 8
361+
jpeg.PX_PLANE0_TILING_V = 8 // decode_scale
362+
jpeg.PX_PLANE1_TILING_H = 1
363+
jpeg.PX_PLANE1_TILING_V = 1
364+
elif jpeg_MODE == '420':
365+
jpeg.PX_PLANE0_TILING_H = 8
366+
jpeg.PX_PLANE0_TILING_V = 16 // decode_scale
367+
jpeg.PX_PLANE1_TILING_H = 0
368+
jpeg.PX_PLANE1_TILING_V = 0
369+
elif jpeg_MODE == '411':
370+
jpeg.PX_PLANE0_TILING_H = 16
371+
jpeg.PX_PLANE0_TILING_V = 8 // decode_scale
372+
jpeg.PX_PLANE1_TILING_H = 0
373+
jpeg.PX_PLANE1_TILING_V = 0
374+
else:
375+
assert False
376+
elif pixfmt == 'RGB565':
377+
if jpeg_MODE == '444' or jpeg_MODE == '400':
378+
jpeg.PX_PLANE0_TILING_H = 2
379+
jpeg.PX_PLANE0_TILING_V = 8 // decode_scale
380+
jpeg.PX_PLANE1_TILING_H = 1
381+
jpeg.PX_PLANE1_TILING_V = 1
382+
elif jpeg_MODE == '422':
383+
jpeg.PX_PLANE0_TILING_H = 4
384+
jpeg.PX_PLANE0_TILING_V = 8 // decode_scale
385+
jpeg.PX_PLANE1_TILING_H = 1
386+
jpeg.PX_PLANE1_TILING_V = 1
387+
elif jpeg_MODE == '420':
388+
jpeg.PX_PLANE0_TILING_H = 4
389+
jpeg.PX_PLANE0_TILING_V = 16 // decode_scale
390+
jpeg.PX_PLANE1_TILING_H = 0
391+
jpeg.PX_PLANE1_TILING_V = 0
392+
elif jpeg_MODE == '411':
393+
jpeg.PX_PLANE0_TILING_H = 8
394+
jpeg.PX_PLANE0_TILING_V = 8 // decode_scale
395+
jpeg.PX_PLANE1_TILING_H = 0
396+
jpeg.PX_PLANE1_TILING_V = 0
397+
else:
398+
assert False
359399

360400
if jpeg_MODE in ['422', '420']: # TODO
361401
jpeg.CHROMA_DOUBLE_H = 1
@@ -378,10 +418,19 @@ def set_default_regs(param1=0):
378418
jpeg.MATRIX_MULT[9].val = 0x0
379419
jpeg.MATRIX_MULT[10].val = 0xffffff80
380420

381-
jpeg.RGBA_ALPHA = 0xff
382-
jpeg.RGBA_ORDER = 1
383-
384-
jpeg.SCALE_FACTOR = 0
421+
jpeg.RGBA_ALPHA = args.decode_rgba_alpha
422+
jpeg.RGBA_ORDER = pixfmt == "RGBA"
423+
424+
if decode_scale == 1:
425+
jpeg.SCALE_FACTOR.set(SCALE=E_SCALE.DIV1)
426+
elif decode_scale == 2:
427+
jpeg.SCALE_FACTOR.set(SCALE=E_SCALE.DIV2)
428+
elif decode_scale == 4:
429+
jpeg.SCALE_FACTOR.set(SCALE=E_SCALE.DIV4)
430+
elif decode_scale == 8:
431+
jpeg.SCALE_FACTOR.set(SCALE=E_SCALE.DIV8)
432+
else:
433+
assert False
385434

386435
jpeg.INPUT_START1 = input_buf_iova
387436
jpeg.INPUT_START2 = 0xdeadbeef
@@ -421,13 +470,26 @@ def set_default_regs(param1=0):
421470
with open(args.raw_output, 'wb') as f:
422471
f.write(output_data)
423472

424-
with Image.new(mode='RGBA', size=(jpeg_W, jpeg_H)) as im:
425-
for y in range(jpeg_H):
426-
for x in range(jpeg_W):
473+
with Image.new(
474+
mode='RGBA',
475+
size=(jpeg_W // decode_scale, jpeg_H // decode_scale)) as im:
476+
for y in range(jpeg_H // decode_scale):
477+
for x in range(jpeg_W // decode_scale):
427478
block = output_data[
428479
y*surface_stride + x*BYTESPP:
429480
y*surface_stride + (x+1)*BYTESPP]
430481

431-
r, g, b, a = block
482+
if pixfmt == "RGBA":
483+
r, g, b, a = block
484+
elif pixfmt == "BGRA":
485+
b, g, r, a = block
486+
elif pixfmt == "RGB565":
487+
rgb = struct.unpack("<H", block)[0]
488+
b = (rgb & 0b11111) << 3
489+
g = ((rgb >> 5) & 0b111111) << 2
490+
r = ((rgb >> 11) & 0b11111) << 3
491+
a = 255
492+
else:
493+
assert False
432494
im.putpixel((x, y), (r, g, b, a))
433495
im.save(args.output)

0 commit comments

Comments
 (0)