Git Product home page Git Product logo

pyturbojpeg's Introduction

PyTurboJPEG

A Python wrapper of libjpeg-turbo for decoding and encoding JPEG image.

Prerequisites

Example

import cv2
from turbojpeg import TurboJPEG, TJPF_GRAY, TJSAMP_GRAY, TJFLAG_PROGRESSIVE, TJFLAG_FASTUPSAMPLE, TJFLAG_FASTDCT

# specifying library path explicitly
# jpeg = TurboJPEG(r'D:\turbojpeg.dll')
# jpeg = TurboJPEG('/usr/lib64/libturbojpeg.so')
# jpeg = TurboJPEG('/usr/local/lib/libturbojpeg.dylib')

# using default library installation
jpeg = TurboJPEG()

# decoding input.jpg to BGR array
in_file = open('input.jpg', 'rb')
bgr_array = jpeg.decode(in_file.read())
in_file.close()
cv2.imshow('bgr_array', bgr_array)
cv2.waitKey(0)

# decoding input.jpg to BGR array with fast upsample and fast DCT. (i.e. fastest speed but lower accuracy)
in_file = open('input.jpg', 'rb')
bgr_array = jpeg.decode(in_file.read(), flags=TJFLAG_FASTUPSAMPLE|TJFLAG_FASTDCT)
in_file.close()
cv2.imshow('bgr_array', bgr_array)
cv2.waitKey(0)

# direct rescaling 1/2 while decoding input.jpg to BGR array
in_file = open('input.jpg', 'rb')
bgr_array_half = jpeg.decode(in_file.read(), scaling_factor=(1, 2))
in_file.close()
cv2.imshow('bgr_array_half', bgr_array_half)
cv2.waitKey(0)

# getting possible scaling factors for direct rescaling
scaling_factors = jpeg.scaling_factors

# decoding JPEG image properties
in_file = open('input.jpg', 'rb')
width, height, jpeg_subsample, jpeg_colorspace = jpeg.decode_header(in_file.read())
in_file.close()

# decoding input.jpg to YUV array
in_file = open('input.jpg', 'rb')
buffer_array, plane_sizes = jpeg.decode_to_yuv(in_file.read())
in_file.close()

# decoding input.jpg to YUV planes
in_file = open('input.jpg', 'rb')
planes = jpeg.decode_to_yuv_planes(in_file.read())
in_file.close()

# encoding BGR array to output.jpg with default settings.
out_file = open('output.jpg', 'wb')
out_file.write(jpeg.encode(bgr_array))
out_file.close()

# encoding BGR array to output.jpg with TJSAMP_GRAY subsample.
out_file = open('output_gray.jpg', 'wb')
out_file.write(jpeg.encode(bgr_array, jpeg_subsample=TJSAMP_GRAY))
out_file.close()

# encoding BGR array to output.jpg with quality level 50. 
out_file = open('output_quality_50.jpg', 'wb')
out_file.write(jpeg.encode(bgr_array, quality=50))
out_file.close()

# encoding BGR array to output.jpg with quality level 100 and progressive entropy coding.
out_file = open('output_quality_100_progressive.jpg', 'wb')
out_file.write(jpeg.encode(bgr_array, quality=100, flags=TJFLAG_PROGRESSIVE))
out_file.close()

# decoding input.jpg to grayscale array
in_file = open('input.jpg', 'rb')
gray_array = jpeg.decode(in_file.read(), pixel_format=TJPF_GRAY)
in_file.close()
cv2.imshow('gray_array', gray_array)
cv2.waitKey(0)

# scale with quality but leaves out the color conversion step
in_file = open('input.jpg', 'rb')
out_file = open('scaled_output.jpg', 'wb')
out_file.write(jpeg.scale_with_quality(in_file.read(), scaling_factor=(1, 4), quality=70))
out_file.close()
in_file.close()

# lossless crop image
out_file = open('lossless_cropped_output.jpg', 'wb')
out_file.write(jpeg.crop(open('input.jpg', 'rb').read(), 8, 8, 320, 240))
out_file.close()
# using PyTurboJPEG with ExifRead to transpose an image if the image has an EXIF Orientation tag.
#
# pip install PyTurboJPEG -U
# pip install exifread -U

import cv2
import numpy as np
import exifread
from turbojpeg import TurboJPEG

def transposeImage(image, orientation):
    """See Orientation in https://www.exif.org/Exif2-2.PDF for details."""
    if orientation == None: return image
    val = orientation.values[0]
    if val == 1: return image
    elif val == 2: return np.fliplr(image)
    elif val == 3: return np.rot90(image, 2)
    elif val == 4: return np.flipud(image)
    elif val == 5: return np.rot90(np.flipud(image), -1)
    elif val == 6: return np.rot90(image, -1)
    elif val == 7: return np.rot90(np.flipud(image))
    elif val == 8: return np.rot90(image)

# using default library installation
turbo_jpeg = TurboJPEG()
# open jpeg file
in_file = open('foobar.jpg', 'rb')
# parse orientation
orientation = exifread.process_file(in_file).get('Image Orientation', None)
# seek file position back to 0 before decoding JPEG image
in_file.seek(0)
# start to decode the JPEG file
image = turbo_jpeg.decode(in_file.read())
# transpose image based on EXIF Orientation tag
transposed_image = transposeImage(image, orientation)
# close the file since it's no longer needed.
in_file.close()

cv2.imshow('transposed_image', transposed_image)
cv2.waitKey(0)

Installation

macOS

Windows

Linux

Benchmark

macOS

  • macOS Sierra 10.12.6
  • Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz
  • opencv-python 3.4.0.12 (pre-built)
  • turbo-jpeg 1.5.3 (pre-built)
Function Wall-clock time
cv2.imdecode()       0.528 sec  
TurboJPEG.decode() 0.191 sec
cv2.imencode()       0.875 sec  
TurboJPEG.encode() 0.176 sec

Windows

  • Windows 7 Ultimate 64-bit
  • Intel(R) Xeon(R) E3-1276 v3 CPU @ 3.60 GHz
  • opencv-python 3.4.0.12 (pre-built)
  • turbo-jpeg 1.5.3 (pre-built)
Function Wall-clock time
cv2.imdecode()       0.358 sec  
TurboJPEG.decode() 0.135 sec
cv2.imencode()       0.581 sec  
TurboJPEG.encode() 0.140 sec

pyturbojpeg's People

Contributors

akojo avatar antlarr avatar arizuu avatar dandedrick avatar erikogabrielsson avatar fmorillo avatar lilohuang avatar marcoffee avatar sapjunior avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyturbojpeg's Issues

encoding a grayscale image

Hi and thank you for your work on this great package.

I'm trying to save a simple 2D numpy array into a grayscale image, using this test code:

import numpy as np

from turbojpeg import TJPF_GRAY, TurboJPEG

jpeg = TurboJPEG()

rng = np.random.default_rng()
image = rng.integers(low=0, high=255, dtype=np.uint8, size=(3008, 4112))

with open("test.jpg", "wb") as output_jpeg_file:
    output_jpeg_file.write(jpeg.encode(img_array=image, pixel_format=TJPF_GRAY))

and what I get is the following error (obviously, because the input array has only 2 dimensions):

    height, width, _ = img_array.shape
ValueError: not enough values to unpack (expected 3, got 2)

I would expect this code to work, since if I pass pixel_format=TJPF_GRAY a 2D array should suffice to give all the necessary data to the encoder. Even if I try to augment the dimensions yielding three identical channels (using np.dstack), I get a OSError: Unsupported color conversion request error on the encode command.

What am I doing wrong? What can be done to obtain a grayscale JPEG?

About Benchmark Details

hi, how about benchmark details? such as jpeg image information, cv2 build information? I wonder the speed difference between when cv2 built with libjpegturbo.so and PyTurboJPEG

Not working on mac m2 with python3.7

I did brew install jpeg-turbo

And when I try to do

from turbojpeg import TurboJPEG
jpeg = TurboJPEG()

I get the following error

OSError: dlopen(/opt/homebrew/opt/jpeg-turbo/lib/libturbojpeg.dylib, 0x0006): tried: '/opt/homebrew/opt/jpeg-turbo/lib/libturbojpeg.dylib' (mach-o file, but is an incompatible architecture (have (arm64), need (x86_64))), '/opt/homebrew/Cellar/jpeg-turbo/2.1.4/lib/libturbojpeg.0.2.0.dylib' (mach-o file, but is an incompatible architecture (have (arm64), need (x86_64)))

I think this is because I used x86_64 for python installation. Any way to get around this problem? It works on my default python3.9 which came with the mac.

Lossless drop

Hi,

any chance you could add lossless drop?

https://github.com/libjpeg-turbo/libjpeg-turbo/blob/master/transupp.h

  • A lossless drop option is also provided, which allows another JPEG image to
  • be inserted ("dropped") into the source image data at a given position,
  • replacing the existing image data at that position. Both the source image
  • and the drop image must have the same subsampling level. It is best if they
  • also have the same quantization (quality.) Otherwise, the quantization of
  • the output image will be adapted to accommodate the higher of the source
  • image quality and the drop image quality. The trim option can be used with
  • the drop option to requantize the drop image to match the source image.

thank you,
Tomaz

lose rotation info using this repo

Now,i have a picture at
cong

when i use

img = cv2.imread("cong.jpg")

the picture is been correctly displayed.But when i use

in_file = open("cong.jpg", 'rb')
img = jpeg.decode(in_file.read())
in_file.close()

the picture loses its rotation info which leads to wrong display.
You can try and hope that you can fix this bug.

Unable to Identify TurboJPEG Class

Hi @lilohuang, I've pip-installed TurboJPEG, numpy and PyTurboJPEG, and yet when I ran the sample code provided in the readme file, python keeps returning error message saying that TurboJPEG() can't be found. I'm not sure if it's due to my lack of knowledge of python or maybe because of certain environment variables, but i do have turbojpeg64/bin/ (where turbojpeg.dll is) path stored in the path environment variable in my Windows machine. Am I missing something? I'm running Windows 11 with Python 3.11, MS VC++ 2015-2022 Redist and VS Code

I've done research and somehow couldn't find anything that helps with resolving this issue. I've also attempted to use turbojpeg-gcc64 and replaced the previous turbojpeg64\bin path environment to gcc64\bin one. Yet, issue persists.

I've also tried to implement and use my own custom class, or used a different module's class. I don't have any problem with this one. I'm thinking maybe because I'm using Python 3.11? I have yet to test this out though.

PyTurboJPEG not working with latest (2.0.4) release of libturbo-jpeg

The error that I get is:

/opt/libjpeg-turbo/lib64/libjpeg.so: undefined symbol: tjInitDecompress

How to reproduce:
Download the .deb for 2.0.4 from https://sourceforge.net/projects/libjpeg-turbo/ and install using dpkg
Then, from python

>>> from turbojpeg import TurboJPEG, TJPF_GRAY, TJSAMP_GRAY
>>> jpeg = TurboJPEG("/opt/libjpeg-turbo/lib64/libjpeg.so")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/test/.local/lib/python2.7/site-packages/turbojpeg.py", line 98, in __init__
    self.__init_decompress = turbo_jpeg.tjInitDecompress
  File "/usr/lib/python2.7/ctypes/__init__.py", line 375, in __getattr__
    func = self.__getitem__(name)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 380, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /opt/libjpeg-turbo/lib64/libjpeg.so: undefined symbol: tjInitDecompress

I checked and indeed the symbol tjInitDecompress isn't defined in the new .so file.

Version 2.0.3 didn't have this problem (the symbol is defined in the .so for 2.0.3)

[Windows 10] Unable to locate turbojpeg library automatically

I am installing the package in Windows. Following the instruction, I did the following two steps:

  1. Installed the latest version of libjpeg-turbo (i.e. libjpeg-turbo-2.0.3-gcc.exe). After the installation, I saw it is installed in C:/libjpeg-turbo-gcc.
  2. execute $ pip install -U git+git://github.com/lilohuang/PyTurboJPEG.git

After the above installation steps, I encountered the following error when running the sample script:

>>> from turbojpeg import TurboJPEG
>>> x = TurboJPEG()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\u3509\Anaconda3\envs\realsense\lib\site-packages\turbojpeg.py", line 97, in __init__
    self.__find_turbojpeg() if lib_path is None else lib_path)
  File "C:\Users\u3509\Anaconda3\envs\realsense\lib\site-packages\turbojpeg.py", line 257, in __find_turbojpeg
    'Unable to locate turbojpeg library automatically. '
RuntimeError: Unable to locate turbojpeg library automatically. You may specify the turbojpeg library path manually.
e.g. jpeg = TurboJPEG(lib_path)

I noticed I may need to specify library path explicitly, but I can't find the target files (i.e. turbojpeg.dll, libturbojpeg.so, or libturbojpeg.so) in my libjpeg-turbo directory (i.e. C:/libjpeg-turbo-gcc)
Below is what I saw from C:\libjpeg-turbo-gcc\lib\

(base) PS C:\Users\u3509> ls C:\libjpeg-turbo-gcc\lib\                                                                  

    Directory: C:\libjpeg-turbo-gcc\lib


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       10/20/2019   8:55 PM                pkgconfig
-a----         9/5/2019   7:38 AM         772182 libjpeg.a
-a----         9/5/2019   7:35 AM          70746 libjpeg.dll.a
-a----         9/5/2019   7:36 AM         878050 libturbojpeg.a
-a----         9/5/2019   7:37 AM          52760 libturbojpeg.dll.a

Memory leak in PyTurboJPEG?

Hi,

There seems to be a case of unmanaged memory in PyTurboJPEG. Memory is allocated during the image decode process, but not deallocated later (at least not immediately), and the memory usage of the process keeps building up.

As an example, please consider the following code:

from turbojpeg import TurboJPEG, TJPF_GRAY, TJSAMP_GRAY
import psutil
import os
import time
jpeg = TurboJPEG("/usr/lib/x86_64-linux-gnu/libturbojpeg.so.0")
import numpy

i = 0
PROCESS = psutil.Process(os.getpid())

buf = None
with open('some_image.jpg', 'rb') as fin:
    buf = fin.read()
for i in range(100):
    print 'iteration', i
    img_array = jpeg.decode(buf)
    print img_array.shape
    print 'memory = ', PROCESS.memory_info().rss // 1024

The output of this program looks like this:

...
iteration 43
(2160, 4096, 3)
memory =  806464
iteration 44
(2160, 4096, 3)
memory =  832576
iteration 45
(2160, 4096, 3)
memory =  858472
iteration 46
(2160, 4096, 3)
memory =  884340
iteration 47
(2160, 4096, 3)
memory =  910188
iteration 48
(2160, 4096, 3)
memory =  936316
iteration 49
(2160, 4096, 3)
memory =  962216
iteration 50
...

The memory usage keeps building up till more than a GB. It sometimes goes back to a low value, but again the buildup happens.

The other popular turbojpeg python wrapper -- jpeg4py -- doesn't have this problem. However, I prefer using PyTurboJPEG because it offers a scaling factor in the decode function which speeds up things considerably for my use case. But the memory build up is causing problems as I have a tight memory budget.

What could be the reason and are there any known fixes/workarounds?

Problem with copynone using libjpeg-turbo 3.0.0

Hi,

I noticed that when using libjpeg-turbo 3.0.0 markers are removed regardless of copynone being set:

libjpeg-turbo 3.0.0:

turbo = TurboJPEG(r"C:\tools\libjpeg-turbo64-3.0.0\bin\turbojpeg.dll")
cropped = turbo.crop_multiple(tile_2, [(0, 0, 32, 32)], copynone=False)[0]
print(cropped[0:30])
>> b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x06\x04\x05\x06\x05'

libjpeg-turbo 2.1.*

turbo = TurboJPEG(r"C:\tools\libjpeg-turbo64\bin\turbojpeg.dll")
cropped = turbo.crop_multiple(tile_2, [(0, 0, 32, 32)], copynone=False)[0]
print(cropped[0:30])
>> b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xfe\x00)Hamama'

On 2.1.* I get the FF-FE comment marker followed by the comment, on 3.0.0 it is missing.

Setting copynone=True on 2.1.* produces the desired output (no comment marker). Also jpegtran in 3.0.0 seems to work with the different copy-switches.

Multiple transform operations and modification of dct coefficents during transform

Hi and thanks for your work,

I work with a file format converter for whole scan images (wsi), which are basically a large number of smaller images (tiles, for example 1024x1024 px) that tiled together form a large (10s of Gigapixels) image. For the conversion, I have to merge together jpeg images to a larger image (e.g. 4096x1024) and split that image into a tiles of wanted size (e.g. 4 tiles of 1024x1024). The crop function in PyTurboJPEG is very useful for this last step, however for this specific application there are 2 'issues' that could make it better:

  1. tjTransform can perform multiple transform operations on the same source image (documentation). In PyTurboJPEG, this can be accomplished by sending arrays of pointers of the dstBufs, dstSizes, and transforms parameters. Doing multiple transforms in the same call, instead of multiple calls with single transform, improves performance by only decompressing the source image once. For my specific application, this can lead to ~50% performance boost.
  2. tjTransform allows for the width and height of the crop operation to extend outside the source image. In my case, if the source image is smaller than the requested tile size it needs to be extended, and I use this feature to do so. The result is then a image where the extended part is grey (as the part is filled with dct coefficents of 0). The tjtransform struct allows a customfilter callback function to be used for modification of DCT coefficents after transformation (documentation). In order to get white (or black) background, I have therefor written a callback function that modifies the dct coefficents after transform.

I have solved these issues in a way that fits my need by sub-classing the TurboJPEG-class. If these issues something that is interesting to more users and thus something that relevant for inclusion in your library, I would be happy to work with you.

Best regards
Erik Gabrielsson

Encoding exception with Python 3

Hi @lilohuang,

I was using turboJPEG with python 2.7 and it was working fine. I was using
https://downloads.sourceforge.net/project/libjpeg-turbo/2.0.2/libjpeg-turbo-official_2.0.2_amd64.deb and your latest code repo.
But when i migrated to python 3.7, the same fucntions which was working before is creating some exceptions. Please see the exceptions stack trace below.

Traceback (most recent call last):
  File "/opt/code/faceid/utils.py", line 86, in convert_img_to_buffer
    jpg_as_text = turbo.encode(frame, quality=95)
  File "/usr/local/lib/python3.7/site-packages/turbojpeg.py", line 219, in encode
    self.__report_error(handle)
  File "/usr/local/lib/python3.7/site-packages/turbojpeg.py", line 235, in __report_error
    raise IOError(self.__get_error_string(handle))
OSError: tjCompress2(): Invalid argument

I am unable to understand what is the issue here. Can you please point me.

Thanks,
Srijith

support partial frame decoding

libjpeg-turbo supports partial decoding, but that isn't exposed yet in PyTurboJPEG. it would be great if the decode function supported x, y, desiredWidth, and desiredHeight much like the java API does.

Do not raise decoder warnings

Hey there,

I have another request: Some specific images yield warnings, which are currently handled as exceptions (see libjpeg-turbo/libjpeg-turbo#157 (comment) ).
For fixing that, I suggest the following:
Add tjGetErrorCode to the imports:

        self.__get_error_code = turbo_jpeg.tjGetErrorCode
        self.__get_error_code.argtypes = [
            c_void_p
        ]
        self.__get_error_code.restype = c_int

instead of immediately raising the IOError exception if the status is not 0, use that function to check if it's a warning:

import warnings
[...]
            err_code = self.__get_error_code(handle)
            if status != 0:
                if err_code == 0:
                    warnings.warn(self.__get_error_str().decode())
                else:
                    raise IOError(self.__get_error_str().decode(), err_code)

(unfortunately, I'm limited in what code I can commit as PR, so writing that stuff here, so you can do that)

Thanks!

Is there a way to decode only to DCT coefficients?

I admire the rich functionality of the project, but is there really no way to read JPG into DCT coefficients?
I train forgery detecting NN and it uses several DCT features. It would be great if I can use PyTurboJPEG for image loading right into them, bypassing decoding to YUV and making DCT again.

Feature Request: Decode header only

Hello,

I have a feature request: A method to decode the header only would be great :)

E.g.:

    def decode_header(self, jpeg_buf):
        """decode JPEG memory buffer header and return a tuple (width, height ."""
        handle = self.__init_decompress()
        try:
            if scaling_factor is not None and \
                scaling_factor not in self.__scaling_factors:
                raise ValueError('supported scaling factors are ' +
                    str(self.__scaling_factors))
            pixel_size = [3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4]
            width = c_int()
            height = c_int()
            jpeg_subsample = c_int()
            jpeg_colorspace = c_int()
            jpeg_array = np.frombuffer(jpeg_buf, dtype=np.uint8)
            src_addr = jpeg_array.ctypes.data_as(POINTER(c_ubyte))
            status = self.__decompress_header(
                handle, src_addr, jpeg_array.size, byref(width), byref(height),
                byref(jpeg_subsample), byref(jpeg_colorspace))
            if status != 0:
                raise IOError(self.__get_error_str().decode())
            return (width.value, height.value, jpeg_subsample.value, jpeg_colorspace.value)
        finally:
            self.__destroy(handle)

Thank you!

How to get encoded data without marker?

Hello! Thanks for offering this repository!
Due to my work, I need to get encoded data from BGR image without marker and then decode into BGR image. How can I realize it?

OSX Homebrew lib path for Apple M1

On Apple silicon, Homebrew installs under /opt/homebrew instead of /usr/local.
Consequently, brew install jpeg-turbo results in the lib path "/opt/homebrew/opt/jpeg-turbo/lib/libturbojpeg.dylib".
Would it please be possible to check for this path as well on OSX when calling the default constructor TurboJPEG()?
As of now the user has to dig into the brew install to figure out the right path to pass to the TurboJPEG constructor.

Pass icc_profile for picture's encode

Hello! Thanks for your lib, it's a very useful tool for fast work with JPEG format.
Can you please tell me how can i pass the color profile (like icc_profile in Pillow) for picture's encode? If this feature is not available, can it be added during the next release?

Cropped image is getting distorted

Hi,

I have cropped an image part from an open cv frame. Then i encode it , decode it and write it as a file gives a distorted image.

Encoding
---------
face_crop = frame[bbox[1]:bbox[3], bbox[0]:bbox[2], :]
jpg_as_text = turbo.encode(face_crop)
Decoding
------------
img_file = io.BytesIO(jpg_as_text)
face_crop_decoded = turbo.decode(img_file.read())

Now if i write face_crop_decoded using cv2.imwrite('face.jpg', face_crop_decoded) , distorted lines are coming , not the actual face.

But if i use original face_crop for cv2.imwrite , proper face is getting written. So encode-decode-write causing some issues. But the frame variable which is used in the first line is actually encoded-decoded, there i am able to encode and decode properly. But on face_crop encode-decode is not working. What would be the issue here ?

Thank You

lib paths missing on NetBSD

The current situation is that the pkgsrc package libjpeg-turbo-2.1.2 installs

-rw-r--r--  1 root  wheel  427360 Dec 25 16:28 /usr/pkg/lib/libturbojpeg.a
lrwxr-xr-x  1 root  wheel      17 Dec 25 16:31 /usr/pkg/lib/libturbojpeg.so -> libturbojpeg.so.0
lrwxr-xr-x  1 root  wheel      21 Dec 25 16:31 /usr/pkg/lib/libturbojpeg.so.0 -> libturbojpeg.so.0.2.0
-rwxr-xr-x  1 root  wheel  345916 Dec 25 16:25 /usr/pkg/lib/libturbojpeg.so.0.2.0

so it should be sufficient to copy the FreeBSD block with /usr/local changed to /usr/pkg.

`scale_with_quality()` returns empty data if decoding the image to be scaled triggers a warning.

I was debugging why my mjpg_streamer images wouldn't show in Home Assistant's preview cards. Turns out HA is using PyTurboJPEG to try to rescale down the source image to a better fit to the card size, but my camera is producing some flaky (m)jpeg output that triggers these warnings:

/srv/homeassistant/lib/python3.9/site-packages/turbojpeg.py:867: UserWarning: Corrupt JPEG data: 1 extraneous bytes before marker 0xd4

It turns out the return in this line needs to be removed:

if status != 0:
    self.__report_error(handle)
    return

__report_error() will already raise an exception when an actual error has occurred, so no return is necessary. When what we had was a warning only, the return will prevent the code from proceeding.

I tested this by modifying my own installation to remove the line and see that I now have this camera's preview in the HA card.

Code Cleanup

Hi there,

first, thanks for quickly adding the decode_header function! :)

Just a small note: The arguments pixel_format=TJPF_BGR, scaling_factor=None seem to be unused for the decode_header, so I guess they could be removed?

Best
Lukas

silent crash on wrong array shape

If I try to encode an image with missing components, the python interpreter silently exits with no message/exception.

See this example code:

from numpy import uint8, zeros
from turbojpeg import TJPF_RGB, TJSAMP_420, TurboJPEG

jpeg = TurboJPEG()

image = zeros((1024, 4096), dtype=uint8)

print("Entering store...")

with open("test.jpg", "wb") as f:
    jpeg_encoded = jpeg.encode(
        image,
        pixel_format=TJPF_RGB,
        quality=95,
        jpeg_subsample=TJSAMP_420,
    )
    f.write(jpeg_encoded)

print("Exiting store (this never gets printed)...")

Conversely, if I say image = zeros((1024, 4096, 3), dtype=uint8), the script completes normally.

Issue appears with both pyturbojpeg 1.6.3 and 1.6.4, on Windows 10x64.

I would expect to see an exception raised in this case.

Thank you for your work on this great wrapper library, and happy new year!

What image array format is accepted by encode()?

Hi,
I wish know in what image array format does the encode function accept? BGR of RGB?
I aim to use opencv to read a video frame and encode is with TurboJPEG.encode(). OpenCV gives me a BGR array. Should convert it to RGB or should I pass it to encode as it is?

Default library paths

Hey there,

still one more hint: I believe it's a cleaner interface if you'd use from ctypes.util import find_library like find_library("turbojpeg") to detect the path to the library instead of the hardcoded dictionary :) (I'm doing exactly that and pass the result to the constructor).

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.