8

I'm using PyGame to display images (photos). For larger image sizes the load and convert process is slow (eg. taking 2-3 seconds for an image of size 6000x4485). The actual code that's slow is:

image = pg.image.load(fname).convert()

Is there an alternative library or method that'll give better performance? My target platforms are windows7 and os x, and I'm ok with separate solutions for each (although a single solution would be better).

Parand
  • 102,950
  • 48
  • 151
  • 186
  • 4
    I don't think you can get much better performance. What's probably taking most of the time is loading and decoding the image. And that's C code (jpeglib). Keep in mind an image that size weighs at 77 Mb decompressed. Depending on the application, you can "cheat" by pre-loading in the background or something. – Gustavo Giráldez Jun 15 '11 at 03:05
  • I'm pretty sure the same image is displayed faster by both picasa and the built-in windows viewer. I'll see if I can time it. – Parand Jun 15 '11 at 17:57
  • 3
    Check http://stackoverflow.com/q/1594319/718209 . In particular they mention libjpeg-turbo which is a drop-in replacement for libjpeg. – Gustavo Giráldez Jun 15 '11 at 18:24
  • libjpeg-turbo looks very promising (though a bit of a hassle to compile). I got a 3x improvement over the standard libjpeg when timing an execution of djpeg on a 7560x5600 jpg file. – Gustavo Giráldez Jun 15 '11 at 18:36
  • Looks promising. You don't know of any pre-compiled binaries for windows by chance? – Parand Jun 16 '11 at 01:54
  • In the SF page there are precompiled binaries for various platforms: http://sourceforge.net/projects/libjpeg-turbo/files/1.1.1/ – Gustavo Giráldez Jun 16 '11 at 02:27
  • 4
    If your application doesn't require displaying the image at full resolution (i.e. you aren't zooming full-screen on a small portion of it) then 27 megapixels may be overkill. You could preprocess the image to something smaller (on the order of 1K x 1K) once (either offline or in a background task), then load the smaller version in your app. – Russell Borogove Aug 25 '11 at 21:33
  • I second the idea of cutting down that image size. Unless the target user has a 6000x4485 monitor or your game involves a lot of high-resolution photo printing, I am unclear why one would need an image that large. – Namey Sep 21 '11 at 20:58
  • Can you Memory-Map the file in the background... before it needs to be shown... ? Like if you have a "Previous and Next" maybe you can memory map these. – Ben DeMott Nov 13 '11 at 21:12

3 Answers3

3

If your jpeg library supports it you can set the scaling parameters. You probably don't need a 6kx4k output image if you are showing it on the screen and it can speed up by a factor of several.

http://jpegclub.org/djpeg/

David Koski
  • 965
  • 7
  • 12
1

You can give a try on PyTurboJPEG which is a Python wrapper of libjpeg-turbo with insanely fast rescaling (1/2, 1/4, 1/8) while decoding large JPEG image like the following,

import pygame
from turbojpeg import TurboJPEG

# 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()

# direct rescaling 1/2 while decoding input.jpg to RGBA pixel array
pixel_array = jpeg.decode(
    open('input.jpg', 'rb').read(), 
    pixel_format=TJPF_RGBA, 
    scaling_factor=(1, 2))
height, width, _ = pixel_array.shape
image = pygame.image.frombuffer(pixel_array.data, (width, height), 'RGBA')

libjpeg-turbo prebuilt binaries for macOS and Windows 7 are also available here.

Lilo Huang
  • 51
  • 4
0

You might have better luck using a GUI library like TkInter or GTK+ over PyGame. If you need to use a game library, you might like PyGlet. For PyGame, someone said that this speeds it up: comments.gmane.org/gmane.comp.python.pygame/9015. You could also check libjpeg-turbo as stated in the comments at libjpeg-turbo.virtualgl.org. But, like I said, you might be better off using a GUI library or ported the whole thing to C/C++ to avoid the multi-language calls. Good luck!

kirbyfan64sos
  • 10,377
  • 6
  • 54
  • 75