【问题标题】:Convert Leptonica Pix Object to QPixmap ( or other image object )将 Leptonica Pix 对象转换为 QPixmap(或其他图像对象)
【发布时间】:2023-03-25 13:09:01
【问题描述】:

我正在使用 Leptonica 库来处理一些图片。之后我想在我的 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 像素,但实际上我不知道怎么做?我需要遍历所有坐标吗?我如何看待位深?这里有什么想法吗?

【问题讨论】:

    标签: c++ image qt qpixmap


    【解决方案1】:

    I usethis 用于将 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();
    }
    

    【讨论】:

      【解决方案2】:

      此代码接受const QImage&amp; 参数。

      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());
      }
      

      【讨论】:

        【解决方案3】:

        我不知道 Leptonica 库,但我简要查看了文档并找到了有关 PIX 结构的文档。您可以从原始数据创建一个QImage 并将其转换为带有convertFromImage 的QPixmap。

        【讨论】:

        • 嗯,谢谢 - 我试着用这个,但实际上我有点困惑 -> 在我的问题上查看更新
        • 如果幸运的话,您应该能够通过将 Pix.data 转换为 uchar* 来使用它:reinterpret_cast(Pix.data)。您必须调整 QImage 构造函数的 Format 参数(尝试 QImage::Format_RGB32 或 QImage::Format_ARGB32)。如果你不走运,你必须首先创建一个大小为 PIX.wpl * h 的新缓冲区,并通过从 PIX.data 读取 l_uint32 并将它们分成四个字节(对于 R、G、B、A ) 通过屏蔽和移位。
        • 哈,好吧,我明白了 - 做了一点点不同(因为有一个功能可以做到这一点) - 但是,如果没有你建议我在使用 QPixmap 之前使用 QImage,我可能不会找到它!
        【解决方案4】:

        我可以这样解决问题:

        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
        

        这实际上对我有用,但我不知道是否有一种方法可以如此轻松地向后执行此操作。 (如果有,请告诉我)

        最好的问候

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-01-16
            • 1970-01-01
            • 2018-12-30
            • 2012-01-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多