Dear all,
I am trying to speed up the loading of a JPEG image by replacing the decode step during the loading with some libturbojpeg functions.
So I put together a minimal working example from several pieces which I found in forums etc:
.pro file:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Application
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp\
JpegEncoderDecoder/JpegEncoderDecoder.cpp
HEADERS += mainwindow.h\
JpegEncoderDecoder/JpegEncoderDecoder.h
FORMS += mainwindow.ui
LIBS += -L$$PWD/usr/lib/ -ljpeg -lturbojpeg
INCLUDEPATH += $$PWD/usr/include
DEPENDPATH += $$PWD/usr/include
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = Application
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp\
JpegEncoderDecoder/JpegEncoderDecoder.cpp
HEADERS += mainwindow.h\
JpegEncoderDecoder/JpegEncoderDecoder.h
FORMS += mainwindow.ui
LIBS += -L$$PWD/usr/lib/ -ljpeg -lturbojpeg
INCLUDEPATH += $$PWD/usr/include
DEPENDPATH += $$PWD/usr/include
To copy to clipboard, switch view to plain text mode
main.cpp:
#include "mainwindow.h"
#include <QApplication>
#include <QImageReader>
#include <QByteArray>
#include <QFile>
#include <QBuffer>
#include <QString>
#include <jpeglib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <JpegEncoderDecoder/JpegEncoderDecoder.h>
int read_jpeg_file(unsigned char *pInputDataStream, std::string file_name)
{
std::ifstream imageStream;
imageStream.open(file_name.c_str(), std::ios_base::binary);
imageStream.seekg (0, std::ios::end);
int n = imageStream.tellg();
imageStream.seekg (0, std::ios::beg);
pInputDataStream = new unsigned char[n];
if (!imageStream.is_open())
{
std::cout << stderr << "Can't open input file !\n";
exit(1);
}
else
{
imageStream.read((char *)pInputDataStream, n);
}
return 0;
}
int main(int argc, char *argv[])
{
unsigned char *pInputDataStream;
int width = 320;
int height= 240;
int JPEG_QUALITY=75;
int COLOR_COMPONENTS=3;
int in_len = width*height*COLOR_COMPONENTS;
std::string strFileName=qPath.toStdString();
//Step 1: Load .jpeg in memory filebuffer
int iRead = read_jpeg_file(pInputDataStream, strFileName);
//Step 2: Use turbojpeglib to decompress filebuffer to uncompressedbuffer
JpegEncoderDecoder bla(width, height, JPEG_QUALITY, COLOR_COMPONENTS);
unsigned char*buffer = bla.decodeJpeg(pInputDataStream);
//Step 3: Convert to QImage
QImage myDecodedJPEGimage
(buffer, width, height,
QImage::Format_RGB888) ;
//Step 4: Show in main window
MainWindow w(myDecodedJPEGimage);
w.show();
return a.exec();
}
#include "mainwindow.h"
#include <QApplication>
#include <QImageReader>
#include <QByteArray>
#include <QFile>
#include <QBuffer>
#include <QString>
#include <jpeglib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <JpegEncoderDecoder/JpegEncoderDecoder.h>
int read_jpeg_file(unsigned char *pInputDataStream, std::string file_name)
{
std::ifstream imageStream;
imageStream.open(file_name.c_str(), std::ios_base::binary);
imageStream.seekg (0, std::ios::end);
int n = imageStream.tellg();
imageStream.seekg (0, std::ios::beg);
pInputDataStream = new unsigned char[n];
if (!imageStream.is_open())
{
std::cout << stderr << "Can't open input file !\n";
exit(1);
}
else
{
imageStream.read((char *)pInputDataStream, n);
}
return 0;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString qPath("jpeg-100.jpg");
unsigned char *pInputDataStream;
int width = 320;
int height= 240;
int JPEG_QUALITY=75;
int COLOR_COMPONENTS=3;
int in_len = width*height*COLOR_COMPONENTS;
std::string strFileName=qPath.toStdString();
//Step 1: Load .jpeg in memory filebuffer
int iRead = read_jpeg_file(pInputDataStream, strFileName);
//Step 2: Use turbojpeglib to decompress filebuffer to uncompressedbuffer
JpegEncoderDecoder bla(width, height, JPEG_QUALITY, COLOR_COMPONENTS);
unsigned char*buffer = bla.decodeJpeg(pInputDataStream);
//Step 3: Convert to QImage
QImage myDecodedJPEGimage(buffer, width, height, QImage::Format_RGB888) ;
//Step 4: Show in main window
MainWindow w(myDecodedJPEGimage);
w.show();
return a.exec();
}
To copy to clipboard, switch view to plain text mode
JpegEncoderDecoder.h:
#ifndef JPEGENCODERDECODER_H
#define JPEGENCODERDECODER_H
class JpegEncoderDecoder
{
public:
JpegEncoderDecoder(int width=1920, int height=1080, int JPEG_QUALITY=75, int COLOR_COMPONENTS=3);
void encodeJpeg(unsigned char * pBuffer);
unsigned char * decodeJpeg(unsigned char * pcompressedImage);
private:
int m_width;
int m_height;
const int m_JPEG_QUALITY ;
const int m_COLOR_COMPONENTS;
};
#endif // JPEGENCODERDECODER_H
#ifndef JPEGENCODERDECODER_H
#define JPEGENCODERDECODER_H
class JpegEncoderDecoder
{
public:
JpegEncoderDecoder(int width=1920, int height=1080, int JPEG_QUALITY=75, int COLOR_COMPONENTS=3);
void encodeJpeg(unsigned char * pBuffer);
unsigned char * decodeJpeg(unsigned char * pcompressedImage);
private:
int m_width;
int m_height;
const int m_JPEG_QUALITY ;
const int m_COLOR_COMPONENTS;
};
#endif // JPEGENCODERDECODER_H
To copy to clipboard, switch view to plain text mode
// some includes....
JpegEncoderDecoder::JpegEncoderDecoder(int width, int height, int JPEG_QUALITY, int COLOR_COMPONENTS) :
m_width (width)
, m_height(height)
, m_JPEG_QUALITY(JPEG_QUALITY)
, m_COLOR_COMPONENTS(COLOR_COMPONENTS)
{
}
unsigned char * JpegEncoderDecoder::decodeJpeg(unsigned char *pcompressedImage)
{
long unsigned int _jpegSize; //!< _jpegSize from above
int jpegSubsamp;
unsigned char buffer[m_width*m_height*m_COLOR_COMPONENTS]; //!< will contain the decompressed image
tjhandle _jpegDecompressor = tjInitDecompress();
tjDecompressHeader2(_jpegDecompressor, pcompressedImage, _jpegSize, &m_width, &m_height, &jpegSubsamp);
tjDecompress2(_jpegDecompressor, pcompressedImage, _jpegSize, buffer, m_width, 0/*pitch*/, m_height, TJPF_RGB, TJFLAG_FASTDCT);
tjDestroy(_jpegDecompressor);
return buffer;
}
// some includes....
JpegEncoderDecoder::JpegEncoderDecoder(int width, int height, int JPEG_QUALITY, int COLOR_COMPONENTS) :
m_width (width)
, m_height(height)
, m_JPEG_QUALITY(JPEG_QUALITY)
, m_COLOR_COMPONENTS(COLOR_COMPONENTS)
{
}
unsigned char * JpegEncoderDecoder::decodeJpeg(unsigned char *pcompressedImage)
{
long unsigned int _jpegSize; //!< _jpegSize from above
int jpegSubsamp;
unsigned char buffer[m_width*m_height*m_COLOR_COMPONENTS]; //!< will contain the decompressed image
tjhandle _jpegDecompressor = tjInitDecompress();
tjDecompressHeader2(_jpegDecompressor, pcompressedImage, _jpegSize, &m_width, &m_height, &jpegSubsamp);
tjDecompress2(_jpegDecompressor, pcompressedImage, _jpegSize, buffer, m_width, 0/*pitch*/, m_height, TJPF_RGB, TJFLAG_FASTDCT);
tjDestroy(_jpegDecompressor);
return buffer;
}
To copy to clipboard, switch view to plain text mode
I am omitting the definition of JpegEncoderDecoder::encodeJpeg, as well as mainwindow.h and mainwindow.cpp here.
This is compiling and also running fine, but unfortunately it does not show the image as expected. Instead I just see a black rectangle with some colored pixels in it. What am I doing wrong?
Bookmarks