ScreenTranslator/ImageProcessing.cpp

157 lines
3.7 KiB
C++
Raw Normal View History

#include <QDebug>
#include <leptonica/allheaders.h>
#include <tesseract/host.h>
#include "ImageProcessing.h"
2015-06-30 00:26:33 +07:00
#include "StAssert.h"
#if defined(Q_OS_LINUX)
# include <fstream>
# include <limits>
qint64 getFreeMemory () {
std::string token;
std::ifstream file ("/proc/meminfo");
qint64 freeMem = 0;
while (file >> token) {
if (token == "MemFree:" || token == "Buffers:" || token == "Cached:") {
unsigned long mem = 0;
freeMem += (file >> mem) ? mem : 0;
}
}
return freeMem * 1024;
}
#elif defined(Q_OS_WIN)
2015-09-23 01:41:08 +07:00
# include <windows.h>
qint64 getFreeMemory () {
MEMORYSTATUSEX statex;
statex.dwLength = sizeof (statex);
2015-09-23 01:41:08 +07:00
if (GlobalMemoryStatusEx (&statex)) {
return statex.ullAvailPhys;
}
return -1;
}
#endif
2015-09-23 01:41:08 +07:00
Pix * convertImage (const QImage &image) {
PIX *pix;
2015-10-11 23:51:37 +07:00
int width = image.width ();
int height = image.height ();
int depth = image.depth ();
int bytesPerLine = image.bytesPerLine ();
int wpl = bytesPerLine / 4;
2015-09-23 01:41:08 +07:00
pix = pixCreate (width, height, depth);
pixSetWpl (pix, wpl);
pixSetColormap (pix, NULL);
2015-10-11 23:51:37 +07:00
memmove (pix->data, image.bits (), bytesPerLine * height);
const qreal toDPM = 1.0 / 0.0254;
2015-10-11 23:51:37 +07:00
int resolutionX = image.dotsPerMeterX () / toDPM;
int resolutionY = image.dotsPerMeterY () / toDPM;
2015-09-23 01:41:08 +07:00
if (resolutionX < 300) {
resolutionX = 300;
}
if (resolutionY < 300) {
resolutionY = 300;
}
pixSetResolution (pix, resolutionX, resolutionY);
2015-10-11 22:33:55 +07:00
return pix;
}
2015-09-23 01:41:08 +07:00
QImage convertImage (Pix &image) {
int width = pixGetWidth (&image);
int height = pixGetHeight (&image);
int depth = pixGetDepth (&image);
int bytesPerLine = pixGetWpl (&image) * 4;
2015-10-11 23:51:37 +07:00
l_uint32 *datas = pixGetData (&image);
QImage::Format format;
2015-09-23 01:41:08 +07:00
if (depth == 1) {
format = QImage::Format_Mono;
2015-09-23 01:41:08 +07:00
}
else if (depth == 8) {
format = QImage::Format_Indexed8;
2015-09-23 01:41:08 +07:00
}
else {
format = QImage::Format_RGB32;
2015-09-23 01:41:08 +07:00
}
2015-09-23 01:41:08 +07:00
QImage result ((uchar *)datas, width, height, bytesPerLine, format);
// Set resolution
2015-09-23 01:41:08 +07:00
l_int32 xres, yres;
pixGetResolution (&image, &xres, &yres);
const qreal toDPM = 1.0 / 0.0254;
2015-09-23 01:41:08 +07:00
result.setDotsPerMeterX (xres * toDPM);
result.setDotsPerMeterY (yres * toDPM);
// Handle pallete
QVector<QRgb> _bwCT;
2015-09-23 01:41:08 +07:00
_bwCT.append (qRgb (255,255,255));
_bwCT.append (qRgb (0,0,0));
2015-09-23 01:41:08 +07:00
QVector<QRgb> _grayscaleCT (256);
for (int i = 0; i < 256; i++) {
_grayscaleCT.append (qRgb (i, i, i));
}
switch (depth) {
case 1:
2015-09-23 01:41:08 +07:00
result.setColorTable (_bwCT);
break;
case 8:
2015-09-23 01:41:08 +07:00
result.setColorTable (_grayscaleCT);
break;
default:
2015-09-23 01:41:08 +07:00
result.setColorTable (_grayscaleCT);
}
2015-09-23 01:41:08 +07:00
if (result.isNull ()) {
static QImage none (0,0,QImage::Format_Invalid);
qDebug ("Invalid format!!!\n");
return none;
}
2015-10-11 23:51:37 +07:00
return result;
}
2015-09-23 01:41:08 +07:00
Pix * prepareImage (const QImage &image, int preferredScale) {
Pix *pix = convertImage (image);
2015-06-30 00:26:33 +07:00
ST_ASSERT (pix != NULL);
2015-09-23 01:41:08 +07:00
Pix *gray = pixConvertRGBToGray (pix, 0.0, 0.0, 0.0);
2015-06-30 00:26:33 +07:00
ST_ASSERT (gray != NULL);
pixDestroy (&pix);
2015-09-23 01:41:08 +07:00
Pix *scaled = gray;
if (preferredScale > 0) {
float maxScaleX = MAX_INT16 / double (gray->w);
float scaleX = std::min (float (preferredScale), maxScaleX);
float maxScaleY = MAX_INT16 / double (gray->h);
float scaleY = std::min (float (preferredScale), maxScaleY);
float scale = std::min (scaleX, scaleY);
qint64 availableMemory = getFreeMemory () * 0.95;
if (availableMemory > 0) {
qint32 actualSize = gray->w * gray->h * gray->d / 8;
float maxScaleMemory = float (availableMemory) / actualSize;
scale = std::min (scale, maxScaleMemory);
}
scaled = pixScale (gray, scale, scale);
if (scaled == NULL) {
scaled = gray;
}
}
2015-09-23 01:41:08 +07:00
if (scaled != gray) {
pixDestroy (&gray);
}
return scaled;
}
2015-09-23 01:41:08 +07:00
void cleanupImage (Pix **image) {
pixDestroy (image);
}