Reputation: 26007
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?
Upvotes: 5
Views: 1695
Reputation: 207485
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.sstatic.net/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'
Upvotes: 0
Reputation: 8380
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.
Upvotes: 0