ScreenTranslator/ImageProcessing.cpp

150 lines
3.6 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"
#ifdef WIN32
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-09-23 01:41:08 +07:00
QImage swapped = image.rgbSwapped ();
int width = swapped.width ();
int height = swapped.height ();
int depth = swapped.depth ();
int wpl = swapped.bytesPerLine () / 4;
2015-09-23 01:41:08 +07:00
pix = pixCreate (width, height, depth);
pixSetWpl (pix, wpl);
pixSetColormap (pix, NULL);
l_uint32 *outData = pix->data;
2015-09-23 01:41:08 +07:00
for (int y = 0; y < height; y++) {
l_uint32 *lines = outData + y * wpl;
2015-09-23 01:41:08 +07:00
QByteArray a ((const char *)swapped.scanLine (y), swapped.bytesPerLine ());
for (int j = 0; j < a.size (); j++) {
*((l_uint8 *)lines + j) = a[j];
}
}
const qreal toDPM = 1.0 / 0.0254;
2015-09-23 01:41:08 +07:00
int resolutionX = swapped.dotsPerMeterX () / toDPM;
int resolutionY = swapped.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-09-23 01:41:08 +07:00
return pixEndianByteSwapNew (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;
l_uint32 *datas = pixGetData (pixEndianByteSwapNew (&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-09-23 01:41:08 +07:00
return result.rgbSwapped ();
}
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);
#ifdef WIN32
qint64 availableMemory = getFreeMemory () * 0.95;
qint32 actualSize = gray->w * gray->h * gray->d / 8;
float maxScaleMemory = float (availableMemory) / actualSize;
scale = std::min (scale, maxScaleMemory);
#endif
scaled = pixScale (gray, scale, scale);
}
2015-06-30 00:26:33 +07:00
ST_ASSERT (scaled != NULL);
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);
}