Skip to content

Commit 09013d6

Browse files
committed
Fixed icns parsing issue with large PNG data.
1 parent 1a1b5ff commit 09013d6

File tree

1 file changed

+85
-86
lines changed

1 file changed

+85
-86
lines changed

icns_info.py

Lines changed: 85 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,7 +1107,7 @@ def get_image(self):
11071107
icns_info.iconChannels = 4 if bpp == 32 else 1
11081108
icns_info.iconPixelDepth = int(bpp / icns_info.iconChannels)
11091109
icns_info.iconRawDataSize = int(width * height * 4)
1110-
icns_info.data = bytearray(list(png_data))
1110+
icns_info.data = bytes(png_data)
11111111
else:
11121112
image = Image.open(BytesIO(data))
11131113
mode_to_bpp = {'1':1, 'L':8, 'P':8, 'RGB':24, 'RGBA':32, 'CMYK':32, 'YCbCr':24, 'I':32, 'F':32}
@@ -1124,7 +1124,7 @@ def get_image(self):
11241124
icns_info.iconChannels = 4 if bpp == 32 else 1
11251125
icns_info.iconPixelDepth = int(bpp / icns_info.iconChannels)
11261126
icns_info.iconRawDataSize = int(image.size[0] * image.size[1] * 4)
1127-
icns_info.data = png_data
1127+
icns_info.data = bytes(png_data)
11281128

11291129
else:
11301130
icns_info = ICNSInfo.from_type(icon_type)
@@ -1173,7 +1173,7 @@ def get_image(self):
11731173
data_pos = data_count * icon_data_row_size
11741174
icns_info.data[data_pos:data_pos+icon_data_row_size] = data[data_pos:data_pos+icon_data_row_size]
11751175
data_count += 1
1176-
1176+
11771177
return icns_info
11781178

11791179
def get_mask(self):
@@ -1264,103 +1264,102 @@ def icns_parse_family_data(icns_data):
12641264
def get_image_with_mask(icns_data, element_type):
12651265
element = ICNSElement.from_family(icns_data, element_type)
12661266
icns_image = element.get_image()
1267-
if element_type in [ICNS_256x256_32BIT_ARGB_DATA,
1268-
ICNS_512x512_32BIT_ARGB_DATA,
1269-
ICNS_1024x1024_32BIT_ARGB_DATA]:
1270-
return icns_image
1271-
mask_type = get_mask_type_for_icon_type(element_type)
1272-
mask_element = ICNSElement.from_family(icns_data, mask_type)
1273-
mask_image = mask_element.get_mask()
1274-
1275-
old_bit_depth = icns_image.iconPixelDepth * icns_image.iconChannels
1276-
if old_bit_depth < 32:
1267+
if element_type not in [ICNS_256x256_32BIT_ARGB_DATA,
1268+
ICNS_512x512_32BIT_ARGB_DATA,
1269+
ICNS_1024x1024_32BIT_ARGB_DATA]:
1270+
mask_type = get_mask_type_for_icon_type(element_type)
1271+
mask_element = ICNSElement.from_family(icns_data, mask_type)
1272+
mask_image = mask_element.get_mask()
1273+
12771274
old_bit_depth = icns_image.iconPixelDepth * icns_image.iconChannels
1278-
pixel_count = icns_image.iconSize.width * icns_image.iconSize.height
1279-
new_block_size = icns_image.iconSize.width * 32
1280-
new_data_size = new_block_size * icns_image.iconSize.height
1275+
if old_bit_depth < 32:
1276+
old_bit_depth = icns_image.iconPixelDepth * icns_image.iconChannels
1277+
pixel_count = icns_image.iconSize.width * icns_image.iconSize.height
1278+
new_block_size = icns_image.iconSize.width * 32
1279+
new_data_size = new_block_size * icns_image.iconSize.height
1280+
1281+
old_data = icns_image.data
1282+
new_data = bytearray(int(new_data_size))
12811283

1282-
old_data = icns_image.data
1283-
new_data = bytearray(int(new_data_size))
1284+
data_count = 0
12841285

1285-
data_count = 0
1286+
if element_type in [ICNS_48x48_8BIT_DATA,
1287+
ICNS_32x32_8BIT_DATA,
1288+
ICNS_16x16_8BIT_DATA,
1289+
ICNS_16x12_8BIT_DATA]:
1290+
for pixel_id in range(pixel_count):
1291+
color_index = old_data[data_count]
1292+
color_rgb = icns_colormap_8[color_index]
1293+
new_data[pixel_id*4+0] = color_rgb[0]
1294+
new_data[pixel_id*4+1] = color_rgb[1]
1295+
new_data[pixel_id*4+2] = color_rgb[2]
1296+
new_data[pixel_id*4+3] = 0xFF
1297+
data_count += 1
1298+
elif element_type in [ICNS_48x48_4BIT_DATA,
1299+
ICNS_32x32_4BIT_DATA,
1300+
ICNS_16x16_4BIT_DATA,
1301+
ICNS_16x12_4BIT_DATA]:
1302+
data_value = 0
1303+
for pixel_id in range(pixel_count):
1304+
if (pixel_id % 2) == 0:
1305+
data_value = old_data[data_count]
1306+
data_count += 1
1307+
color_index = (data_value & 0xF0) >> 4
1308+
color_rgb = icns_colormap_4[color_index]
1309+
new_data[pixel_id*4+0] = color_rgb[0]
1310+
new_data[pixel_id*4+1] = color_rgb[1]
1311+
new_data[pixel_id*4+2] = color_rgb[2]
1312+
new_data[pixel_id*4+3] = 0xFF
1313+
elif element_type in [ICNS_48x48_1BIT_DATA,
1314+
ICNS_32x32_1BIT_DATA,
1315+
ICNS_16x16_1BIT_DATA,
1316+
ICNS_16x12_1BIT_DATA]:
1317+
data_value = 0
1318+
for pixel_id in range(pixel_count):
1319+
if (pixel_id % 8) == 0:
1320+
data_value = old_data[data_count]
1321+
data_count += 1
1322+
color_index = 0x00 if (data_value & 0x80) else 0xFF
1323+
data_value = data_value << 1
1324+
new_data[pixel_id*4+0] = color_index
1325+
new_data[pixel_id*4+1] = color_index
1326+
new_data[pixel_id*4+2] = color_index
1327+
new_data[pixel_id*4+3] = 0xFF
1328+
1329+
icns_image.iconPixelDepth = 8
1330+
icns_image.iconChannels = 4
1331+
icns_image.iconRawDataSize = int(new_data_size)
1332+
icns_image.data = new_data
12861333

1287-
if element_type in [ICNS_48x48_8BIT_DATA,
1288-
ICNS_32x32_8BIT_DATA,
1289-
ICNS_16x16_8BIT_DATA,
1290-
ICNS_16x12_8BIT_DATA]:
1334+
if mask_type in [ICNS_128x128_8BIT_MASK,
1335+
ICNS_48x48_8BIT_MASK,
1336+
ICNS_32x32_8BIT_MASK,
1337+
ICNS_16x16_8BIT_MASK]:
1338+
pixel_count = mask_image.iconSize.width * mask_image.iconSize.height
1339+
data_count = 0
12911340
for pixel_id in range(pixel_count):
1292-
color_index = old_data[data_count]
1293-
color_rgb = icns_colormap_8[color_index]
1294-
new_data[pixel_id*4+0] = color_rgb[0]
1295-
new_data[pixel_id*4+1] = color_rgb[1]
1296-
new_data[pixel_id*4+2] = color_rgb[2]
1297-
new_data[pixel_id*4+3] = 0xFF
1341+
icns_image.data[pixel_id*4+3] = mask_image.data[data_count]
12981342
data_count += 1
1299-
elif element_type in [ICNS_48x48_4BIT_DATA,
1300-
ICNS_32x32_4BIT_DATA,
1301-
ICNS_16x16_4BIT_DATA,
1302-
ICNS_16x12_4BIT_DATA]:
1303-
data_value = 0
1304-
for pixel_id in range(pixel_count):
1305-
if (pixel_id % 2) == 0:
1306-
data_value = old_data[data_count]
1307-
data_count += 1
1308-
color_index = (data_value & 0xF0) >> 4
1309-
color_rgb = icns_colormap_4[color_index]
1310-
new_data[pixel_id*4+0] = color_rgb[0]
1311-
new_data[pixel_id*4+1] = color_rgb[1]
1312-
new_data[pixel_id*4+2] = color_rgb[2]
1313-
new_data[pixel_id*4+3] = 0xFF
1314-
elif element_type in [ICNS_48x48_1BIT_DATA,
1315-
ICNS_32x32_1BIT_DATA,
1316-
ICNS_16x16_1BIT_DATA,
1317-
ICNS_16x12_1BIT_DATA]:
1343+
1344+
elif mask_type in [ICNS_48x48_1BIT_MASK,
1345+
ICNS_32x32_1BIT_MASK,
1346+
ICNS_16x16_1BIT_MASK,
1347+
ICNS_16x12_1BIT_MASK]:
1348+
pixel_count = mask_image.iconSize.width * mask_image.iconSize.height
1349+
data_count = 0
13181350
data_value = 0
13191351
for pixel_id in range(pixel_count):
13201352
if (pixel_id % 8) == 0:
1321-
data_value = old_data[data_count]
1353+
data_value = mask_image.data[data_count]
13221354
data_count += 1
1323-
color_index = 0x00 if (data_value & 0x80) else 0xFF
1355+
color_index = 0xFF if (data_value & 0x80) else 0x00
13241356
data_value = data_value << 1
1325-
new_data[pixel_id*4+0] = color_index
1326-
new_data[pixel_id*4+1] = color_index
1327-
new_data[pixel_id*4+2] = color_index
1328-
new_data[pixel_id*4+3] = 0xFF
1329-
1330-
icns_image.iconPixelDepth = 8
1331-
icns_image.iconChannels = 4
1332-
icns_image.iconRawDataSize = int(new_data_size)
1333-
icns_image.data = new_data
1334-
1335-
if mask_type in [ICNS_128x128_8BIT_MASK,
1336-
ICNS_48x48_8BIT_MASK,
1337-
ICNS_32x32_8BIT_MASK,
1338-
ICNS_16x16_8BIT_MASK]:
1339-
pixel_count = mask_image.iconSize.width * mask_image.iconSize.height
1340-
data_count = 0
1341-
for pixel_id in range(pixel_count):
1342-
icns_image.data[pixel_id*4+3] = mask_image.data[data_count]
1343-
data_count += 1
1344-
1345-
elif mask_type in [ICNS_48x48_1BIT_MASK,
1346-
ICNS_32x32_1BIT_MASK,
1347-
ICNS_16x16_1BIT_MASK,
1348-
ICNS_16x12_1BIT_MASK]:
1349-
pixel_count = mask_image.iconSize.width * mask_image.iconSize.height
1350-
data_count = 0
1351-
data_value = 0
1352-
for pixel_id in range(pixel_count):
1353-
if (pixel_id % 8) == 0:
1354-
data_value = mask_image.data[data_count]
1355-
data_count += 1
1356-
color_index = 0xFF if (data_value & 0x80) else 0x00
1357-
data_value = data_value << 1
1358-
icns_image.data[pixel_id*4+3] = color_index
1357+
icns_image.data[pixel_id*4+3] = color_index
1358+
13591359
im = Image.frombytes('RGBA', [icns_image.iconSize.width,icns_image.iconSize.height], bytes(icns_image.data))
1360-
#print(icns_image.data)
13611360
output = BytesIO()
13621361
im.save(output, format='PNG')
1363-
icns_image.data = bytearray(output.getvalue())
1362+
icns_image.data = bytes(output.getvalue())
13641363

13651364
return icns_image
13661365

0 commit comments

Comments
 (0)