PyTurboJPEG 1.7.7__tar.gz → 1.8.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/LICENSE +1 -1
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/PKG-INFO +28 -1
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/PyTurboJPEG.egg-info/PKG-INFO +28 -1
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/README.md +27 -0
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/setup.py +1 -1
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/turbojpeg.py +58 -22
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/PyTurboJPEG.egg-info/SOURCES.txt +0 -0
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/PyTurboJPEG.egg-info/dependency_links.txt +0 -0
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/PyTurboJPEG.egg-info/requires.txt +0 -0
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/PyTurboJPEG.egg-info/top_level.txt +0 -0
- {PyTurboJPEG-1.7.7 → PyTurboJPEG-1.8.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2018-
|
|
3
|
+
Copyright (c) 2018-2025 Lilo Huang <kuso.cc@gmail.com>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyTurboJPEG
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.2
|
|
4
4
|
Summary: A Python wrapper of libjpeg-turbo for decoding and encoding JPEG image.
|
|
5
5
|
Home-page: https://github.com/lilohuang/PyTurboJPEG
|
|
6
6
|
Author: Lilo Huang
|
|
@@ -108,6 +108,33 @@ in_file.close()
|
|
|
108
108
|
out_file = open('lossless_cropped_output.jpg', 'wb')
|
|
109
109
|
out_file.write(jpeg.crop(open('input.jpg', 'rb').read(), 8, 8, 320, 240))
|
|
110
110
|
out_file.close()
|
|
111
|
+
|
|
112
|
+
# in-place decoding input.jpg to BGR array
|
|
113
|
+
# here I use a 640x480 example (in practise, read the dimensions)
|
|
114
|
+
in_file = open('input.jpg', 'rb')
|
|
115
|
+
img_array = np.empty((640, 480, 3), dtype=np.uint8)
|
|
116
|
+
result = jpeg.decode(in_file.read(), dst=img_array)
|
|
117
|
+
in_file.close()
|
|
118
|
+
|
|
119
|
+
# return value is the img_array argument value
|
|
120
|
+
id(result) == id(img_array)
|
|
121
|
+
# True
|
|
122
|
+
|
|
123
|
+
# Optional: display the in-place array
|
|
124
|
+
# cv2.imshow('img_array', img_array)
|
|
125
|
+
# cv2.waitKey(0)
|
|
126
|
+
|
|
127
|
+
# in-place encoding with default settings.
|
|
128
|
+
buffer_size = jpeg.buffer_size(img_array)
|
|
129
|
+
dest_buf = bytearray(buffer_size)
|
|
130
|
+
result, n_byte = jpeg.encode(img_array, dst=dest_buf)
|
|
131
|
+
|
|
132
|
+
# return value is the dest_buf argument value
|
|
133
|
+
id(result) == id(dest_buf)
|
|
134
|
+
|
|
135
|
+
out_file = open('output.jpg', 'wb')
|
|
136
|
+
out_file.write(dest_buf[:n_byte])
|
|
137
|
+
out_file.close()
|
|
111
138
|
```
|
|
112
139
|
|
|
113
140
|
```python
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyTurboJPEG
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.2
|
|
4
4
|
Summary: A Python wrapper of libjpeg-turbo for decoding and encoding JPEG image.
|
|
5
5
|
Home-page: https://github.com/lilohuang/PyTurboJPEG
|
|
6
6
|
Author: Lilo Huang
|
|
@@ -108,6 +108,33 @@ in_file.close()
|
|
|
108
108
|
out_file = open('lossless_cropped_output.jpg', 'wb')
|
|
109
109
|
out_file.write(jpeg.crop(open('input.jpg', 'rb').read(), 8, 8, 320, 240))
|
|
110
110
|
out_file.close()
|
|
111
|
+
|
|
112
|
+
# in-place decoding input.jpg to BGR array
|
|
113
|
+
# here I use a 640x480 example (in practise, read the dimensions)
|
|
114
|
+
in_file = open('input.jpg', 'rb')
|
|
115
|
+
img_array = np.empty((640, 480, 3), dtype=np.uint8)
|
|
116
|
+
result = jpeg.decode(in_file.read(), dst=img_array)
|
|
117
|
+
in_file.close()
|
|
118
|
+
|
|
119
|
+
# return value is the img_array argument value
|
|
120
|
+
id(result) == id(img_array)
|
|
121
|
+
# True
|
|
122
|
+
|
|
123
|
+
# Optional: display the in-place array
|
|
124
|
+
# cv2.imshow('img_array', img_array)
|
|
125
|
+
# cv2.waitKey(0)
|
|
126
|
+
|
|
127
|
+
# in-place encoding with default settings.
|
|
128
|
+
buffer_size = jpeg.buffer_size(img_array)
|
|
129
|
+
dest_buf = bytearray(buffer_size)
|
|
130
|
+
result, n_byte = jpeg.encode(img_array, dst=dest_buf)
|
|
131
|
+
|
|
132
|
+
# return value is the dest_buf argument value
|
|
133
|
+
id(result) == id(dest_buf)
|
|
134
|
+
|
|
135
|
+
out_file = open('output.jpg', 'wb')
|
|
136
|
+
out_file.write(dest_buf[:n_byte])
|
|
137
|
+
out_file.close()
|
|
111
138
|
```
|
|
112
139
|
|
|
113
140
|
```python
|
|
@@ -96,6 +96,33 @@ in_file.close()
|
|
|
96
96
|
out_file = open('lossless_cropped_output.jpg', 'wb')
|
|
97
97
|
out_file.write(jpeg.crop(open('input.jpg', 'rb').read(), 8, 8, 320, 240))
|
|
98
98
|
out_file.close()
|
|
99
|
+
|
|
100
|
+
# in-place decoding input.jpg to BGR array
|
|
101
|
+
# here I use a 640x480 example (in practise, read the dimensions)
|
|
102
|
+
in_file = open('input.jpg', 'rb')
|
|
103
|
+
img_array = np.empty((640, 480, 3), dtype=np.uint8)
|
|
104
|
+
result = jpeg.decode(in_file.read(), dst=img_array)
|
|
105
|
+
in_file.close()
|
|
106
|
+
|
|
107
|
+
# return value is the img_array argument value
|
|
108
|
+
id(result) == id(img_array)
|
|
109
|
+
# True
|
|
110
|
+
|
|
111
|
+
# Optional: display the in-place array
|
|
112
|
+
# cv2.imshow('img_array', img_array)
|
|
113
|
+
# cv2.waitKey(0)
|
|
114
|
+
|
|
115
|
+
# in-place encoding with default settings.
|
|
116
|
+
buffer_size = jpeg.buffer_size(img_array)
|
|
117
|
+
dest_buf = bytearray(buffer_size)
|
|
118
|
+
result, n_byte = jpeg.encode(img_array, dst=dest_buf)
|
|
119
|
+
|
|
120
|
+
# return value is the dest_buf argument value
|
|
121
|
+
id(result) == id(dest_buf)
|
|
122
|
+
|
|
123
|
+
out_file = open('output.jpg', 'wb')
|
|
124
|
+
out_file.write(dest_buf[:n_byte])
|
|
125
|
+
out_file.close()
|
|
99
126
|
```
|
|
100
127
|
|
|
101
128
|
```python
|
|
@@ -2,7 +2,7 @@ import io
|
|
|
2
2
|
from setuptools import setup, find_packages
|
|
3
3
|
setup(
|
|
4
4
|
name='PyTurboJPEG',
|
|
5
|
-
version='1.
|
|
5
|
+
version='1.8.2',
|
|
6
6
|
description='A Python wrapper of libjpeg-turbo for decoding and encoding JPEG image.',
|
|
7
7
|
author='Lilo Huang',
|
|
8
8
|
author_email='kuso.cc@gmail.com',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# PyTurboJPEG - A Python wrapper of libjpeg-turbo for decoding and encoding JPEG image.
|
|
4
4
|
#
|
|
5
|
-
# Copyright (c) 2018-
|
|
5
|
+
# Copyright (c) 2018-2025, Lilo Huang. All rights reserved.
|
|
6
6
|
#
|
|
7
7
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
8
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
# SOFTWARE.
|
|
24
24
|
|
|
25
25
|
__author__ = 'Lilo Huang <kuso.cc@gmail.com>'
|
|
26
|
-
__version__ = '1.
|
|
26
|
+
__version__ = '1.8.2'
|
|
27
27
|
|
|
28
28
|
from ctypes import *
|
|
29
29
|
from ctypes.util import find_library
|
|
@@ -408,7 +408,7 @@ class TurboJPEG(object):
|
|
|
408
408
|
finally:
|
|
409
409
|
self.__destroy(handle)
|
|
410
410
|
|
|
411
|
-
def decode(self, jpeg_buf, pixel_format=TJPF_BGR, scaling_factor=None, flags=0):
|
|
411
|
+
def decode(self, jpeg_buf, pixel_format=TJPF_BGR, scaling_factor=None, flags=0, dst=None):
|
|
412
412
|
"""decodes JPEG memory buffer to numpy array."""
|
|
413
413
|
handle = self.__init_decompress()
|
|
414
414
|
try:
|
|
@@ -416,9 +416,14 @@ class TurboJPEG(object):
|
|
|
416
416
|
src_addr = self.__getaddr(jpeg_array)
|
|
417
417
|
scaled_width, scaled_height, _, _ = \
|
|
418
418
|
self.__get_header_and_dimensions(handle, jpeg_array.size, src_addr, scaling_factor)
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
dtype
|
|
419
|
+
if ((type(dst) == np.ndarray) and
|
|
420
|
+
(dst.shape == (scaled_height, scaled_width, tjPixelSize[pixel_format])) and
|
|
421
|
+
(dst.dtype == np.uint8)):
|
|
422
|
+
img_array = dst
|
|
423
|
+
else:
|
|
424
|
+
img_array = np.empty(
|
|
425
|
+
[scaled_height, scaled_width, tjPixelSize[pixel_format]],
|
|
426
|
+
dtype=np.uint8)
|
|
422
427
|
dest_addr = self.__getaddr(img_array)
|
|
423
428
|
status = self.__decompress(
|
|
424
429
|
handle, src_addr, jpeg_array.size, dest_addr, scaled_width,
|
|
@@ -486,13 +491,22 @@ class TurboJPEG(object):
|
|
|
486
491
|
finally:
|
|
487
492
|
self.__destroy(handle)
|
|
488
493
|
|
|
489
|
-
def encode(self, img_array, quality=85, pixel_format=TJPF_BGR, jpeg_subsample=TJSAMP_422, flags=0):
|
|
494
|
+
def encode(self, img_array, quality=85, pixel_format=TJPF_BGR, jpeg_subsample=TJSAMP_422, flags=0, dst=None):
|
|
490
495
|
"""encodes numpy array to JPEG memory buffer."""
|
|
491
496
|
handle = self.__init_compress()
|
|
492
497
|
try:
|
|
493
|
-
jpeg_buf = c_void_p()
|
|
494
|
-
jpeg_size = c_ulong()
|
|
495
498
|
img_array = np.ascontiguousarray(img_array)
|
|
499
|
+
if dst is not None and not self.__is_buffer(dst):
|
|
500
|
+
raise TypeError('\'dst\' argument must support buffer protocol')
|
|
501
|
+
if (dst is not None and
|
|
502
|
+
(len(dst) >= self.buffer_size(img_array, jpeg_subsample))):
|
|
503
|
+
dst_array = np.frombuffer(dst, dtype=np.uint8)
|
|
504
|
+
jpeg_buf = dst_array.ctypes.data_as(c_void_p)
|
|
505
|
+
jpeg_size = c_ulong(len(dst))
|
|
506
|
+
else:
|
|
507
|
+
dst_array = None
|
|
508
|
+
jpeg_buf = c_void_p()
|
|
509
|
+
jpeg_size = c_ulong()
|
|
496
510
|
height, width = img_array.shape[:2]
|
|
497
511
|
channel = tjPixelSize[pixel_format]
|
|
498
512
|
if channel > 1 and (len(img_array.shape) < 3 or img_array.shape[2] != channel):
|
|
@@ -503,10 +517,12 @@ class TurboJPEG(object):
|
|
|
503
517
|
byref(jpeg_buf), byref(jpeg_size), jpeg_subsample, quality, flags)
|
|
504
518
|
if status != 0:
|
|
505
519
|
self.__report_error(handle)
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
520
|
+
if dst_array is None or jpeg_buf.value != dst_array.ctypes.data:
|
|
521
|
+
result = self.__copy_from_buffer(jpeg_buf.value, jpeg_size.value)
|
|
522
|
+
self.__free(jpeg_buf)
|
|
523
|
+
else:
|
|
524
|
+
result = dst
|
|
525
|
+
return result if dst is None else (result, jpeg_size.value)
|
|
510
526
|
finally:
|
|
511
527
|
self.__destroy(handle)
|
|
512
528
|
|
|
@@ -539,7 +555,7 @@ class TurboJPEG(object):
|
|
|
539
555
|
scaled_width, scaled_height, jpeg_subsample, _ = self.__get_header_and_dimensions(
|
|
540
556
|
handle, jpeg_array.size, src_addr, scaling_factor)
|
|
541
557
|
buffer_YUV_size = self.__buffer_size_YUV2(
|
|
542
|
-
|
|
558
|
+
scaled_width, 4, scaled_height, jpeg_subsample)
|
|
543
559
|
img_array = np.empty([buffer_YUV_size])
|
|
544
560
|
dest_addr = self.__getaddr(img_array)
|
|
545
561
|
status = self.__decompressToYUV2(
|
|
@@ -680,6 +696,12 @@ class TurboJPEG(object):
|
|
|
680
696
|
finally:
|
|
681
697
|
self.__destroy(handle)
|
|
682
698
|
|
|
699
|
+
def buffer_size(self, img_array, jpeg_subsample=TJSAMP_422):
|
|
700
|
+
"""Get maximum number of bytes of compressed jpeg data"""
|
|
701
|
+
img_array = np.ascontiguousarray(img_array)
|
|
702
|
+
height, width = img_array.shape[:2]
|
|
703
|
+
return self.__buffer_size(width, height, jpeg_subsample)
|
|
704
|
+
|
|
683
705
|
def __do_transform(self, handle, src_buf, src_size, number_of_transforms, transforms):
|
|
684
706
|
"""Do transform.
|
|
685
707
|
|
|
@@ -774,16 +796,22 @@ class TurboJPEG(object):
|
|
|
774
796
|
return scaled_width, scaled_height, jpeg_subsample, jpeg_colorspace
|
|
775
797
|
|
|
776
798
|
def __axis_to_image_boundaries(self, a, b, img_boundary, preserve, mcuBlock):
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
a
|
|
799
|
+
if preserve:
|
|
800
|
+
original_a = a
|
|
801
|
+
a = int(math.ceil(float(original_a) / mcuBlock) * mcuBlock)
|
|
802
|
+
b -= (a - original_a)
|
|
803
|
+
if (a + b) > img_boundary:
|
|
804
|
+
b = img_boundary - a
|
|
781
805
|
else:
|
|
782
|
-
|
|
783
|
-
|
|
806
|
+
img_b = img_boundary - (img_boundary % mcuBlock)
|
|
807
|
+
delta_a = a % mcuBlock
|
|
808
|
+
if a > img_b:
|
|
809
|
+
a = img_b
|
|
810
|
+
else:
|
|
811
|
+
a = a - delta_a
|
|
784
812
|
b = b + delta_a
|
|
785
|
-
|
|
786
|
-
|
|
813
|
+
if (a + b) > img_b:
|
|
814
|
+
b = img_b - a
|
|
787
815
|
return a, b
|
|
788
816
|
|
|
789
817
|
@staticmethod
|
|
@@ -974,6 +1002,14 @@ class TurboJPEG(object):
|
|
|
974
1002
|
"""returns the memory address for a given ndarray"""
|
|
975
1003
|
return cast(nda.__array_interface__['data'][0], POINTER(c_ubyte))
|
|
976
1004
|
|
|
1005
|
+
def __is_buffer(self, x):
|
|
1006
|
+
result = True
|
|
1007
|
+
try:
|
|
1008
|
+
memoryview(x)
|
|
1009
|
+
except Exception:
|
|
1010
|
+
result = False
|
|
1011
|
+
return result
|
|
1012
|
+
|
|
977
1013
|
@property
|
|
978
1014
|
def scaling_factors(self):
|
|
979
1015
|
return self.__scaling_factors
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|