【问题标题】:Combine multiple mono QImage into a color QImage将多个单声道 QImage 组合成一个彩色 QImage
【发布时间】:2016-01-20 23:30:03
【问题描述】:

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

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

我有 3 个想法。

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

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 位图像吗?

我不理解文档 - 这是否意味着只能使用 scanLine() 读取/写入 32 位图像,或者无论图像类型如何,该功能都将以相同的方式工作,我只使用其中一个4 个字节?
使用 32 位图像而不是 8 位或 2 位图像会更有效吗?

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

请帮助我改进我的算法,或者改进我可以迭代图像的所有像素的版本,或者使用一些工具,比如使用合成来组合图像。

【问题讨论】:

  • 我不确定您期望的结果是什么样的。非 32 位图像格式使用颜色表,请参阅 Pixel Manipulation
  • 其他信息也在Format enum下的描述中。
  • 完全正确 - 我的代码中的第一部分填充了颜色表。

标签: qt qimage


【解决方案1】:

真的可以使用scanLine() 处理8 位或2 位图像吗?

是的。

使用 32 位图像而不是 8 位或 2 位图像会更有效吗?

您必须进行测量,这取决于具体的代码。为了简单起见,我在这里使用了 8 位代码,因为您的代码确实如此。

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

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

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

【讨论】:

  • 谢谢,我试试。至于复制图像而不是使用它...if(m_images.at(k).pixelIndex(i, j) == 0) - 我是打算使用它的,我一直在不断地进行更改。 fill() 没有额外的全通吗?这就是我将它包含在循环中的原因。
  • 是的,它会通过,但它仍然会比 i*j 调用 setPixel 更快
猜你喜欢
  • 2012-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-05
相关资源
最近更新 更多