Discussion:
[Libjpeg-turbo-users] libjpeg in Delphi
David Brenner
2016-03-10 05:47:14 UTC
Permalink
Hi,

It's about this: https://github.com/libjpeg-turbo/libjpeg-turbo/issues/65
Since it was closed, I will try to continue the discussion here.

First, thank you dcommander for your tip. It worked.
Now I'm using this:

var
prow: Prgbarray;
RowD: Prgbarray;

............

jpeg.out_color_space := JCS_EXT_BGR;

............

// reading image
jpeg_start_decompress(@jpeg);

// allocate row
GetMem(prow, jpeg.output_width * 3);

inherited SetSize(jpeg.output_width, jpeg.output_height);
inherited PixelFormat := pf24bit;
for y := 0 to jpeg.output_height - 1 do
begin
// reading row
rowD := scanline[y];
jpeg_read_scanlines(@jpeg, @rowD, 1);
end;

It's twice as fast :)

2 questions:

1. Is it safe to use it like this?
2. It's still kind of slow (15..20 ms). Is it possible to transfer the
entire data in one step instead of one row st a time?

Thank you.

Best regards,
David
DRC
2016-03-10 08:19:21 UTC
Permalink
You can still add comments on GitHub even if the issue is closed. When I close an issue, it means that it has been resolved, but please feel
free to add additional information or questions after it is closed. If it turns out that it hasn't been resolved, then I will re-open it.

To answer your question, yes, you can read multiple scanlines. Again, I'm not a Delphi programmer, but to see the equivalent C code, I refer you to the tjDecompress2() function in turbojpeg.c.
Post by David Brenner
Hi,
It's about this: https://github.com/libjpeg-turbo/libjpeg-turbo/issues/65
Since it was closed, I will try to continue the discussion here.
First, thank you dcommander for your tip. It worked.
var
prow: Prgbarray;
RowD: Prgbarray;
............
jpeg.out_color_space := JCS_EXT_BGR;
............
// reading image
// allocate row
GetMem(prow, jpeg.output_width * 3);
inherited SetSize(jpeg.output_width, jpeg.output_height);
inherited PixelFormat := pf24bit;
for y := 0 to jpeg.output_height - 1 do
begin
// reading row
rowD := scanline[y];
end;
It's twice as fast :)
1. Is it safe to use it like this?
2. It's still kind of slow (15..20 ms). Is it possible to transfer the
entire data in one step instead of one row st a time?
Thank you.
Best regards,
David
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785111&iu=/4140
_______________________________________________
Libjpeg-turbo-users mailing list
https://lists.sourceforge.net/lists/listinfo/libjpeg-turbo-users
David Brenner
2016-03-11 06:15:36 UTC
Permalink
Thank you, I'll have a look.
The problem is TBitmap has also its scanlines in reversed order (not just
BGR instead of RGB).
Read here: http://edn.embarcadero.com/article/29173
That function has any "switch" for reversing the order of scanlines?
DRC
2016-03-11 15:09:51 UTC
Permalink
Again, I'm not a Delphi programmer, but the C version of the function
(jpeg_read_scanlines()) takes an array of pointers as the second
argument. Each pointer in this array points to a different scanline
("row") in the output image, so this allows you to control the mapping
between rows in the input (JPEG) image and rows in the output
(uncompressed) image. To do bottom-up decompression, you would just
reverse the order of row pointers in the array.
Post by David Brenner
Thank you, I'll have a look.
The problem is TBitmap has also its scanlines in reversed order (not just
BGR instead of RGB).
Read here: http://edn.embarcadero.com/article/29173
That function has any "switch" for reversing the order of scanlines?
David Brenner
2016-03-11 16:38:25 UTC
Permalink
Yes, I can do that.
But it won't improve the overall speed.
The point is to make the function read all the scanlines in one shot (or
better, to give the memory address where they are stored one after another)
and to be able to copy te entire result directly into the bitmap. Otherwise
it won't be much different from what is doing right now.

But I think it's not possible in the current version + it will speed it up
only by a few percents.

Thanks anyway.
DRC
2016-03-11 16:55:34 UTC
Permalink
The scanline order only comes into play when doing color conversion (the
final step in the JPEG decompression process.) Since the color
conversion routines only operate on one scanline at a time anyhow, there
is no performance difference between passing the scanlines to
jpeg_read_scanlines() in forward or reverse order. And actually, in my
testing, there is very little difference (a couple of percent at most)
between requesting that jpeg_read_scanlines() read multiple scanlines or
just one scanline. Either way, the underlying library caches "MCU rows"
(blocks of {width} x 8 or {width} x 16), and jpeg_read_scanlines() will
either populate that cache (if a new MCU row is being accessed), or it
will pull from the existing cache (if the same MCU row is being
accessed.) Like I said, refer to the tjDecompress2() function in the
TurboJPEG API. It does literally everything you are trying to do,
except in C and not in Delphi.
Post by David Brenner
Yes, I can do that.
But it won't improve the overall speed.
The point is to make the function read all the scanlines in one shot (or
better, to give the memory address where they are stored one after another)
and to be able to copy te entire result directly into the bitmap. Otherwise
it won't be much different from what is doing right now.
But I think it's not possible in the current version + it will speed it up
only by a few percents.
Thanks anyway.
Loading...