转换Leptonica像素对象到QPixmap(或其他图像对象)

Convert Leptonica Pix Object to QPixmap ( or other image object )

本文关键字:对象 其他 图像 QPixmap Leptonica 像素 转换      更新时间:2023-10-16

我正在使用Leptonica Library来处理一些图片。之后,我想在我的QT GUI中显示它们。Leptonica使用自己的图像格式Pix,而QT使用自己的格式QPixmap。目前,我唯一的方法是将处理后的图片保存为文件(如bmp),然后用QT函数调用再次加载它们。现在我想在我的代码中转换它们,所以我不需要绕道将它们保存在文件系统中。有什么办法吗?

问好

//编辑:

好的,正如已经建议的那样,我尝试将PIX*转换为QImage。PIX*的定义如下:

http://tpgit.github.com/Leptonica/pix_8h_source.html

struct Pix
{
  l_uint32             w;           /* width in pixels                   */
  l_uint32             h;           /* height in pixels                  */
  l_uint32             d;           /* depth in bits                     */
  l_uint32             wpl;         /* 32-bit words/line                 */
  l_uint32             refcount;    /* reference count (1 if no clones)  */
  l_int32              xres;        /* image res (ppi) in x direction    */
                                    /* (use 0 if unknown)                */
  l_int32              yres;        /* image res (ppi) in y direction    */
                                    /* (use 0 if unknown)                */
  l_int32              informat;    /* input file format, IFF_*          */
  char                *text;        /* text string associated with pix   */
  struct PixColormap  *colormap;    /* colormap (may be null)            */
  l_uint32            *data;        /* the image data                    */
};

而QImage为我提供了这样一个方法:

http://developer.qt.nokia.com/doc/qt - 4.8 -/- qimage.html # QImage-7

QImage ( const uchar * data, 
    int width, 
    int height, 
    int bytesPerLine, 
    Format format )

我假设我不能在调用构造函数时将数据从PIX复制到QImage。我想我需要填补的QImage像素逐像素,但实际上我不知道如何?我需要遍历所有坐标吗?我如何看待比特深度?有什么想法吗?

我用它来转换QImage到PIX:

PIX* TessTools::qImage2PIX(QImage& qImage) {
  PIX * pixs;
  l_uint32 *lines;
  qImage = qImage.rgbSwapped();
  int width = qImage.width();
  int height = qImage.height();
  int depth = qImage.depth();
  int wpl = qImage.bytesPerLine() / 4;
  pixs = pixCreate(width, height, depth);
  pixSetWpl(pixs, wpl);
  pixSetColormap(pixs, NULL);
  l_uint32 *datas = pixs->data;
  for (int y = 0; y < height; y++) {
    lines = datas + y * wpl;
    QByteArray a((const char*)qImage.scanLine(y), qImage.bytesPerLine());
    for (int j = 0; j < a.size(); j++) {
      *((l_uint8 *)lines + j) = a[j];
    }
  }
  return pixEndianByteSwapNew(pixs);
}

这是用于转换PIX到QImage:

QImage TessTools::PIX2QImage(PIX *pixImage) {
  int width = pixGetWidth(pixImage);
  int height = pixGetHeight(pixImage);
  int depth = pixGetDepth(pixImage);
  int bytesPerLine = pixGetWpl(pixImage) * 4;
  l_uint32 * s_data = pixGetData(pixEndianByteSwapNew(pixImage));
  QImage::Format format;
  if (depth == 1)
    format = QImage::Format_Mono;
  else if (depth == 8)
    format = QImage::Format_Indexed8;
  else
    format = QImage::Format_RGB32;
  QImage result((uchar*)s_data, width, height, bytesPerLine, format);
  // Handle pallete
  QVector<QRgb> _bwCT;
  _bwCT.append(qRgb(255,255,255));
  _bwCT.append(qRgb(0,0,0));
  QVector<QRgb> _grayscaleCT(256);
  for (int i = 0; i < 256; i++)  {
    _grayscaleCT.append(qRgb(i, i, i));
  }
  if (depth == 1) {
    result.setColorTable(_bwCT);
  }  else if (depth == 8)  {
    result.setColorTable(_grayscaleCT);
  } else {
    result.setColorTable(_grayscaleCT);
  }
  if (result.isNull()) {
    static QImage none(0,0,QImage::Format_Invalid);
    qDebug() << "***Invalid format!!!";
    return none;
  }
  return result.rgbSwapped();
}

这段代码接受一个const QImage&参数。

static PIX* makePIXFromQImage(const QImage &image)
{
 QByteArray ba;
 QBuffer buf(&ba);
 buf.open(QIODevice::WriteOnly);
 image.save(&buf, "BMP");
 return pixReadMemBmp(ba.constData(), ba.size());
}

我不知道Leptonica Library,但是我浏览了一下文档,找到了关于PIX结构的文档。您可以从原始数据创建一个QImage,并使用convertFromImage将其转换为QPixmap .

我可以这样解决这个问题:

Leptonica提供了一个函数

l_int32     pixWriteMemBmp (l_uint8 **pdata, size_t *psize, PIX *pix)

使用这个函数,您可以写入内存而不是文件流。(在这个例子中)Bmp的Header和格式仍然存在(对于其他图像格式也有相同的函数)。

QT对应的函数是:

bool QImage::loadFromData ( const uchar * data, int len, const char * format = 0 )

由于Header访问,我只需要将数据ptr和大小传递给loadFromData函数,QT完成其余的工作。

所以它们合在一起就像这样:

PIX *m_pix;
FILE * pFile;
pFile = fopen( "PathToFile", "r" );
m_pix = pixReadStreamBmp(pFile); // If other file format use the according function
fclose(pFile);
// Now we have a Pix object from leptonica
l_uint8* ptr_memory;
size_t len;
pixWriteMemBmp(&ptr_memory, &size, m_pix);
// Now we have the picture somewhere in the memory
QImage testimage;
QPixmap pixmap;
testimage.loadFromData((uchar *)ptr_memory,len);
pixmap.convertFromImage(testimage);
// Now we have the image as a pixmap in Qt

这实际上对我有效,虽然我不知道是否有一种方法可以这么容易地做到这一点。(如果有,请告诉我)

您可以将像素图保存到RAM而不是文件(使用QByteArray存储数据,并使用QBuffer作为I/O设备)。