From 9d126fbc8c975479d9e69be5434e1ba37337eb00 Mon Sep 17 00:00:00 2001 From: rpm-build Date: Aug 05 2020 14:57:55 +0000 Subject: python-imagesize-1.0.0 base --- diff --git a/LICENSE.rst b/LICENSE.rst new file mode 100644 index 0000000..58a2394 --- /dev/null +++ b/LICENSE.rst @@ -0,0 +1,19 @@ +The MIT License (MIT) +---------------------------- + +Copyright © 2016 Yoshiki Shibukawa + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the “Software”), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH +THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..afe1754 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include LICENSE.rst +graft test diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 0000000..ed0d5b9 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,36 @@ +Metadata-Version: 1.1 +Name: imagesize +Version: 1.0.0 +Summary: Getting image size from png/jpeg/jpeg2000/gif file +Home-page: https://github.com/shibukawa/imagesize_py +Author: Yoshiki Shibukawa +Author-email: yoshiki@shibu.jp +License: MIT +Description: + It parses image files' header and return image size. + + * PNG + * JPEG + * JPEG2000 + * GIF + + This is a pure Python library. + +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Multimedia :: Graphics diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..cdc76e9 --- /dev/null +++ b/README.rst @@ -0,0 +1,62 @@ +imagesize +============= + +.. image:: https://travis-ci.org/shibukawa/imagesize_py.svg?branch=master + :target: https://travis-ci.org/shibukawa/imagesize_py + +This module analyzes jpeg/jpeg2000/png/gif image header and return image size. + +.. code:: python + + import imagesize + + width, height = imagesize.get("test.png") + print(width, height) + +This module is a pure python module. + +API +----- + +* ``imagesize.get(filepath)`` + + Returns image size(width, height). + +Benchmark +------------ + +It just parses only header, ignores pixel data. So it is much faster than Pillow. + +.. list-table:: + :header-rows: 1 + + - * module + * result + - * imagesize(pure python) + * 1.077 seconds per 100000 times + - * Pillow + * 10.569 seconds per 100000 times + +I tested on MacBookPro(2014/Core i7) with 125kB PNG files. + +License +----------- + +MIT License + +Thanks +---------- + +I refers the following codes: + +* http://markasread.net/post/17551554979/get-image-size-info-using-pure-python-code +* http://stackoverflow.com/questions/8032642/how-to-obtain-image-size-using-standard-python-class-without-using-external-lib + +Thank you for feedbacks: + +* tk0miya (https://github.com/tk0miya) +* shimizukawa (https://github.com/shimizukawa) +* xantares (https://github.com/xantares) +* Ivan Zakharyaschev (https://github.com/imz) +* Jon Dufresne (https://github.com/jdufresne) +* Geoff Lankow (https://github.com/darktrojan) diff --git a/imagesize.egg-info/PKG-INFO b/imagesize.egg-info/PKG-INFO new file mode 100644 index 0000000..ed0d5b9 --- /dev/null +++ b/imagesize.egg-info/PKG-INFO @@ -0,0 +1,36 @@ +Metadata-Version: 1.1 +Name: imagesize +Version: 1.0.0 +Summary: Getting image size from png/jpeg/jpeg2000/gif file +Home-page: https://github.com/shibukawa/imagesize_py +Author: Yoshiki Shibukawa +Author-email: yoshiki@shibu.jp +License: MIT +Description: + It parses image files' header and return image size. + + * PNG + * JPEG + * JPEG2000 + * GIF + + This is a pure Python library. + +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Multimedia :: Graphics diff --git a/imagesize.egg-info/SOURCES.txt b/imagesize.egg-info/SOURCES.txt new file mode 100644 index 0000000..995be14 --- /dev/null +++ b/imagesize.egg-info/SOURCES.txt @@ -0,0 +1,18 @@ +LICENSE.rst +MANIFEST.in +README.rst +imagesize.py +setup.cfg +setup.py +imagesize.egg-info/PKG-INFO +imagesize.egg-info/SOURCES.txt +imagesize.egg-info/dependency_links.txt +imagesize.egg-info/top_level.txt +test/__init__.py +test/__init__.pyc +test/test_get.py +test/test_get.pyc +test/images/test.gif +test/images/test.jp2 +test/images/test.jpg +test/images/test.png \ No newline at end of file diff --git a/imagesize.egg-info/dependency_links.txt b/imagesize.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/imagesize.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/imagesize.egg-info/top_level.txt b/imagesize.egg-info/top_level.txt new file mode 100644 index 0000000..acdd70a --- /dev/null +++ b/imagesize.egg-info/top_level.txt @@ -0,0 +1 @@ +imagesize diff --git a/imagesize.py b/imagesize.py new file mode 100644 index 0000000..05c1bf3 --- /dev/null +++ b/imagesize.py @@ -0,0 +1,204 @@ +import struct + +_UNIT_KM = -3 +_UNIT_100M = -2 +_UNIT_10M = -1 +_UNIT_1M = 0 +_UNIT_10CM = 1 +_UNIT_CM = 2 +_UNIT_MM = 3 +_UNIT_0_1MM = 4 +_UNIT_0_01MM = 5 +_UNIT_UM = 6 +_UNIT_INCH = 6 + +def _convertToDPI(density, unit): + if unit == _UNIT_KM: + return int(density * 0.0000254 + 0.5) + elif unit == _UNIT_100M: + return int(density * 0.000254 + 0.5) + elif unit == _UNIT_10M: + return int(density * 0.00254 + 0.5) + elif unit == _UNIT_1M: + return int(density * 0.0254 + 0.5) + elif unit == _UNIT_10CM: + return int(density * 0.254 + 0.5) + elif unit == _UNIT_CM: + return int(density * 2.54 + 0.5) + elif unit == _UNIT_MM: + return int(density * 25.4 + 0.5) + elif unit == _UNIT_0_1MM: + return density * 254 + elif unit == _UNIT_0_01MM: + return density * 2540 + elif unit == _UNIT_UM: + return density * 25400 + return density + +def get(filepath): + """ + Return (width, height) for a given img file content + no requirements + """ + height = -1 + width = -1 + + with open(filepath, 'rb') as fhandle: + head = fhandle.read(24) + size = len(head) + # handle GIFs + if size >= 10 and head[:6] in (b'GIF87a', b'GIF89a'): + # Check to see if content_type is correct + try: + width, height = struct.unpack("= 24 and head.startswith(b'\211PNG\r\n\032\n') and head[12:16] == b'IHDR': + try: + width, height = struct.unpack(">LL", head[16:24]) + except struct.error: + raise ValueError("Invalid PNG file") + # Maybe this is for an older PNG version. + elif size >= 16 and head.startswith(b'\211PNG\r\n\032\n'): + # Check to see if we have the right content type + try: + width, height = struct.unpack(">LL", head[8:16]) + except struct.error: + raise ValueError("Invalid PNG file") + # handle JPEGs + elif size >= 2 and head.startswith(b'\377\330'): + try: + fhandle.seek(0) # Read 0xff next + size = 2 + ftype = 0 + while not 0xc0 <= ftype <= 0xcf or ftype in [0xc4, 0xc8, 0xcc]: + fhandle.seek(size, 1) + byte = fhandle.read(1) + while ord(byte) == 0xff: + byte = fhandle.read(1) + ftype = ord(byte) + size = struct.unpack('>H', fhandle.read(2))[0] - 2 + # We are at a SOFn block + fhandle.seek(1, 1) # Skip `precision' byte. + height, width = struct.unpack('>HH', fhandle.read(4)) + except struct.error: + raise ValueError("Invalid JPEG file") + # handle JPEG2000s + elif size >= 12 and head.startswith(b'\x00\x00\x00\x0cjP \r\n\x87\n'): + fhandle.seek(48) + try: + height, width = struct.unpack('>LL', fhandle.read(8)) + except struct.error: + raise ValueError("Invalid JPEG2000 file") + return width, height + +def getDPI(filepath): + """ + Return (width, height) for a given img file content + no requirements + """ + xDPI = -1 + yDPI = -1 + with open(filepath, 'rb') as fhandle: + head = fhandle.read(24) + size = len(head) + # handle GIFs + # GIFs doesn't have density + if size >= 10 and head[:6] in (b'GIF87a', b'GIF89a'): + pass + # see png edition spec bytes are below chunk length then and finally the + elif size >= 24 and head.startswith(b'\211PNG\r\n\032\n'): + chunkOffset = 8 + chunk = head[8:] + while True: + chunkType = chunk[4:8] + if chunkType == b'pHYs': + try: + xDensity, yDensity, unit = struct.unpack(">LLB", chunk[8:]) + except struct.error: + raise ValueError("Invalid PNG file") + if unit: + xDPI = _convertToDPI(xDensity, _UNIT_1M) + yDPI = _convertToDPI(yDensity, _UNIT_1M) + else: # no unit + xDPI = xDensity + yDPI = yDensity + break + elif chunkType == b'IDAT': + break + else: + try: + dataSize, = struct.unpack(">L", chunk[0:4]) + except struct.error: + raise ValueError("Invalid PNG file") + chunkOffset += dataSize + 12 + fhandle.seek(chunkOffset) + chunk = fhandle.read(17) + # handle JPEGs + elif size >= 2 and head.startswith(b'\377\330'): + try: + fhandle.seek(0) # Read 0xff next + size = 2 + ftype = 0 + while not 0xc0 <= ftype <= 0xcf: + if ftype == 0xe0: # APP0 marker + fhandle.seek(7, 1) + unit, xDensity, yDensity = struct.unpack(">BHH", fhandle.read(5)) + if unit == 1 or unit == 0: + xDPI = xDensity + yDPI = yDensity + elif unit == 2: + xDPI = _convertToDPI(xDensity, _UNIT_CM) + yDPI = _convertToDPI(yDensity, _UNIT_CM) + break + fhandle.seek(size, 1) + byte = fhandle.read(1) + while ord(byte) == 0xff: + byte = fhandle.read(1) + ftype = ord(byte) + size = struct.unpack('>H', fhandle.read(2))[0] - 2 + except struct.error: + raise ValueError("Invalid JPEG file") + # handle JPEG2000s + elif size >= 12 and head.startswith(b'\x00\x00\x00\x0cjP \r\n\x87\n'): + fhandle.seek(32) + # skip JP2 image header box + headerSize = struct.unpack('>L', fhandle.read(4))[0] - 8 + fhandle.seek(4, 1) + foundResBox = False + try: + while headerSize > 0: + print("headerSize", headerSize) + boxHeader = fhandle.read(8) + boxType = boxHeader[4:] + print(boxType) + if boxType == 'res ': # find resolution super box + foundResBox = True + headerSize -= 8 + print("found res super box") + break + print("@1", boxHeader) + boxSize, = struct.unpack('>L', boxHeader[:4]) + print("boxSize", boxSize) + fhandle.seek(boxSize - 8, 1) + headerSize -= boxSize + if foundResBox: + while headerSize > 0: + boxHeader = fhandle.read(8) + boxType = boxHeader[4:] + print(boxType) + if boxType == 'resd': # Display resolution box + print("@2") + yDensity, xDensity, yUnit, xUnit = struct.unpack(">HHBB", fhandle.read(10)) + xDPI = _convertToDPI(xDensity, xUnit) + yDPI = _convertToDPI(yDensity, yUnit) + break + boxSize, = struct.unpack('>L', boxHeader[:4]) + print("boxSize", boxSize) + fhandle.seek(boxSize - 8, 1) + headerSize -= boxSize + except struct.error as e: + print(e) + raise ValueError("Invalid JPEG2000 file") + return xDPI, yDPI diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..25f53e6 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,11 @@ +[bdist_wheel] +universal = 1 + +[metadata] +license_file = LICENSE.rst + +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..f9f4816 --- /dev/null +++ b/setup.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +from setuptools import setup +#from distutils.core import setup + +setup(name='imagesize', + version='1.0.0', + description='Getting image size from png/jpeg/jpeg2000/gif file', + long_description=''' +It parses image files' header and return image size. + +* PNG +* JPEG +* JPEG2000 +* GIF + +This is a pure Python library. +''', + author='Yoshiki Shibukawa', + author_email='yoshiki@shibu.jp', + url='https://github.com/shibukawa/imagesize_py', + license="MIT", + py_modules=['imagesize'], + test_suite='test', + classifiers = [ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', + 'Topic :: Multimedia :: Graphics' + ] +) diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/__init__.py diff --git a/test/__init__.pyc b/test/__init__.pyc new file mode 100644 index 0000000..7b6453a Binary files /dev/null and b/test/__init__.pyc differ diff --git a/test/images/test.gif b/test/images/test.gif new file mode 100644 index 0000000..4a2e175 Binary files /dev/null and b/test/images/test.gif differ diff --git a/test/images/test.jp2 b/test/images/test.jp2 new file mode 100644 index 0000000..58d528d Binary files /dev/null and b/test/images/test.jp2 differ diff --git a/test/images/test.jpg b/test/images/test.jpg new file mode 100644 index 0000000..b621a05 Binary files /dev/null and b/test/images/test.jpg differ diff --git a/test/images/test.png b/test/images/test.png new file mode 100644 index 0000000..cd4a46c Binary files /dev/null and b/test/images/test.png differ diff --git a/test/test_get.py b/test/test_get.py new file mode 100644 index 0000000..dfebeff --- /dev/null +++ b/test/test_get.py @@ -0,0 +1,27 @@ +import unittest +import os, sys +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +import imagesize + +imagedir = os.path.join(os.path.dirname(__file__), "images") + +class GetTest(unittest.TestCase): + def test_load_png(self): + width, height = imagesize.get(os.path.join(imagedir, "test.png")) + self.assertEqual(width, 802) + self.assertEqual(height, 670) + + def test_load_jpeg(self): + width, height = imagesize.get(os.path.join(imagedir, "test.jpg")) + self.assertEqual(width, 802) + self.assertEqual(height, 670) + + def test_load_jpeg2000(self): + width, height = imagesize.get(os.path.join(imagedir, "test.jp2")) + self.assertEqual(width, 802) + self.assertEqual(height, 670) + + def test_load_gif(self): + width, height = imagesize.get(os.path.join(imagedir, "test.gif")) + self.assertEqual(width, 802) + self.assertEqual(height, 670) diff --git a/test/test_get.pyc b/test/test_get.pyc new file mode 100644 index 0000000..2c2deff Binary files /dev/null and b/test/test_get.pyc differ