从头开始创建栅格图像

OdGiRasterImage 接口提供了在几个步骤中从各种类型的源数据实现栅格图像创建的能力,并且生成的栅格图像将被所有图像处理功能接受,类似于从文件源加载的栅格图像。在本文中,我们将从头开始创建一个渐变图像。我们将使用本系列第一部分中先前描述的步骤提取的四个角像素颜色。

创建一个继承自 OdGiRasterImage 接口的类,并添加一些类成员来存储图像参数:

class GeneratedRasterImage : public OdGiRasterImage
{
    protected:
        OdUInt32 m_pixW, m_pixH;
        PixelFormatInfo m_pf;
        ODCOLORREF m_cornerColors[4];

实现 OdGiRasterImage 接口中定义的所有必需的抽象纯虚方法:

public:
    virtual OdUInt32 pixelWidth() const { return m_pixW; }
    virtual OdUInt32 pixelHeight() const { return m_pixH; }
    virtual OdUInt32 colorDepth() const { return 24; }
    virtual OdUInt32 numColors() const { return 0; }
    virtual ODCOLORREF color(OdUInt32 /*colorIndex*/) const { return 0; }
    virtual OdUInt32 paletteDataSize() const { return 0; }
    virtual void paletteData(OdUInt8* /*bytes*/) const { }
    virtual PixelFormatInfo pixelFormat() const { return m_pf; }
    virtual OdUInt32 scanLinesAlignment() const { return 4; }

在这里,我们简单地返回图像的宽度、高度和像素格式,这些将在栅格图像构建期间设置。图像使用每像素 24 位的颜色深度。调色板相关方法仅适用于索引图像(颜色深度小于或等于每像素 8 位),因此只需将其设为存根。

添加图像构造方法,这些方法将用于初始化 GeneratedRasterImage 类内部的数据:

GeneratedRasterImage() : m_pixW(1), m_pixH(1) {}
void configureImage(OdUInt32 nWidth, OdUInt32 nHeight, const PixelFormatInfo &pf, const ODCOLORREF *pColors)
{
    m_pixW = nWidth; m_pixH = nHeight; m_pf = pf;
    for (int i = 0; i < 4; i++)
        m_cornerColors[i] = pColors[i];
}

最后实现 scanLines 图像方法:

virtual const OdUInt8* scanLines() const { return NULL; }
virtual void scanLines(OdUInt8* scnLines, OdUInt32 firstScanline, OdUInt32 numLines = 1) const
{
    OdUInt32 scanLen = scanLineSize();
    for (OdUInt32 i = firstScanline; i < firstScanline + numLines; i++)
    {
        OdUInt8 *pScanLine = scnLines + ((i - firstScanline) * scanLen);
        for (OdUInt32 j = 0; j < m_pixW; j++, pScanLine += 3)
            computePixel(j, i, pScanLine);
    }
}

我们不在生成的栅格图像类中存储像素数据,因此在我们的情况下,直接扫描线访问器方法将始终返回 null。基于复制的 scanLines 方法简单地为每个像素调用内部的 computePixel 方法。computePixel 方法使用四个输入颜色在生成的图像表面内插值一个渐变,并将计算出的渐变颜色放入输出像素缓冲区:

void computePixel(OdUInt32 x, OdUInt32 y, OdUInt8 *pOutput) const
{
    // Interpolate colors by X-axis
    const double interpolateX = double(x) / (m_pixW - 1);
    const ODCOLORREF bottom = ODRGB((1.0 - interpolateX) * ODGETRED(m_cornerColors[0]) + interpolateX * ODGETRED(m_cornerColors[1]),
          (1.0 - interpolateX) * ODGETGREEN(m_cornerColors[0]) + interpolateX * ODGETGREEN(m_cornerColors[1]),
          (1.0 - interpolateX) * ODGETBLUE(m_cornerColors[0]) + interpolateX * ODGETBLUE(m_cornerColors[1]));
    const ODCOLORREF top = ODRGB((1.0 - interpolateX) * ODGETRED(m_cornerColors[2])   + interpolateX * ODGETRED(m_cornerColors[3]),
          (1.0 - interpolateX) * ODGETGREEN(m_cornerColors[2]) + interpolateX * ODGETGREEN(m_cornerColors[3]),
          (1.0 - interpolateX) * ODGETBLUE(m_cornerColors[2]) + interpolateX * ODGETBLUE(m_cornerColors[3]));
    // Interpolate colors in Y-axis
    const double interpolateY = double(y) / (m_pixH - 1);
    const ODCOLORREF color = ODRGB((1.0 - interpolateY) * ODGETRED(bottom) + interpolateY * ODGETRED(top),
          (1.0 - interpolateY) * ODGETGREEN(bottom) + interpolateY * ODGETGREEN(top),
          (1.0 - interpolateY) * ODGETBLUE(bottom)  + interpolateY * ODGETBLUE(top));
    pOutput[0] = ODGETRED(color); pOutput[1] = ODGETGREEN(color); pOutput[2] = ODGETBLUE(color);
}

示例图像类实现已完成。现在创建一个 GeneratedRasterImage 类的实例,初始化它并存储输出栅格图像以进行文件保存或进一步实验:

OdGiRasterImagePtr pOutputImage;
{
    OdSmartPtr<GeneratedRasterImage> pImage = OdRxObjectImpl<GeneratedRasterImage>::createObject();
    pImage->configureImage(256, 256, pInputImage->pixelFormat(), inputColors);
    pOutputImage = pImage;
}

现在我们可以使用本系列第一部分中“将栅格图像保存到文件”的代码来存储我们生成的栅格图像,并查看生成的文件:

今天就开始行动

免费试用 ODA 软件 60 天。
无风险,无需信用卡。

免费试用