Added support for Mac ICNS icon display when loading ICNS files.
This commit is contained in:
parent
4748e40b3d
commit
6991d84e2e
4 changed files with 789 additions and 77 deletions
|
|
@ -1,3 +1,4 @@
|
|||
0.12.1
|
||||
0.12.0
|
||||
0.12.0-rc1
|
||||
0.12.0-alpha3
|
||||
|
|
|
|||
845
icns_info.py
845
icns_info.py
|
|
@ -1,64 +1,66 @@
|
|||
import struct
|
||||
import image_utils
|
||||
import png
|
||||
|
||||
from PIL import Image
|
||||
import os
|
||||
from cStringIO import StringIO
|
||||
|
||||
#---------------------CONSTANTS-----------------------------------------------#
|
||||
|
||||
ICNS_TABLE_OF_CONTENTS = 0x544F4320 # "TOC "
|
||||
ICNS_TABLE_OF_CONTENTS = 0x544F4320 # "TOC "
|
||||
|
||||
ICNS_ICON_VERSION = 0x69636E56 # "icnV"
|
||||
ICNS_ICON_VERSION = 0x69636E56 # "icnV"
|
||||
|
||||
ICNS_1024x1024_32BIT_ARGB_DATA = 0x69633130 # "ic10"
|
||||
ICNS_1024x1024_32BIT_ARGB_DATA = 0x69633130 # "ic10"
|
||||
|
||||
ICNS_512x512_32BIT_ARGB_DATA = 0x69633039 # "ic09"
|
||||
ICNS_256x256_32BIT_ARGB_DATA = 0x69633038 # "ic08"
|
||||
ICNS_512x512_32BIT_ARGB_DATA = 0x69633039 # "ic09"
|
||||
ICNS_256x256_32BIT_ARGB_DATA = 0x69633038 # "ic08"
|
||||
|
||||
ICNS_128x128_32BIT_DATA = 0x69743332 # "it32"
|
||||
ICNS_128x128_8BIT_MASK = 0x74386D6B # "t8mk"
|
||||
ICNS_128x128_32BIT_DATA = 0x69743332 # "it32"
|
||||
ICNS_128x128_8BIT_MASK = 0x74386D6B # "t8mk"
|
||||
|
||||
ICNS_48x48_1BIT_DATA = 0x69636823 # "ich#"
|
||||
ICNS_48x48_4BIT_DATA = 0x69636834 # "ich4"
|
||||
ICNS_48x48_8BIT_DATA = 0x69636838 # "ich8"
|
||||
ICNS_48x48_32BIT_DATA = 0x69683332 # "ih32"
|
||||
ICNS_48x48_1BIT_MASK = 0x69636823 # "ich#"
|
||||
ICNS_48x48_8BIT_MASK = 0x68386D6B # "h8mk"
|
||||
ICNS_48x48_1BIT_DATA = 0x69636823 # "ich#"
|
||||
ICNS_48x48_4BIT_DATA = 0x69636834 # "ich4"
|
||||
ICNS_48x48_8BIT_DATA = 0x69636838 # "ich8"
|
||||
ICNS_48x48_32BIT_DATA = 0x69683332 # "ih32"
|
||||
ICNS_48x48_1BIT_MASK = 0x69636823 # "ich#"
|
||||
ICNS_48x48_8BIT_MASK = 0x68386D6B # "h8mk"
|
||||
|
||||
ICNS_32x32_1BIT_DATA = 0x49434E23 # "ICN#"
|
||||
ICNS_32x32_4BIT_DATA = 0x69636C34 # "icl4"
|
||||
ICNS_32x32_8BIT_DATA = 0x69636C38 # "icl8"
|
||||
ICNS_32x32_32BIT_DATA = 0x696C3332 # "il32"
|
||||
ICNS_32x32_1BIT_MASK = 0x49434E23 # "ICN#"
|
||||
ICNS_32x32_8BIT_MASK = 0x6C386D6B # "l8mk"
|
||||
ICNS_32x32_1BIT_DATA = 0x49434E23 # "ICN#"
|
||||
ICNS_32x32_4BIT_DATA = 0x69636C34 # "icl4"
|
||||
ICNS_32x32_8BIT_DATA = 0x69636C38 # "icl8"
|
||||
ICNS_32x32_32BIT_DATA = 0x696C3332 # "il32"
|
||||
ICNS_32x32_1BIT_MASK = 0x49434E23 # "ICN#"
|
||||
ICNS_32x32_8BIT_MASK = 0x6C386D6B # "l8mk"
|
||||
|
||||
ICNS_16x16_1BIT_DATA = 0x69637323 # "ics#"
|
||||
ICNS_16x16_4BIT_DATA = 0x69637334 # "ics4"
|
||||
ICNS_16x16_8BIT_DATA = 0x69637338 # "ics8"
|
||||
ICNS_16x16_32BIT_DATA = 0x69733332 # "is32"
|
||||
ICNS_16x16_1BIT_MASK = 0x69637323 # "ics#"
|
||||
ICNS_16x16_8BIT_MASK = 0x73386D6B # "s8mk"
|
||||
ICNS_16x16_1BIT_DATA = 0x69637323 # "ics#"
|
||||
ICNS_16x16_4BIT_DATA = 0x69637334 # "ics4"
|
||||
ICNS_16x16_8BIT_DATA = 0x69637338 # "ics8"
|
||||
ICNS_16x16_32BIT_DATA = 0x69733332 # "is32"
|
||||
ICNS_16x16_1BIT_MASK = 0x69637323 # "ics#"
|
||||
ICNS_16x16_8BIT_MASK = 0x73386D6B # "s8mk"
|
||||
|
||||
ICNS_16x12_1BIT_DATA = 0x69636D23 # "icm#"
|
||||
ICNS_16x12_4BIT_DATA = 0x69636D34 # "icm4"
|
||||
ICNS_16x12_1BIT_MASK = 0x69636D23 # "icm#"
|
||||
ICNS_16x12_8BIT_DATA = 0x69636D38 # "icm8"
|
||||
ICNS_16x12_1BIT_DATA = 0x69636D23 # "icm#"
|
||||
ICNS_16x12_4BIT_DATA = 0x69636D34 # "icm4"
|
||||
ICNS_16x12_1BIT_MASK = 0x69636D23 # "icm#"
|
||||
ICNS_16x12_8BIT_DATA = 0x69636D38 # "icm8"
|
||||
|
||||
ICNS_32x32_1BIT_ICON = 0x49434F4E # "ICON"
|
||||
ICNS_32x32_1BIT_ICON = 0x49434F4E # "ICON"
|
||||
|
||||
ICNS_TILE_VARIANT = 0x74696C65 # "tile"
|
||||
ICNS_ROLLOVER_VARIANT = 0x6F766572 # "over"
|
||||
ICNS_DROP_VARIANT = 0x64726F70 # "drop"
|
||||
ICNS_OPEN_VARIANT = 0x6F70656E # "open"
|
||||
ICNS_OPEN_DROP_VARIANT = 0x6F647270 # "odrp"
|
||||
ICNS_TILE_VARIANT = 0x74696C65 # "tile"
|
||||
ICNS_ROLLOVER_VARIANT = 0x6F766572 # "over"
|
||||
ICNS_DROP_VARIANT = 0x64726F70 # "drop"
|
||||
ICNS_OPEN_VARIANT = 0x6F70656E # "open"
|
||||
ICNS_OPEN_DROP_VARIANT = 0x6F647270 # "odrp"
|
||||
|
||||
ICNS_NULL_DATA = 0x00000000
|
||||
ICNS_NULL_MASK = 0x00000000
|
||||
|
||||
# icns file / resource type constants
|
||||
|
||||
ICNS_FAMILY_TYPE = 0x69636E73 # "icns"
|
||||
ICNS_FAMILY_TYPE = 0x69636E73 # "icns"
|
||||
|
||||
ICNS_MACBINARY_TYPE = 0x6D42494E # "mBIN"
|
||||
ICNS_MACBINARY_TYPE = 0x6D42494E # "mBIN"
|
||||
|
||||
ICNS_NULL_TYPE = 0x00000000
|
||||
|
||||
|
|
@ -79,43 +81,322 @@ ICNS_STATUS_UNSUPPORTED = 4
|
|||
|
||||
#---------------------------SYMBOL DICTS-------------------------------------#
|
||||
|
||||
struct_symbols = {1:'B',#byte
|
||||
2:'H',#word
|
||||
4:'I',#unsigned int/double word
|
||||
8:'Q' #quad word
|
||||
}
|
||||
struct_symbols = {1: 'B', # byte
|
||||
2: 'H', # word
|
||||
4: 'I', # unsigned int/double word
|
||||
8: 'Q' # quad word
|
||||
}
|
||||
|
||||
#used to easily get the icon type from dimensions
|
||||
type_dict = {'mask':{128:{8:ICNS_128x128_8BIT_MASK},
|
||||
48:{1:ICNS_48x48_1BIT_MASK,
|
||||
8:ICNS_48x48_8BIT_MASK},
|
||||
32:{1:ICNS_32x32_1BIT_MASK,
|
||||
8:ICNS_32x32_8BIT_MASK},
|
||||
16:{1:ICNS_16x16_1BIT_MASK,
|
||||
8:ICNS_16x16_8BIT_MASK},
|
||||
type_dict = {'mask': {128: {8: ICNS_128x128_8BIT_MASK},
|
||||
48: {1: ICNS_48x48_1BIT_MASK,
|
||||
8: ICNS_48x48_8BIT_MASK},
|
||||
32: {1: ICNS_32x32_1BIT_MASK,
|
||||
8: ICNS_32x32_8BIT_MASK},
|
||||
16: {1: ICNS_16x16_1BIT_MASK,
|
||||
8: ICNS_16x16_8BIT_MASK},
|
||||
},
|
||||
'data':{1024:{32:ICNS_1024x1024_32BIT_ARGB_DATA},
|
||||
512:{32:ICNS_512x512_32BIT_ARGB_DATA},
|
||||
256:{32:ICNS_256x256_32BIT_ARGB_DATA},
|
||||
128:{32:ICNS_128x128_32BIT_DATA},
|
||||
48:{1:ICNS_48x48_1BIT_DATA,
|
||||
4:ICNS_48x48_4BIT_DATA,
|
||||
8:ICNS_48x48_8BIT_DATA,
|
||||
32:ICNS_48x48_32BIT_DATA},
|
||||
32:{1:ICNS_32x32_1BIT_DATA,
|
||||
4:ICNS_32x32_4BIT_DATA,
|
||||
8:ICNS_32x32_8BIT_DATA,
|
||||
32:ICNS_32x32_32BIT_DATA},
|
||||
16:{1:ICNS_16x16_1BIT_DATA,
|
||||
4:ICNS_16x16_4BIT_DATA,
|
||||
8:ICNS_16x16_8BIT_DATA,
|
||||
32:ICNS_16x16_32BIT_DATA},
|
||||
'data': {1024: {32: ICNS_1024x1024_32BIT_ARGB_DATA},
|
||||
512: {32: ICNS_512x512_32BIT_ARGB_DATA},
|
||||
256: {32: ICNS_256x256_32BIT_ARGB_DATA},
|
||||
128: {32: ICNS_128x128_32BIT_DATA},
|
||||
48: {1: ICNS_48x48_1BIT_DATA,
|
||||
4: ICNS_48x48_4BIT_DATA,
|
||||
8: ICNS_48x48_8BIT_DATA,
|
||||
32: ICNS_48x48_32BIT_DATA},
|
||||
32: {1: ICNS_32x32_1BIT_DATA,
|
||||
4: ICNS_32x32_4BIT_DATA,
|
||||
8: ICNS_32x32_8BIT_DATA,
|
||||
32: ICNS_32x32_32BIT_DATA},
|
||||
16: {1: ICNS_16x16_1BIT_DATA,
|
||||
4: ICNS_16x16_4BIT_DATA,
|
||||
8: ICNS_16x16_8BIT_DATA,
|
||||
32: ICNS_16x16_32BIT_DATA},
|
||||
}}
|
||||
|
||||
|
||||
icns_colormap_4 = [
|
||||
[0xFF, 0xFF, 0xFF],
|
||||
[0xFC, 0xF3, 0x05],
|
||||
[0xFF, 0x64, 0x02],
|
||||
[0xDD, 0x08, 0x06],
|
||||
[0xF2, 0x08, 0x84],
|
||||
[0x46, 0x00, 0xA5],
|
||||
[0x00, 0x00, 0xD4],
|
||||
[0x02, 0xAB, 0xEA],
|
||||
[0x1F, 0xB7, 0x14],
|
||||
[0x00, 0x64, 0x11],
|
||||
[0x56, 0x2C, 0x05],
|
||||
[0x90, 0x71, 0x3A],
|
||||
[0xC0, 0xC0, 0xC0],
|
||||
[0x80, 0x80, 0x80],
|
||||
[0x40, 0x40, 0x40],
|
||||
[0x00, 0x00, 0x00]
|
||||
]
|
||||
|
||||
icns_colormap_8 =[
|
||||
[0xFF, 0xFF, 0xFF],
|
||||
[0xFF, 0xFF, 0xCC],
|
||||
[0xFF, 0xFF, 0x99],
|
||||
[0xFF, 0xFF, 0x66],
|
||||
[0xFF, 0xFF, 0x33],
|
||||
[0xFF, 0xFF, 0x00],
|
||||
[0xFF, 0xCC, 0xFF],
|
||||
[0xFF, 0xCC, 0xCC],
|
||||
[0xFF, 0xCC, 0x99],
|
||||
[0xFF, 0xCC, 0x66],
|
||||
[0xFF, 0xCC, 0x33],
|
||||
[0xFF, 0xCC, 0x00],
|
||||
[0xFF, 0x99, 0xFF],
|
||||
[0xFF, 0x99, 0xCC],
|
||||
[0xFF, 0x99, 0x99],
|
||||
[0xFF, 0x99, 0x66],
|
||||
[0xFF, 0x99, 0x33],
|
||||
[0xFF, 0x99, 0x00],
|
||||
[0xFF, 0x66, 0xFF],
|
||||
[0xFF, 0x66, 0xCC],
|
||||
[0xFF, 0x66, 0x99],
|
||||
[0xFF, 0x66, 0x66],
|
||||
[0xFF, 0x66, 0x33],
|
||||
[0xFF, 0x66, 0x00],
|
||||
[0xFF, 0x33, 0xFF],
|
||||
[0xFF, 0x33, 0xCC],
|
||||
[0xFF, 0x33, 0x99],
|
||||
[0xFF, 0x33, 0x66],
|
||||
[0xFF, 0x33, 0x33],
|
||||
[0xFF, 0x33, 0x00],
|
||||
[0xFF, 0x00, 0xFF],
|
||||
[0xFF, 0x00, 0xCC],
|
||||
[0xFF, 0x00, 0x99],
|
||||
[0xFF, 0x00, 0x66],
|
||||
[0xFF, 0x00, 0x33],
|
||||
[0xFF, 0x00, 0x00],
|
||||
[0xCC, 0xFF, 0xFF],
|
||||
[0xCC, 0xFF, 0xCC],
|
||||
[0xCC, 0xFF, 0x99],
|
||||
[0xCC, 0xFF, 0x66],
|
||||
[0xCC, 0xFF, 0x33],
|
||||
[0xCC, 0xFF, 0x00],
|
||||
[0xCC, 0xCC, 0xFF],
|
||||
[0xCC, 0xCC, 0xCC],
|
||||
[0xCC, 0xCC, 0x99],
|
||||
[0xCC, 0xCC, 0x66],
|
||||
[0xCC, 0xCC, 0x33],
|
||||
[0xCC, 0xCC, 0x00],
|
||||
[0xCC, 0x99, 0xFF],
|
||||
[0xCC, 0x99, 0xCC],
|
||||
[0xCC, 0x99, 0x99],
|
||||
[0xCC, 0x99, 0x66],
|
||||
[0xCC, 0x99, 0x33],
|
||||
[0xCC, 0x99, 0x00],
|
||||
[0xCC, 0x66, 0xFF],
|
||||
[0xCC, 0x66, 0xCC],
|
||||
[0xCC, 0x66, 0x99],
|
||||
[0xCC, 0x66, 0x66],
|
||||
[0xCC, 0x66, 0x33],
|
||||
[0xCC, 0x66, 0x00],
|
||||
[0xCC, 0x33, 0xFF],
|
||||
[0xCC, 0x33, 0xCC],
|
||||
[0xCC, 0x33, 0x99],
|
||||
[0xCC, 0x33, 0x66],
|
||||
[0xCC, 0x33, 0x33],
|
||||
[0xCC, 0x33, 0x00],
|
||||
[0xCC, 0x00, 0xFF],
|
||||
[0xCC, 0x00, 0xCC],
|
||||
[0xCC, 0x00, 0x99],
|
||||
[0xCC, 0x00, 0x66],
|
||||
[0xCC, 0x00, 0x33],
|
||||
[0xCC, 0x00, 0x00],
|
||||
[0x99, 0xFF, 0xFF],
|
||||
[0x99, 0xFF, 0xCC],
|
||||
[0x99, 0xFF, 0x99],
|
||||
[0x99, 0xFF, 0x66],
|
||||
[0x99, 0xFF, 0x33],
|
||||
[0x99, 0xFF, 0x00],
|
||||
[0x99, 0xCC, 0xFF],
|
||||
[0x99, 0xCC, 0xCC],
|
||||
[0x99, 0xCC, 0x99],
|
||||
[0x99, 0xCC, 0x66],
|
||||
[0x99, 0xCC, 0x33],
|
||||
[0x99, 0xCC, 0x00],
|
||||
[0x99, 0x99, 0xFF],
|
||||
[0x99, 0x99, 0xCC],
|
||||
[0x99, 0x99, 0x99],
|
||||
[0x99, 0x99, 0x66],
|
||||
[0x99, 0x99, 0x33],
|
||||
[0x99, 0x99, 0x00],
|
||||
[0x99, 0x66, 0xFF],
|
||||
[0x99, 0x66, 0xCC],
|
||||
[0x99, 0x66, 0x99],
|
||||
[0x99, 0x66, 0x66],
|
||||
[0x99, 0x66, 0x33],
|
||||
[0x99, 0x66, 0x00],
|
||||
[0x99, 0x33, 0xFF],
|
||||
[0x99, 0x33, 0xCC],
|
||||
[0x99, 0x33, 0x99],
|
||||
[0x99, 0x33, 0x66],
|
||||
[0x99, 0x33, 0x33],
|
||||
[0x99, 0x33, 0x00],
|
||||
[0x99, 0x00, 0xFF],
|
||||
[0x99, 0x00, 0xCC],
|
||||
[0x99, 0x00, 0x99],
|
||||
[0x99, 0x00, 0x66],
|
||||
[0x99, 0x00, 0x33],
|
||||
[0x99, 0x00, 0x00],
|
||||
[0x66, 0xFF, 0xFF],
|
||||
[0x66, 0xFF, 0xCC],
|
||||
[0x66, 0xFF, 0x99],
|
||||
[0x66, 0xFF, 0x66],
|
||||
[0x66, 0xFF, 0x33],
|
||||
[0x66, 0xFF, 0x00],
|
||||
[0x66, 0xCC, 0xFF],
|
||||
[0x66, 0xCC, 0xCC],
|
||||
[0x66, 0xCC, 0x99],
|
||||
[0x66, 0xCC, 0x66],
|
||||
[0x66, 0xCC, 0x33],
|
||||
[0x66, 0xCC, 0x00],
|
||||
[0x66, 0x99, 0xFF],
|
||||
[0x66, 0x99, 0xCC],
|
||||
[0x66, 0x99, 0x99],
|
||||
[0x66, 0x99, 0x66],
|
||||
[0x66, 0x99, 0x33],
|
||||
[0x66, 0x99, 0x00],
|
||||
[0x66, 0x66, 0xFF],
|
||||
[0x66, 0x66, 0xCC],
|
||||
[0x66, 0x66, 0x99],
|
||||
[0x66, 0x66, 0x66],
|
||||
[0x66, 0x66, 0x33],
|
||||
[0x66, 0x66, 0x00],
|
||||
[0x66, 0x33, 0xFF],
|
||||
[0x66, 0x33, 0xCC],
|
||||
[0x66, 0x33, 0x99],
|
||||
[0x66, 0x33, 0x66],
|
||||
[0x66, 0x33, 0x33],
|
||||
[0x66, 0x33, 0x00],
|
||||
[0x66, 0x00, 0xFF],
|
||||
[0x66, 0x00, 0xCC],
|
||||
[0x66, 0x00, 0x99],
|
||||
[0x66, 0x00, 0x66],
|
||||
[0x66, 0x00, 0x33],
|
||||
[0x66, 0x00, 0x00],
|
||||
[0x33, 0xFF, 0xFF],
|
||||
[0x33, 0xFF, 0xCC],
|
||||
[0x33, 0xFF, 0x99],
|
||||
[0x33, 0xFF, 0x66],
|
||||
[0x33, 0xFF, 0x33],
|
||||
[0x33, 0xFF, 0x00],
|
||||
[0x33, 0xCC, 0xFF],
|
||||
[0x33, 0xCC, 0xCC],
|
||||
[0x33, 0xCC, 0x99],
|
||||
[0x33, 0xCC, 0x66],
|
||||
[0x33, 0xCC, 0x33],
|
||||
[0x33, 0xCC, 0x00],
|
||||
[0x33, 0x99, 0xFF],
|
||||
[0x33, 0x99, 0xCC],
|
||||
[0x33, 0x99, 0x99],
|
||||
[0x33, 0x99, 0x66],
|
||||
[0x33, 0x99, 0x33],
|
||||
[0x33, 0x99, 0x00],
|
||||
[0x33, 0x66, 0xFF],
|
||||
[0x33, 0x66, 0xCC],
|
||||
[0x33, 0x66, 0x99],
|
||||
[0x33, 0x66, 0x66],
|
||||
[0x33, 0x66, 0x33],
|
||||
[0x33, 0x66, 0x00],
|
||||
[0x33, 0x33, 0xFF],
|
||||
[0x33, 0x33, 0xCC],
|
||||
[0x33, 0x33, 0x99],
|
||||
[0x33, 0x33, 0x66],
|
||||
[0x33, 0x33, 0x33],
|
||||
[0x33, 0x33, 0x00],
|
||||
[0x33, 0x00, 0xFF],
|
||||
[0x33, 0x00, 0xCC],
|
||||
[0x33, 0x00, 0x99],
|
||||
[0x33, 0x00, 0x66],
|
||||
[0x33, 0x00, 0x33],
|
||||
[0x33, 0x00, 0x00],
|
||||
[0x00, 0xFF, 0xFF],
|
||||
[0x00, 0xFF, 0xCC],
|
||||
[0x00, 0xFF, 0x99],
|
||||
[0x00, 0xFF, 0x66],
|
||||
[0x00, 0xFF, 0x33],
|
||||
[0x00, 0xFF, 0x00],
|
||||
[0x00, 0xCC, 0xFF],
|
||||
[0x00, 0xCC, 0xCC],
|
||||
[0x00, 0xCC, 0x99],
|
||||
[0x00, 0xCC, 0x66],
|
||||
[0x00, 0xCC, 0x33],
|
||||
[0x00, 0xCC, 0x00],
|
||||
[0x00, 0x99, 0xFF],
|
||||
[0x00, 0x99, 0xCC],
|
||||
[0x00, 0x99, 0x99],
|
||||
[0x00, 0x99, 0x66],
|
||||
[0x00, 0x99, 0x33],
|
||||
[0x00, 0x99, 0x00],
|
||||
[0x00, 0x66, 0xFF],
|
||||
[0x00, 0x66, 0xCC],
|
||||
[0x00, 0x66, 0x99],
|
||||
[0x00, 0x66, 0x66],
|
||||
[0x00, 0x66, 0x33],
|
||||
[0x00, 0x66, 0x00],
|
||||
[0x00, 0x33, 0xFF],
|
||||
[0x00, 0x33, 0xCC],
|
||||
[0x00, 0x33, 0x99],
|
||||
[0x00, 0x33, 0x66],
|
||||
[0x00, 0x33, 0x33],
|
||||
[0x00, 0x33, 0x00],
|
||||
[0x00, 0x00, 0xFF],
|
||||
[0x00, 0x00, 0xCC],
|
||||
[0x00, 0x00, 0x99],
|
||||
[0x00, 0x00, 0x66],
|
||||
[0x00, 0x00, 0x33],
|
||||
[0xEE, 0x00, 0x00],
|
||||
[0xDD, 0x00, 0x00],
|
||||
[0xBB, 0x00, 0x00],
|
||||
[0xAA, 0x00, 0x00],
|
||||
[0x88, 0x00, 0x00],
|
||||
[0x77, 0x00, 0x00],
|
||||
[0x55, 0x00, 0x00],
|
||||
[0x44, 0x00, 0x00],
|
||||
[0x22, 0x00, 0x00],
|
||||
[0x11, 0x00, 0x00],
|
||||
[0x00, 0xEE, 0x00],
|
||||
[0x00, 0xDD, 0x00],
|
||||
[0x00, 0xBB, 0x00],
|
||||
[0x00, 0xAA, 0x00],
|
||||
[0x00, 0x88, 0x00],
|
||||
[0x00, 0x77, 0x00],
|
||||
[0x00, 0x55, 0x00],
|
||||
[0x00, 0x44, 0x00],
|
||||
[0x00, 0x22, 0x00],
|
||||
[0x00, 0x11, 0x00],
|
||||
[0x00, 0x00, 0xEE],
|
||||
[0x00, 0x00, 0xDD],
|
||||
[0x00, 0x00, 0xBB],
|
||||
[0x00, 0x00, 0xAA],
|
||||
[0x00, 0x00, 0x88],
|
||||
[0x00, 0x00, 0x77],
|
||||
[0x00, 0x00, 0x55],
|
||||
[0x00, 0x00, 0x44],
|
||||
[0x00, 0x00, 0x22],
|
||||
[0x00, 0x00, 0x11],
|
||||
[0xEE, 0xEE, 0xEE],
|
||||
[0xDD, 0xDD, 0xDD],
|
||||
[0xBB, 0xBB, 0xBB],
|
||||
[0xAA, 0xAA, 0xAA],
|
||||
[0x88, 0x88, 0x88],
|
||||
[0x77, 0x77, 0x77],
|
||||
[0x55, 0x55, 0x55],
|
||||
[0x44, 0x44, 0x44],
|
||||
[0x22, 0x22, 0x22],
|
||||
[0x11, 0x11, 0x11],
|
||||
[0x00, 0x00, 0x00]
|
||||
]
|
||||
|
||||
|
||||
#---------------------------UTILITY FUNCTIONS---------------------------------#
|
||||
|
||||
def encode_rle24(data):
|
||||
encoded_data = bytearray()
|
||||
dataRun = bytearray(130)
|
||||
dataInChanSize = len(data)/4
|
||||
dataTempCount = 0
|
||||
|
|
@ -210,6 +491,44 @@ def encode_rle24(data):
|
|||
|
||||
return dataTemp[:dataTempCount]
|
||||
|
||||
def decode_rle24(data, pixel_count):
|
||||
color_value = 0
|
||||
run_length = 0
|
||||
data_offset = 0
|
||||
pixel_offset = 0
|
||||
i = 0
|
||||
dest_icon_data = bytearray(pixel_count*4)
|
||||
|
||||
if from_bytes(data[:4]) == 0:
|
||||
data_offset = 4
|
||||
color_offset = 0
|
||||
while color_offset < 3:
|
||||
pixel_offset = 0
|
||||
while (pixel_offset < pixel_count) and (data_offset < len(data)):
|
||||
if ((data[data_offset] & 0x80) == 0):
|
||||
run_length = (0xFF & data[data_offset]) + 1
|
||||
data_offset += 1
|
||||
i = 0
|
||||
while (i < run_length) and (pixel_offset < pixel_count) and (data_offset < len(data)):
|
||||
dest_icon_data[(pixel_offset*4)+color_offset] = data[data_offset]
|
||||
pixel_offset += 1
|
||||
data_offset += 1
|
||||
i += 1
|
||||
else:
|
||||
run_length = (0xFF & data[data_offset]) - 125
|
||||
data_offset += 1
|
||||
color_value = data[data_offset]
|
||||
data_offset += 1
|
||||
i = 0
|
||||
while (i < run_length) and (pixel_offset < pixel_count):
|
||||
dest_icon_data[(pixel_offset*4)+color_offset] = color_value
|
||||
pixel_offset += 1
|
||||
i += 1
|
||||
color_offset += 1
|
||||
|
||||
return dest_icon_data
|
||||
|
||||
|
||||
def get_mask_type_for_icon_type(icon_type):
|
||||
if icon_type == ICNS_TABLE_OF_CONTENTS or\
|
||||
icon_type == ICNS_ICON_VERSION or\
|
||||
|
|
@ -259,6 +578,22 @@ def get_mask_type_for_icon_type(icon_type):
|
|||
|
||||
return ICNS_NULL_MASK
|
||||
|
||||
|
||||
def to_bytes(n, length, endianess='big'):
|
||||
h = '%x' % n
|
||||
s = ('0'*(len(h) % 2) + h).zfill(length*2).decode('hex')
|
||||
return s if endianess == 'big' else s[::-1]
|
||||
|
||||
|
||||
def from_bytes(byte_str):
|
||||
bits = (len(byte_str)-1)*8
|
||||
result = 0
|
||||
for i in xrange(len(byte_str)):
|
||||
result = (byte_str[i] << bits) + result
|
||||
bits -= 8
|
||||
return result
|
||||
|
||||
|
||||
def type_to_str(type):
|
||||
s = bytearray()
|
||||
s.append(type >> 24 & 0xff)
|
||||
|
|
@ -678,7 +1013,6 @@ class ICNSHeader(Structure):
|
|||
icon_type = icns_info.get_image_type()
|
||||
mask_type = get_mask_type_for_icon_type(icon_type)
|
||||
|
||||
|
||||
if mask_type != ICNS_NULL_MASK:
|
||||
icns_mask = ICNSInfo.from_type(mask_type)
|
||||
|
||||
|
|
@ -695,7 +1029,6 @@ class ICNSHeader(Structure):
|
|||
mask_element.Size = len(icns_mask.data) + mask_element.size
|
||||
mask_element.icns_image = icns_mask
|
||||
|
||||
|
||||
icns_element.TypeID = icon_type
|
||||
icns_element.Size = len(encoded_data) + icns_element.size
|
||||
icns_element.icns_image = icns_info
|
||||
|
|
@ -706,7 +1039,7 @@ class ICNSHeader(Structure):
|
|||
self.elements.append(icns_element)
|
||||
self.elements.append(mask_element)
|
||||
|
||||
else:#just use the png data
|
||||
else: # just use the png data
|
||||
icns_element.TypeID = icon_type
|
||||
icns_element.Size = len(encoded_data) + icns_element.size
|
||||
icns_element.icns_image = icns_info
|
||||
|
|
@ -720,11 +1053,379 @@ class ICNSHeader(Structure):
|
|||
return self.dump()+f_data
|
||||
|
||||
|
||||
|
||||
|
||||
class ICNSElement(Structure):
|
||||
_fields = [Field('TypeID', 4),
|
||||
Field('Size', 4)]
|
||||
|
||||
icns_image = None
|
||||
data = None
|
||||
|
||||
@classmethod
|
||||
def from_family(cls, icns_data, icon_type):
|
||||
resource_size = len(icns_data)
|
||||
offset = 8
|
||||
found_data = False
|
||||
icon_element = cls()
|
||||
|
||||
while not found_data and offset < resource_size:
|
||||
icon_element.TypeID = from_bytes(icns_data[offset:offset+4])
|
||||
icon_element.Size = from_bytes(icns_data[offset+4:offset+8])
|
||||
size = from_bytes(icns_data[offset+4:offset+8])
|
||||
icon_element.data = icns_data[offset+8:offset+size]
|
||||
|
||||
if icon_element.TypeID == icon_type:
|
||||
found_data = True
|
||||
else:
|
||||
offset += icon_element.Size
|
||||
|
||||
return icon_element
|
||||
|
||||
def get_image(self):
|
||||
icon_type = self.TypeID
|
||||
raw_data_size = self.Size - 8
|
||||
data = self.data
|
||||
|
||||
icns_info = ICNSInfo()
|
||||
icns_info.isImage = 1
|
||||
|
||||
if icon_type in [ICNS_256x256_32BIT_ARGB_DATA,
|
||||
ICNS_512x512_32BIT_ARGB_DATA,
|
||||
ICNS_1024x1024_32BIT_ARGB_DATA]:
|
||||
magic_png = bytearray([0x89, 0x50, 0x4E, 0x47,
|
||||
0x0D, 0x0A, 0x1A, 0x0A])
|
||||
magic_read = data[:8]
|
||||
|
||||
if magic_png == magic_read:
|
||||
png_file = png.Reader(bytes=data)
|
||||
|
||||
width, height, png_data, stats_dict = png_file.read_flat()
|
||||
|
||||
bpp = stats_dict['bitdepth'] * 4
|
||||
|
||||
icns_info = ICNSInfo()
|
||||
icns_info.isImage = 1
|
||||
icns_info.iconSize.width = width
|
||||
icns_info.iconSize.height = height
|
||||
icns_info.iconBitDepth = bpp
|
||||
icns_info.iconChannels = 4 if bpp == 32 else 1
|
||||
icns_info.iconPixelDepth = bpp / icns_info.iconChannels
|
||||
icns_info.iconRawDataSize = width * height * 4
|
||||
icns_info.data = bytearray(list(png_data))
|
||||
else:
|
||||
image = Image.open(StringIO(data))
|
||||
mode_to_bpp = {'1':1, 'L':8, 'P':8, 'RGB':24, 'RGBA':32, 'CMYK':32, 'YCbCr':24, 'I':32, 'F':32}
|
||||
output = StringIO()
|
||||
bpp = mode_to_bpp[image.mode]
|
||||
image.save(output, format='PNG')
|
||||
png_data = bytearray(output.getvalue())
|
||||
|
||||
icns_info = ICNSInfo()
|
||||
icns_info.isImage = 1
|
||||
icns_info.iconSize.width = image.size[0]
|
||||
icns_info.iconSize.height = image.size[1]
|
||||
icns_info.iconBitDepth = bpp
|
||||
icns_info.iconChannels = 4 if bpp == 32 else 1
|
||||
icns_info.iconPixelDepth = bpp / icns_info.iconChannels
|
||||
icns_info.iconRawDataSize = image.size[0] * image.size[1] * 4
|
||||
icns_info.data = png_data
|
||||
|
||||
else:
|
||||
icns_info = ICNSInfo.from_type(icon_type)
|
||||
|
||||
if icon_type in [ICNS_128x128_32BIT_DATA,
|
||||
ICNS_48x48_32BIT_DATA,
|
||||
ICNS_32x32_32BIT_DATA,
|
||||
ICNS_16x16_32BIT_DATA]:
|
||||
icon_bit_depth = icns_info.iconPixelDepth * icns_info.iconChannels
|
||||
icon_data_row_size = icns_info.iconSize.width * icon_bit_depth*ICNS_BYTE_BITS
|
||||
|
||||
if raw_data_size < icns_info.iconRawDataSize:
|
||||
pixel_count = icns_info.iconSize.width*icns_info.iconSize.height
|
||||
decoded_data = decode_rle24(data, pixel_count)
|
||||
icns_info.data = decoded_data
|
||||
else:
|
||||
data_count = 0
|
||||
pixel_count = 0
|
||||
while data_count < icns_info.iconSize.width:
|
||||
data_pos = data_count * icon_data_row_size
|
||||
icns_info.data[data_pos:data_pos+icon_data_row_size] = data[data_pos:data_pos+icon_data_row_size]
|
||||
data_count += 1
|
||||
pixel_count = icns_info.iconSize.width*icns_info.iconSize.height
|
||||
data_count = 0
|
||||
while data_count < pixel_count:
|
||||
argb = icns_info.data[data_count*4:data_count*4+4]
|
||||
rgba = [argb[1], argb[2], argb[3], argb[0]]
|
||||
icns_info.data[data_count*4:data_count*4+4] = rgba
|
||||
data_count += 1
|
||||
elif icon_type in [ICNS_48x48_8BIT_DATA,
|
||||
ICNS_32x32_8BIT_DATA,
|
||||
ICNS_16x16_8BIT_DATA,
|
||||
ICNS_16x12_8BIT_DATA,
|
||||
ICNS_48x48_4BIT_DATA,
|
||||
ICNS_32x32_4BIT_DATA,
|
||||
ICNS_16x16_4BIT_DATA,
|
||||
ICNS_16x12_4BIT_DATA,
|
||||
ICNS_48x48_1BIT_DATA,
|
||||
ICNS_32x32_1BIT_DATA,
|
||||
ICNS_16x16_1BIT_DATA,
|
||||
ICNS_16x12_1BIT_DATA]:
|
||||
icon_bit_depth = icns_info.iconPixelDepth * icns_info.iconChannels
|
||||
icon_data_row_size = icns_info.iconSize.width * icon_bit_depth*ICNS_BYTE_BITS
|
||||
data_count = 0
|
||||
while data_count < icns_info.iconSize.width:
|
||||
data_pos = data_count * icon_data_row_size
|
||||
icns_info.data[data_pos:data_pos+icon_data_row_size] = data[data_pos:data_pos+icon_data_row_size]
|
||||
data_count += 1
|
||||
|
||||
return icns_info
|
||||
|
||||
def get_mask(self):
|
||||
element_type = self.TypeID
|
||||
element_size = self.Size
|
||||
mask_type = element_type
|
||||
raw_data_size = element_size - 8
|
||||
data = self.data
|
||||
icns_info = ICNSInfo.from_type(mask_type)
|
||||
mask_bit_depth = icns_info.iconSize.width * icns_info.iconSize.height
|
||||
mask_data_size = icns_info.iconRawDataSize
|
||||
mask_data_row_size = icns_info.iconSize.width * mask_bit_depth / ICNS_BYTE_BITS
|
||||
|
||||
if mask_type in [ICNS_128x128_8BIT_MASK,
|
||||
ICNS_48x48_8BIT_MASK,
|
||||
ICNS_32x32_8BIT_MASK,
|
||||
ICNS_16x16_8BIT_MASK]:
|
||||
data_count = 0
|
||||
while data_count < icns_info.iconSize.height:
|
||||
data_pos = data_count * mask_data_row_size
|
||||
icns_info.data[data_pos:data_pos+mask_data_row_size] = data[data_pos:data_pos+mask_data_row_size]
|
||||
data_count += 1
|
||||
|
||||
elif mask_type in [ICNS_48x48_1BIT_MASK,
|
||||
ICNS_32x32_1BIT_MASK,
|
||||
ICNS_16x16_1BIT_MASK,
|
||||
ICNS_16x12_1BIT_MASK]:
|
||||
if raw_data_size == mask_data_size*2:
|
||||
data_count = 0
|
||||
while data_count < icns_info.iconSize.height:
|
||||
data_pos = data_count * mask_data_row_size
|
||||
icns_info.data[data_pos:data_pos+mask_data_row_size] = data[data_pos+mask_data_size:data_pos+mask_data_row_size+mask_data_size]
|
||||
data_count += 1
|
||||
|
||||
else:
|
||||
data_count = 0
|
||||
while data_count < icns_info.iconSize.height:
|
||||
data_pos = data_count * mask_data_row_size
|
||||
icns_info.data[data_pos:data_pos+mask_data_row_size] = data[data_pos:data_pos+mask_data_row_size]
|
||||
data_count += 1
|
||||
return icns_info
|
||||
|
||||
|
||||
def icns_read_be(icns_data, size):
|
||||
icns_bytes = icns_data[:size]
|
||||
|
||||
if size == 1:
|
||||
return icns_bytes[0]
|
||||
elif size == 2:
|
||||
return icns_bytes[1] | icns_bytes[0] << 8
|
||||
elif size == 3:
|
||||
return (icns_bytes[2] & 0xffff | icns_bytes[1] & 0xffff << 8| icns_bytes[0] & 0xffff << 16) & 0x00FFFFFF
|
||||
elif size == 4:
|
||||
return icns_bytes[3] | icns_bytes[2] << 8 | icns_bytes[1] << 16 | icns_bytes[0] << 24
|
||||
elif size == 8:
|
||||
b = icns_bytes
|
||||
return b[7] | b[6] << 8 | b[5] << 16 | b[4] << 24 | b[3] << 32 | b[2] << 40 | b[1] << 48 | b[0] << 56
|
||||
|
||||
|
||||
def icns_header_check(icns_data):
|
||||
resource_type = icns_read_be(icns_data, 4)
|
||||
resource_size = icns_read_be(icns_data[4:], 4)
|
||||
|
||||
if resource_type != ICNS_FAMILY_TYPE:
|
||||
raise Exception('File is not an ICNS file.')
|
||||
if resource_size != len(icns_data):
|
||||
raise Exception('Expected size {}, but got {}'.format(len(icns_data)))
|
||||
|
||||
|
||||
def icns_parse_family_data(icns_data):
|
||||
resource_type = icns_read_be(icns_data, 4)
|
||||
resource_size = icns_read_be(icns_data[4:], 4)
|
||||
|
||||
if resource_type == ICNS_FAMILY_TYPE:
|
||||
if len(icns_data) == resource_size:
|
||||
icns_data[:4] = to_bytes(resource_type, 4)
|
||||
icns_data[4:8] = to_bytes(resource_size, 4)
|
||||
|
||||
offset = 8
|
||||
while (offset+8) < resource_size:
|
||||
element_type = icns_read_be(icns_data[offset:], 4)
|
||||
element_size = icns_read_be(icns_data[offset+4:], 4)
|
||||
icns_data[offset:offset+4] = to_bytes(element_type, 4)
|
||||
icns_data[offset+4:offset+8] = to_bytes(element_size, 4)
|
||||
offset += element_size
|
||||
return icns_data
|
||||
|
||||
def get_image_with_mask(icns_data, element_type):
|
||||
element = ICNSElement.from_family(icns_data, element_type)
|
||||
icns_image = element.get_image()
|
||||
if element_type in [ICNS_256x256_32BIT_ARGB_DATA,
|
||||
ICNS_512x512_32BIT_ARGB_DATA,
|
||||
ICNS_1024x1024_32BIT_ARGB_DATA]:
|
||||
return icns_image
|
||||
mask_type = get_mask_type_for_icon_type(element_type)
|
||||
mask_element = ICNSElement.from_family(icns_data, mask_type)
|
||||
mask_image = mask_element.get_mask()
|
||||
|
||||
old_bit_depth = icns_image.iconPixelDepth * icns_image.iconChannels
|
||||
if old_bit_depth < 32:
|
||||
old_bit_depth = icns_image.iconPixelDepth * icns_image.iconChannels
|
||||
pixel_count = icns_image.iconSize.width * icns_image.iconSize.height
|
||||
new_block_size = icns_image.iconSize.width * 32
|
||||
new_data_size = new_block_size * icns_image.iconSize.height
|
||||
|
||||
old_data = icns_image.data
|
||||
new_data = bytearray(new_data_size)
|
||||
|
||||
data_count = 0
|
||||
|
||||
if element_type in [ICNS_48x48_8BIT_DATA,
|
||||
ICNS_32x32_8BIT_DATA,
|
||||
ICNS_16x16_8BIT_DATA,
|
||||
ICNS_16x12_8BIT_DATA]:
|
||||
for pixel_id in xrange(pixel_count):
|
||||
color_index = old_data[data_count]
|
||||
color_rgb = icns_colormap_8[color_index]
|
||||
new_data[pixel_id*4+0] = color_rgb[0]
|
||||
new_data[pixel_id*4+1] = color_rgb[1]
|
||||
new_data[pixel_id*4+2] = color_rgb[2]
|
||||
new_data[pixel_id*4+3] = 0xFF
|
||||
data_count += 1
|
||||
elif element_type in [ICNS_48x48_4BIT_DATA,
|
||||
ICNS_32x32_4BIT_DATA,
|
||||
ICNS_16x16_4BIT_DATA,
|
||||
ICNS_16x12_4BIT_DATA]:
|
||||
data_value = 0
|
||||
for pixel_id in xrange(pixel_count):
|
||||
if (pixel_id % 2) == 0:
|
||||
data_value = old_data[data_count]
|
||||
data_count += 1
|
||||
color_index = (data_value & 0xF0) >> 4
|
||||
color_rgb = icns_colormap_4[color_index]
|
||||
new_data[pixel_id*4+0] = color_rgb[0]
|
||||
new_data[pixel_id*4+1] = color_rgb[1]
|
||||
new_data[pixel_id*4+2] = color_rgb[2]
|
||||
new_data[pixel_id*4+3] = 0xFF
|
||||
elif element_type in [ICNS_48x48_1BIT_DATA,
|
||||
ICNS_32x32_1BIT_DATA,
|
||||
ICNS_16x16_1BIT_DATA,
|
||||
ICNS_16x12_1BIT_DATA]:
|
||||
data_value = 0
|
||||
for pixel_id in xrange(pixel_count):
|
||||
if (pixel_id % 8) == 0:
|
||||
data_value = old_data[data_count]
|
||||
data_count += 1
|
||||
color_index = 0x00 if (data_value & 0x80) else 0xFF
|
||||
data_value = data_value << 1
|
||||
new_data[pixel_id*4+0] = color_index
|
||||
new_data[pixel_id*4+1] = color_index
|
||||
new_data[pixel_id*4+2] = color_index
|
||||
new_data[pixel_id*4+3] = 0xFF
|
||||
|
||||
icns_image.iconPixelDepth = 8
|
||||
icns_image.iconChannels = 4
|
||||
icns_image.iconRawDataSize = new_data_size
|
||||
icns_image.data = new_data
|
||||
|
||||
if mask_type in [ICNS_128x128_8BIT_MASK,
|
||||
ICNS_48x48_8BIT_MASK,
|
||||
ICNS_32x32_8BIT_MASK,
|
||||
ICNS_16x16_8BIT_MASK]:
|
||||
pixel_count = mask_image.iconSize.width * mask_image.iconSize.height
|
||||
data_count = 0
|
||||
for pixel_id in xrange(pixel_count):
|
||||
icns_image.data[pixel_id*4+3] = mask_image.data[data_count]
|
||||
data_count += 1
|
||||
|
||||
elif mask_type in [ICNS_48x48_1BIT_MASK,
|
||||
ICNS_32x32_1BIT_MASK,
|
||||
ICNS_16x16_1BIT_MASK,
|
||||
ICNS_16x12_1BIT_MASK]:
|
||||
pixel_count = mask_image.iconSize.width * mask_image.iconSize.height
|
||||
data_count = 0
|
||||
data_value = 0
|
||||
for pixel_id in xrange(pixel_count):
|
||||
if (pixel_id % 8) == 0:
|
||||
data_value = mask_image.data[data_count]
|
||||
data_count += 1
|
||||
color_index = 0xFF if (data_value & 0x80) else 0x00
|
||||
data_value = data_value << 1
|
||||
icns_image.data[pixel_id*4+3] = color_index
|
||||
im = Image.frombytes('RGBA', [icns_image.iconSize.width,icns_image.iconSize.height],str(icns_image.data))
|
||||
output = StringIO()
|
||||
im.save(output, format='PNG')
|
||||
icns_image.data = bytearray(output.getvalue())
|
||||
|
||||
return icns_image
|
||||
|
||||
|
||||
def extract_icons(all_icns_data):
|
||||
image_count = 0
|
||||
stack = [all_icns_data]
|
||||
data = []
|
||||
|
||||
while stack:
|
||||
|
||||
offset = 8
|
||||
icns_data = stack.pop()
|
||||
|
||||
while ((offset+8) < len(icns_data)):
|
||||
element = ICNSElement()
|
||||
element.TypeID = from_bytes(icns_data[offset:offset+4])
|
||||
element.Size = from_bytes(icns_data[offset+4:offset+8])
|
||||
|
||||
if element.TypeID == ICNS_TABLE_OF_CONTENTS:
|
||||
pass
|
||||
elif element.TypeID in [ICNS_TILE_VARIANT,
|
||||
ICNS_ROLLOVER_VARIANT,
|
||||
ICNS_DROP_VARIANT,
|
||||
ICNS_OPEN_VARIANT,
|
||||
ICNS_OPEN_DROP_VARIANT]:
|
||||
variant_data = icns_data[offset:offset+element.Size]
|
||||
variant_data[:4] = 'icns'
|
||||
variant_data[4:8] = to_bytes(element.Size, 4)
|
||||
variant_data = icns_parse_family_data(variant_data)
|
||||
stack.append(variant_data)
|
||||
|
||||
else:
|
||||
icon_info = ICNSInfo.from_type(element.TypeID)
|
||||
if icon_info.isImage:
|
||||
image_count += 1
|
||||
|
||||
image_data = get_image_with_mask(icns_data, element.TypeID)
|
||||
image_data.data = str(image_data.data)
|
||||
data.append(image_data)
|
||||
|
||||
offset += element.Size
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def icns_to_png(icns_file, out_file=None):
|
||||
|
||||
if not os.path.exists(icns_file):
|
||||
return
|
||||
|
||||
icns_fp = open(icns_file, 'rb')
|
||||
icns_data = bytearray(icns_fp.read())
|
||||
icns_fp.close()
|
||||
|
||||
icns_header_check(icns_data)
|
||||
new_data = icns_parse_family_data(icns_data)
|
||||
|
||||
icons = extract_icons(new_data)
|
||||
#for image in icons:
|
||||
# fname = 'test{}.png'.format(image.iconSize.width)
|
||||
# print fname
|
||||
# f = open(fname, 'wb+')
|
||||
# f.write(image.data)
|
||||
# f.close()
|
||||
return icons
|
||||
|
|
|
|||
12
main.py
12
main.py
|
|
@ -12,7 +12,7 @@ from PySide.QtGui import QApplication, QHBoxLayout, QVBoxLayout
|
|||
from PySide.QtNetwork import QHttp
|
||||
from PySide.QtCore import QUrl, QFile, QIODevice, QCoreApplication
|
||||
|
||||
|
||||
from pycns import pngs_from_icns
|
||||
from command_line import CommandBase, logger, get_file
|
||||
|
||||
MAX_RECENT = 10
|
||||
|
|
@ -704,9 +704,13 @@ class MainWindow(QtGui.QMainWindow, CommandBase):
|
|||
icon_path = os.path.join(self.project_dir(), icon_path)
|
||||
if os.path.exists(icon_path):
|
||||
if icon_path.endswith('.icns'):
|
||||
#image = QtGui.QImage.fromData(make_thumbnail(icon_path,48), 'png')
|
||||
return
|
||||
image = QtGui.QImage(icon_path)
|
||||
pngs = pngs_from_icns(icon_path)
|
||||
if pngs:
|
||||
image = QtGui.QImage.fromData(QtCore.QByteArray(pngs[-1].data), 'PNG')
|
||||
else:
|
||||
return
|
||||
else:
|
||||
image = QtGui.QImage(icon_path)
|
||||
if image.width() >= image.height():
|
||||
image = image.scaledToWidth(48,
|
||||
QtCore.Qt.SmoothTransformation)
|
||||
|
|
|
|||
8
pycns.py
8
pycns.py
|
|
@ -1,4 +1,4 @@
|
|||
from icns_info import *
|
||||
from icns_info import ICNSHeader, icns_to_png
|
||||
from image_utils import Image
|
||||
import sys
|
||||
|
||||
|
|
@ -6,6 +6,7 @@ import sys
|
|||
The image will be scaled keeping the aspect ratio if it is a non square image.
|
||||
"""
|
||||
|
||||
|
||||
def encode_image_to_icns(image_path):
|
||||
"""Takes an image and converts it to icns. Image aspect ratio will remain intact."""
|
||||
i = Image(image_path)
|
||||
|
|
@ -13,12 +14,17 @@ def encode_image_to_icns(image_path):
|
|||
f_data = icns_header.parse_image(i)
|
||||
return f_data
|
||||
|
||||
|
||||
def save_icns(image_path, icns_path):
|
||||
im_data = encode_image_to_icns(image_path)
|
||||
if im_data is not None:
|
||||
icns_path = icns_path if icns_path.endswith('.icns') else icns_path+'.icns'
|
||||
open(icns_path, 'wb+').write(im_data)
|
||||
|
||||
|
||||
def pngs_from_icns(icns_path):
|
||||
return icns_to_png(icns_path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) != 3:
|
||||
print 'Usage: pycns input_image_path output_icns_path'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue