将多个单色 QImage 组合成一个彩色 QImage

Combine multiple mono QImage into a color QImage

对于颜色列表,我有相应的QImage列表,格式为单色。单色图像经过处理,所有图像中的单个像素都可以是黑色。

我想将它们合并成彩色图像。

我有 3 个想法。

1.使用图像合成模式。我无法让它工作。 (编辑删除它,清理 post...)

2. 添加到目标时,使用单色图像作为每种颜色的蒙版。
我不知道如何实现它。

3. 迭代像素 - 慢,文档说像素操作函数很慢...

这个有效:

// Creating destination image
// m_colors: list of (n+1) QCcolor (last one corresponding to background)
// m_images: list of n QImage, Format_Mono, all of the same size (as the destination)
// using indexed image for destination since I have a limited palette
QImage preview = QImage(rect.size().toSize(), QImage::Format_Indexed8);
int previewWidth  = preview.size().width();
int previewHeight = preview.size().height();
int colorsSize = m_colors.size();
for(int k = 0; k < colorsSize; ++k)
{
    preview.setColor(k, m_colors.at(k).rgb());
}
--colorsSize;

// combining images
for(int j = 0; j < previewHeight; ++j)
{
    for(int i = 0; i < previewWidth; ++i)
    {
        // set background color
        preview.setPixel(i, j, colorsSize);
        for(int k = 0; k < colorsSize; ++k)
        {
            QImage im = m_images.at(k);
            if(!im.isNull())
            {
                if(m_images.at(k).pixelIndex(i, j) == 0)
                {
                    preview.setPixel(i, j, k);
                }
            }
        }
    }
}

我至少应该使用 scanLine() 来改进它,但不知道如何...我只能找到使用 scanLine() 和 32 位图像的示例,而不是 8 位或 2 位图像。
是否真的可以将 scanLine() 用于 8 位或 2 位图像?

我不明白文档 - 这是否意味着只有 32 位图像可以 read/written 使用 scanLine() 或者无论图像类型如何,该功能都将以相同的方式工作,并且我只使用 4 个字节之一 ?
使用 32 位图像而不是 8 位或 2 位图像会更有效吗?

如果我使用 32 位图像作为目标,并尝试使用 scanLine() 写入数据,我仍然如何提高我对单色图像的读取能力?

请帮助我改进我的算法,要么改进我迭代图像所有像素的版本,要么使用一些工具,例如使用合成组合图像。

Is it actually possible to use scanLine() with 8 or 2 bit images ?

是的。

Would be more effective to use 32 bit images instead of 8 or 2 bit ?

你要衡量,具体要看具体代码。为了简单起见,我在这里使用了 8 位代码,因为您的代码确实如此。

If I use 32 bit image for destination, and try to use scanLine() to write data, still how can I improve my reading of the mono images ?

在内部循环中复制图像可能不是一个好主意

QImage im = m_images.at(k)

然后不使用该副本进行下一次访问。

if(m_images.at(k).pixelIndex(i, j) == 0)

如果您的内循环遍历图像而不是在内循环中遍历目标像素,它应该会加快您的绘画速度。

如果图像是单色的,那么扫描线将指向需要解包的打包颜色信息。让 convertToFormat 转换图像然后使用 scanLine 读取解包信息更容易(也可能更快)。在下面的示例中,图像都是 8 位的。

#include<vector>

#include <QtGui/QImage>
#include <QtGui/QColor>

static char * img1[] = { 
   "5 5 2 1", "a c #000000", "b c #ffffff",
   "aabba", "aabba", "aabba", "aabba", "aabba"
};

static char * img2[] = {
   "5 5 2 1","a c #000000","b c #ffffff",
   "aaaaa", "aaaaa", "bbbbb", "bbbbb", "aaaaa"
};

int main( int argc, char* arg[] )
{
   auto images = std::vector<QImage>( 2 );
   images[0] = QImage( img1 );
   images[1] = QImage( img2 );

   auto colors = std::vector<QColor>( 2 );
   colors[0] = QColor( Qt::red );
   colors[1] = QColor( Qt::green );

   QImage combined = QImage( images[0].size(), QImage::Format_Indexed8 );
   combined.setColor( 0, Qt::black );
   combined.fill(0);

   for( int k = 1, num = images.size(); k <= num; ++k )
   {
      combined.setColor( k, colors[k-1].rgb() );
      QImage img= images[k-1];

      for( int i = 0, height = img.height(); i < height ; ++i )
      {
         uchar* src = img.scanLine(i);
         uchar* dst = combined.scanLine(i);

         for( int j = 0, width = mono.width(); j < width; ++j )
         {
            if( src[j] != 0 ) 
               dst[j] = k;
         }
      }
   }