Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b0252f987 | ||
|
|
d5d77fa592 | ||
|
|
eb7ce460b5 | ||
|
|
f80d7d79f6 | ||
|
|
bc6fe5a2b3 | ||
|
|
028df18dbc |
1
MANIFEST.in
Normal file
1
MANIFEST.in
Normal file
@@ -0,0 +1 @@
|
||||
include LICENSE
|
||||
@@ -172,6 +172,10 @@ class IcnsFile:
|
||||
# Nested icns files must omit the icns header
|
||||
if is_icns and data[:4] == b'icns':
|
||||
data = data[8:]
|
||||
if key in ('icp4', 'icp5'):
|
||||
iType = IcnsType.get(key)
|
||||
print('Warning: deprecated "{}"({}) use argb instead'.format(
|
||||
str(key), iType.filename(size_only=True)), file=stderr)
|
||||
self.media[key] = data
|
||||
|
||||
def remove_media(self, key: IcnsType.Media.KeyT) -> bool:
|
||||
|
||||
@@ -29,6 +29,32 @@ def determine_file_ext(data: bytes) -> Optional[str]:
|
||||
return None
|
||||
|
||||
|
||||
def _determine_jp2_size(data: bytes) -> Optional[Tuple[int, int]]:
|
||||
''' Read raw bytes and extract JPEG2000 image size. '''
|
||||
if data[:4] == b'\xFF\x4F\xFF\x51':
|
||||
w, h = struct.unpack('>II', data[8:16])
|
||||
return w, h
|
||||
|
||||
# fixed "jP" file header 0000000C 6A502020 0D0A870A
|
||||
off = 12
|
||||
filesize = len(data)
|
||||
|
||||
while off < filesize:
|
||||
box_size, box_type = struct.unpack('>I4s', data[off:off+8])
|
||||
# find JP2 Header box
|
||||
if box_type == b'jp2h':
|
||||
child = off + 8 # skip parent header
|
||||
while child < (off + box_size):
|
||||
# find Image Header box
|
||||
if data[child+4:child+8] == b'ihdr':
|
||||
h, w = struct.unpack('>II', data[child+8:child+16])
|
||||
return w, h
|
||||
|
||||
child += struct.unpack('>I', data[child:child+4])[0]
|
||||
off += box_size
|
||||
return None
|
||||
|
||||
|
||||
def determine_image_size(data: bytes, ext: Optional[str] = None) \
|
||||
-> Optional[Tuple[int, int]]:
|
||||
''' Supports PNG, ARGB, and Jpeg 2000 image data. '''
|
||||
@@ -45,14 +71,7 @@ def determine_image_size(data: bytes, ext: Optional[str] = None) \
|
||||
data = data[4:] # without it32 header
|
||||
return IcnsType.match_maxsize(PackBytes.get_size(data), 'rgb').size
|
||||
elif ext == 'jp2':
|
||||
if data[:4] == b'\xFF\x4F\xFF\x51':
|
||||
w, h = struct.unpack('>II', data[8:16])
|
||||
return w, h
|
||||
len_ftype = struct.unpack('>I', data[12:16])[0]
|
||||
# file header + type box + header box (super box) + image header box
|
||||
offset = 12 + len_ftype + 8 + 8
|
||||
h, w = struct.unpack('>II', data[offset:offset + 8])
|
||||
return w, h
|
||||
return _determine_jp2_size(data)
|
||||
return None # icns does not support other image types except binary
|
||||
|
||||
|
||||
|
||||
0
icnsutil/autosize/ImageResizer.py
Executable file → Normal file
0
icnsutil/autosize/ImageResizer.py
Executable file → Normal file
0
icnsutil/autosize/PixelResizer.py
Executable file → Normal file
0
icnsutil/autosize/PixelResizer.py
Executable file → Normal file
6
icnsutil/autosize/SVGResizer.py
Executable file → Normal file
6
icnsutil/autosize/SVGResizer.py
Executable file → Normal file
@@ -39,7 +39,7 @@ class ChromeSVG(SVGResizer):
|
||||
|
||||
def resize(self, size: int, fname_out: str) -> None:
|
||||
run([self.exe, '--headless', '--disable-gpu', '--hide-scrollbars',
|
||||
'--force-device-scale-factor=1', '--default-background-color=0',
|
||||
'--window-size={0},{0}'.format(self.preferred_size),
|
||||
'--screenshot="{}"'.format(self.fname), self.fname],
|
||||
'--force-device-scale-factor=1', '--default-background-color=000000',
|
||||
'--window-size={0},{0}'.format(size),
|
||||
'--screenshot={}'.format(fname_out), self.fname],
|
||||
stderr=DEVNULL)
|
||||
|
||||
0
icnsutil/autosize/helper.py
Executable file → Normal file
0
icnsutil/autosize/helper.py
Executable file → Normal file
3
setup.py
3
setup.py
@@ -2,7 +2,7 @@
|
||||
from setuptools import setup
|
||||
from icnsutil import __doc__, __version__
|
||||
|
||||
with open('README.md') as fp:
|
||||
with open('README.md', encoding='utf-8') as fp:
|
||||
longdesc = fp.read()
|
||||
|
||||
setup(
|
||||
@@ -52,4 +52,5 @@ setup(
|
||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||
'Topic :: Utilities',
|
||||
],
|
||||
include_package_data=True
|
||||
)
|
||||
|
||||
BIN
tests/fixtures/32x32.jpf
vendored
Normal file
BIN
tests/fixtures/32x32.jpf
vendored
Normal file
Binary file not shown.
@@ -146,6 +146,7 @@ class TestCLI_compose(unittest.TestCase):
|
||||
def test_jp2(self):
|
||||
self.assert_conv_file('256x256.jp2', 'ic08')
|
||||
self.assert_conv_file('18x18.j2k', 'icsb', arg=['-f'])
|
||||
self.assert_conv_file('32x32.jpf', 'icp5', arg=['-f'])
|
||||
|
||||
def test_argb(self):
|
||||
self.assert_conv_file('rgb.icns.argb', 'ic04')
|
||||
@@ -258,10 +259,10 @@ class TestCLI_convert(unittest.TestCase):
|
||||
|
||||
def test_to_png(self):
|
||||
for expected_size, fname in [
|
||||
(103, '18x18.j2k'),
|
||||
(4778, '256x256.jp2'),
|
||||
(813, 'rgb.icns.png'),
|
||||
(813, 'rgb.icns.rgb'),
|
||||
(107, '18x18.j2k'),
|
||||
(4496, '256x256.jp2'),
|
||||
(818, 'rgb.icns.png'),
|
||||
(818, 'rgb.icns.rgb'),
|
||||
]:
|
||||
size = self.assertConvert(fname, 'png')
|
||||
self.assertEqual(size, expected_size)
|
||||
@@ -292,7 +293,7 @@ class TestCLI_convert(unittest.TestCase):
|
||||
def test_without_dest_name(self):
|
||||
src = 'tmp_cli_out_convert.jp2'
|
||||
shutil.copy('18x18.j2k', src)
|
||||
for ext, size in [('png', 103), ('argb', 822), ('rgb', 812)]:
|
||||
for ext, size in [('png', 107), ('argb', 822), ('rgb', 812)]:
|
||||
run_cli(['img', ext, src]).stdout
|
||||
self.assertTrue(os.path.exists(src + '.' + ext))
|
||||
self.assertEqual(os.path.getsize(src + '.' + ext), size)
|
||||
|
||||
@@ -444,6 +444,7 @@ class TestRawData(unittest.TestCase):
|
||||
self.assertEqual(fn('rgb.icns.argb'), (16, 16))
|
||||
self.assertEqual(fn('256x256.jp2'), (256, 256))
|
||||
self.assertEqual(fn('18x18.j2k'), (18, 18))
|
||||
self.assertEqual(fn('32x32.jpf'), (32, 32))
|
||||
|
||||
def test_ext(self):
|
||||
for data, ext in (
|
||||
|
||||
Reference in New Issue
Block a user