0

I am wondering if there is a software library that enables opening a jpeg and converting a subset of it to an uncompressed array (such as Pillow). This would be in contrast to the more usual method which is to open the file, convert it fully to a bit array, then take a subset of the bit array.

In my case the subset that I have in mind is the upper left corner. The files decompress to 2544 × 4200 pixels, but I am only interested in the top left 150 x 900 pixels.

The background is below:

I am hopeful that the JPEG format is a string of compressed subpanels and an algorithm could stop when it had processed enough subpanels to fulfill the required subset of the image.

I have been searching for a while but have not found any mention of such an algorithm which, admittedly, is a special case.

Background

I use pyzbar to capture a barcode from the top left corner of a JPEG image as produced a high-speed scanner. Generally this required about 250 msecs per image. The actual Pyzbar time is about 2.5 msecs while the other 99% of the time is spent reading the image from a file, having it decompressed using Pillow, extracting the upper left corner.

The non-profit where I do this work as a volunteer cannot really afford to replace the $25K scanner and the channel that this clunker has is the overall bottleneck. Telling the scanner to send uncompressed images would slow the whole process down by at least 90%

WesR
  • 1,292
  • 1
  • 18
  • 30
  • What is the problem with Pillow? – mkrieger1 Jan 22 '20 at 21:01
  • Jpeg data is stored as 8x8 blocks. If you can find the equivalent of `jpegtran -crop`, you might be able to throw away enough of them to get your ROI without having to decode the data. Very interesting problem. – jamieguinan Jan 22 '20 at 22:35
  • @mkrieger1 Before you can crop an image in Pillow you have to have decompressed it. Decompression is 99% of the elapsed time in this process. – WesR Jan 23 '20 at 22:57
  • `vips` can do that - see John's excellent answer here https://stackoverflow.com/a/48376269/2836621 – Mark Setchell Feb 04 '20 at 10:41

1 Answers1

0

I don't know of an existing library that can do this, but it is possible to modify jpegtran.c and jdtrans.c from the IJG C library to only read as many MCU rows as necessary when cropping, and in your specific case the decode time should be reduced by ~75% (900 / 4200 lines).

Since you are using Python, you could obtain a suitably cropped jpeg with:

os.popen("jpegtran -crop 152x904 %s" % inputfile).read()

This assumes the input jpeg is not progressive.

jamieguinan
  • 1,640
  • 1
  • 10
  • 14
  • thanks. This is beyond my capability for now. I might come back to it if I decide to take up C programming, which I did last in the mid-80s. I'll keep it on file in case I do. – WesR Jan 23 '20 at 23:02