Page 1 of 1

Displaying Album Art in Python - Example Please

PostPosted: Sat Nov 25, 2017 4:34 pm
by dplummer

I want to display Album Art that is stored in a tag from a Python program. I can access the SDBImage object and extract the image dimensions etc but so far none of my attempts to use the ImageData value to create an image have worked. My current code is as follows:

Code: Select all
        print("Image format:", img.ImageFormat, "Size: ", img.Width, " x ", img.Height, " Length: ", img.ImageDataLen)
        iw = img.Width
        ih = img.Height
        p = ctypes.cast(img.ImageData, ctypes.c_char_p)
        im = PIL.Image.frombytes("RGB", (iw, ih), p, "jpeg", "RGB", None, 1)
        im = im.resize((256, 256))
        self.albumimage = PIL.ImageTk.PhotoImage(im)
        self.imgcanvas.create_image(128, 128, image=self.albumimage, anchor=tk.CENTER)

This correctly reports the image details:
"Image format: image/jpeg Size: 500 x 492 Length: 43667"
then throws the error:
"ValueError: cannot decode image data"

If I create the PhotoImage from a file saved from the same album the image is displayed correctly.

I have studied the information which gives an example in VB and have also read the topic
The latter suggests writing the data to an intermediate file, however I cannot work out how to do this in Python either.

Could someone post an example please of how one might do this in Python 3

Many thanks

Re: Displaying Album Art in Python - Example Please

PostPosted: Sun Nov 26, 2017 8:45 am
by Peke
You are approaching it wrongly. Point of ImageData is to read raw image to file/mem and tell that file or mem segment is Image. Details on image should be automatically read.

eg. Read ImageData stream -> Image Variable or direcly raw to file (AAImage.jpg) -> Load result to Python PhotoImage that should do.

let me know if it work I'm bit rusty in python.

Re: Displaying Album Art in Python - Example Please

PostPosted: Sun Nov 26, 2017 5:58 pm
by dplummer
Thanks for responding Pavle,

I am afraid that I need a bit more guidance. You say "Read ImageData stream -> Image Variable".

As I understand it the ImageData member of SDBImage is a pointer to the data buffer and is stored in an integer. My first problem is to get the ImageData as a python bytes object. From that I should be able to use BytesIO to create a readable stream. I think I should be able to do something with ctypes but none of my attempts so far has worked.

What do I do with the value ImageData to create a Python bytes object (array of bytes)?

Thanks again

Re: Displaying Album Art in Python - Example Please

PostPosted: Thu Nov 30, 2017 7:47 am
by dplummer

I have tried hard but with no success to extract an image from the ImageData item in the Image object. In the end I gave up on this approach and decided to go back to the track file and use mutagen to extract the image tag picture data. The code I used is below.

I would still however be very interested if anyone could post an example of doing this within the MM Object Structure.

Thanks for reading this.

Code: Select all
import tkinter as tk
import mutagen
from PIL import Image, ImageTk


        if song.AlbumArt == None or song.AlbumArt.Count == 0:
        artlst = song.AlbumArt
        # Get the first AlbumArt item and its Image object
        art = artlst.Item(0)
        img = art.Image
        # Set imdata to a bytes object containing the image data
        # This currently assumes that images are always jpeg encoded
        if art.Itemstorage == 0:        # zero indicates image stored in tag
            # Read file with mutagen and get the first Picture Data according to file type
            mdata = mutagen.File(song.path)
            if mdata==None:
                print("Cannot identify type of: ", song.path)
            elif mdata.__class__.__name__=="MP3":
                imdata = mdata.tags.getall("APIC")[0].data
            elif mdata.__class__.__name__=="FLAC":
                imdata =[0].data
                print("Cannot get cover image from file type: ", mdata.__class__.__name__)
        else:                           # one indicates image stored in file
            with open(art.PicturePath, "rb") as f:
                imdata =

        # Create an image from the tag data and resize to canvas
        im = Image.frombytes("RGB", (img.Width, img.Height), imdata, "jpeg", "RGB", None, 1)
        im = im.resize((self.imgcanvas.winfo_width(), self.imgcanvas.winfo_height()))
        # Make a Photoimage from the Image
        self.albumimage = ImageTk.PhotoImage(im)
        # Load the image onto the canvas
        self.imgcanvas.create_image(0, 0, image=self.albumimage, anchor=tk.NW)