5

I am trying to convert a iamge loaded using PIL to a Cimg image object. I understand that Cimg is a c++ library and PIL is a python imaging library. Given an image url, my aim is to calculate the pHash of an image without writing it onto a disk. pHash module works with a Cimg image object and it has been implemented in C++. So I am planning to send the required image data from my python program to the c++ program using python extension binding. In the following code sniplet, I am loading the image from the given url:

//python code sniplet   
import PIL.Image as pil

file = StringIO(urlopen(url).read())
img = pil.open(file).convert("RGB")

The Cimg image object that I need to construct looks as follows:

CImg  ( const t *const  values,  
    const unsigned int  size_x,  
    const unsigned int  size_y = 1,  
    const unsigned int  size_z = 1,  
    const unsigned int  size_c = 1,  
    const bool  is_shared = false  
)

I can get the width(size_x) and height(size_y) using img.size and can pass it to c++. I am unsure of how to fill 'values' field of the Cimg object? What kind of data structure to use to pass the image data from the python to c++ code?

Also, is there any other way to convert a PIL image to Cimg?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Shobhit Puri
  • 25,769
  • 11
  • 95
  • 124

2 Answers2

0

I assume that your main application is written in Python and you want to call C++ code from Python. You can achieve that by creating a "Python module" that will expose all native C/C++ functionality to Python. You can use a tool like SWIG to make your work easier.

That's the best solution of your problem that came to my mind.

cubuspl42
  • 7,833
  • 4
  • 41
  • 65
  • Thanks for the reply. I have been trying to use python extension module you mentioned. I am not sure of what to pass for the image data. The second part of my question was that "I'm unsure of how to fill 'values' field of the Cimg object". Can I just use the image data that I downloaded, directly to the 'value' variable inside the Cimg structure? – Shobhit Puri Mar 11 '13 at 05:12
0

The simplest way to pass an image from Python to a C++ CImg-based program is via a pipe.

So this a C++ CImg-based program that reads an image from stdin and returns a dummy pHash to the Python caller - just so you can see how it works:

#include "CImg.h"
#include <iostream>

using namespace cimg_library;
using namespace std;

int main()
{
    // Load image from stdin in PNM (a.k.a. PPM Portable PixMap) format
    cimg_library::CImg<unsigned char> image;
    image.load_pnm("-");

    // Save as PNG (just for debug) rather than generate pHash
    image.save_png("result.png");

    // Send dummy result back to Python caller
    std::cout << "pHash = 42" << std::endl;
}

And here is a Python program that downloads an image from a URL, converts it into a PNM/PPM ("Portable PixMap") and sends it to the C++ program so it can generate and return a pHash:

#!/usr/bin/env python3

import requests
import subprocess
from PIL import Image
from io import BytesIO

# Grab image and open as PIL Image
url = 'https://i.stack.imgur.com/DRQbq.png'
response = requests.get(url)
img = Image.open(BytesIO(response.content)).convert('RGB')

# Generate in-memory PPM image which CImg can read without any libraries
with BytesIO() as buffer:
    img.save(buffer,format="PPM")
    data = buffer.getvalue()

# Start CImg passing our PPM image via pipe (not disk)
with subprocess.Popen(["./main"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) as proc:
    (stdout, stderr) = proc.communicate(input=data)

print(f"Returned: {stdout}")

If you run the Python program, you get:

Returned: b'pHash = 42\n'
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432