2 Stimmen

Erstellen Sie ein PhotoImage mit einem C++-Puffer mit: Python 3.3, Python.Boost und Tkinter

Ich verwende Tkinter und python.boost auf python 3.3.

Ich möchte eine einfache Benutzeroberfläche erstellen, die ein Bild in der Mitte anzeigt. Das Bild wird in einer C++-Klasse mit Double-Werten gespeichert. Um ein Bild mit tkinter zu zeigen, muss ich eine FotoBild Objekt.

Ich habe gelesen, dass es möglich ist, ein PhotoImage-Objekt mit der Methode Image.fromstring(mode, size, data, decoder, parameters) . Was ich denke, ist: wenn ich eine Funktion, die meine Puffer in einen std::string konvertiert erstellen wir in der Lage, ein PhotoImage-Objekt zu erstellen.

Mein C++ Kurs ist:

class DoubleImage
{
    double* m_dBuffer; // Values from 0 to 1

public:
    DoubleImage(const char* fileName, const int width, const int height);

    /* Class Functions  */

    std::string toString( void ) {
        double *pSrc  = m_dBuffer;
        int size = getWidth() * getHeight() * getChannels();

        char* buffer = new char[size];
        char* pbuffer = buffer;

        for ( int i = 0; i < size; ++i, ++pSrc, ++pbuffer ) {
            *pbuffer = ((char) (*pSrc * 255.0));
        }

        std::string ret(buffer);

        delete[] buffer;

        return ret;
    }
};

Und der Python-Boost-Code ist:

using namespace boost::python;

BOOST_PYTHON_MODULE(ImageModule)
{

    class_<DoubleImage>("DoubleImage", init<const char*, const int, const int>()) 
        .add_property("width", &DoubleImage::getWidth)
        .add_property("height", &DoubleImage::getHeight)
        .add_property("channels", &DoubleImage::getChannels)
        // Some functions ...
        .def("toString", &DoubleImage::toString)
    ; 
}

Aber wenn ich toString in Python ausführen, erhalten Sie diesen Fehler:

>>> from ImageModule import *
>>> img = DoubleImage('001.png', 300, 200)
>>> buffer = img.toString()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x86 in position 155: invalid start byte
>>>

Ich habe zwei Fragen, erstens, was fehlt mir?? und zweitens, wenn ich diesen Fehler gelöst habe, welche Parameter muss ich verwenden, um ein PhotoImage-Objekt zu erstellen?

0voto

Marcus Punkte 275

Nach langem Leiden habe ich endlich die Lösung gefunden :P

Zunächst die Funktion toString müssen auf diese Weise geändert werden:

std::string DoubleImage::toString( void ) {
    ECV_CHECK_ERROR ( m_eType == IT_UKNOWN, "The image is not initialized!" );

    double *pSrc  = (double *) m_cvImage.data;
    long size = getWidth() * getHeight() * getChannels();

    std::string ret(size, ' ');

    for ( long i = 0; i < size; ++i, ++pSrc ) {
         ret[i] = ((char) (*pSrc * 255.0));
    }

    return ret;
}

andernfalls wird die resultierende std::string nicht die Gesamtlänge haben (weil der Konstruktor nach dem ersten ' \0 '). Außerdem wird der seltsame Fehler " UnicodeDecodeError ", erscheint nur bei Verwendung von Python 3.3. Bei Verwendung von Python 2.7 ist das Problem gelöst. Ich empfehle daher die Verwendung von Python 2.7 für die Bildverarbeitung.

Dann habe ich die PIL-Modul (auch nur unter python 2.7 verfügbar). Dann erstelle ich in Python das PhotoImage-Objekt mit diesem Code:

>>> from ImageModule import *
>>> from PIL import image
>>> from ImageTk import PhotoImage
>>> img = DoubleImage('001.png', 300, 200)
>>> buffer = img.toString()
>>> img_pil = Image.fromstring('RGB', [300, 200], buffer, 'raw', 'BGR', 300 * 3, 0)
>>> tk_image = PhotoImage(img_pil)

wobei 300 die Bildbreite, 200 die Bildhöhe, RGB das Ausgabeformat, BGR das Eingabeformat (IplImage) und 3 die Kanäle (3 * 300 der Bildschritt) sind. Dann funktionieren alle wie ein Charme :)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X