[返回博客](/cn/blog) # 处理栅格图像文件

Andrew Markovich 二月 02, 2017 [\#Raster image](/cn/blog/tag/raster-image) [\#Example](/cn/blog/tag/example)

<a class="a2a_button_facebook"></a><a class="a2a_button_twitter"></a><a class="a2a_button_linkedin"></a>

我们经常被问到的一个问题是：如何在 Teigha 中修改栅格图像数据？有时开发人员会因为 OdGiRasterImage API 中缺少栅格图像编辑功能而感到困惑，该 API 只包含栅格图像数据获取器。本文将展示如何在加载后修改栅格图像。

### 从文件加载栅格图像

为了从文件加载栅格图像，Teigha 提供了一个栅格服务模块，可以使用 Teigha 动态链接器在运行时访问：

```
<span class="hljs-title">OdRxRasterServicesPtr</span> pRasSvcs = <span class="hljs-keyword">odrxDynamicLinker</span>()-><span class="hljs-keyword">loadApp</span>(RX_RASTER_SERVICES_APPNAME, false);
if (pRasSvcs.<span class="hljs-keyword">isNull</span>()) // Check that raster services module correctly loaded
    throw <span class="hljs-keyword">OdError</span>(eNullPtr);
```

对于动态库项目配置，**“RxRasterServices.tx”** 模块必须在应用程序目录中可用。对于静态库项目配置，应用程序必须链接 **“RxRasterServices”** 静态库，并且栅格服务模块必须在 Teigha 静态模块映射中注册：

```
<span class="hljs-keyword">ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT</span>(ExRasterModule);
<span class="hljs-keyword">ODRX_DECLARE_STATIC_MODULE_ENTRY_POINT</span>(OdRasterProcessingServicesImpl);

<span class="hljs-keyword">ODRX_BEGIN_STATIC_MODULE_MAP</span>()
    <span class="hljs-keyword">ODRX_DEFINE_STATIC_APPLICATION</span>(RX_RASTER_SERVICES_APPNAME,  ExRasterModule)
    <span class="hljs-keyword">ODRX_DEFINE_STATIC_APPLICATION</span>(OdRasterProcessorModuleName, OdRasterProcessingServicesImpl)
<span class="hljs-keyword">ODRX_END_STATIC_MODULE_MAP</span>()
```

在此示例中，我们还注册了栅格处理模块，因为它在栅格图像加载或保存期间可能会被需要。

如果栅格服务模块加载正确，我们可以使用单个调用从文件加载栅格图像：

```
<span class="hljs-title">OdGiRasterImagePtr</span> pInputImage = pRasSvcs-><span class="hljs-keyword">loadRasterImage</span>(inputFileName);
if (pInputImage.<span class="hljs-keyword">isNull</span>()) // Check that raster image correctly loaded
    throw <span class="hljs-keyword">OdError</span>(eNullPtr);
```

OdRxRasterServices::loadRasterImage 方法会自动检测栅格图像格式。如果栅格图像加载正确，栅格图像智能指针将为非空，我们可以使用它来访问栅格图像像素数据、格式、调色板和其他属性。

### 将栅格图像保存到文件

栅格服务模块也可以用于保存栅格图像。在我们的示例中，我们将使用最简单的方法，该方法根据输出文件名的扩展名自动检测栅格图像的保存格式：

```
bool bSaveState = pRasSvcs-><span class="hljs-keyword">saveRasterImage</span>(pOutputImage, outputFileName);
if (!bSaveState)
    throw <span class="hljs-keyword">OdError</span>(eFileWriteError);
```

### 访问栅格图像像素

在本文中，我们将使用以下湖面波浪的栅格图像：

[![](/files/images/blog/2017-02-02-pic1.png)](/files/images/blog/2017-02-02-pic1.png)

对于本系列文章中描述的栅格图像实验，我们需要图像四个角的像素颜色。为了访问图像像素，OdGiRasterImage 提供了两个版本的 scanLines 方法。第一个（直接）扫描线访问方法并非所有类型的栅格图像都支持，因为并非所有图像都包含兼容的像素数组。因此，我们首先必须检查是否可以对这种栅格图像使用优化的扫描线访问：

```
<span class="hljs-title">ODCOLORREF</span> inputColors[4];
if (pInputImage-><span class="hljs-keyword">scanLines</span>())
{
    const <span class="hljs-title">OdUInt8</span> *pPixels = pInputImage-><span class="hljs-keyword">scanLines</span>();
    inputColors[0] = <span class="hljs-keyword">ODRGB</span>(pPixels[0], pPixels[1], pPixels[2]); // Bottom-left corner
    pPixels += (pInputImage-><span class="hljs-keyword">pixelWidth</span>() - 1) * 3;
    inputColors[1] = <span class="hljs-keyword">ODRGB</span>(pPixels[0], pPixels[1], pPixels[2]); // Bottom-right corner
    pPixels = pInputImage-><span class="hljs-keyword">scanLines</span>() + (pInputImage-><span class="hljs-keyword">scanLineSize</span>() * (pInputImage-><span class="hljs-keyword">pixelHeight</span>() - 1));
    inputColors[2] = <span class="hljs-keyword">ODRGB</span>(pPixels[0], pPixels[1], pPixels[2]); // Top-left corner
    pPixels += (pInputImage-><span class="hljs-keyword">pixelWidth</span>() - 1) * 3;
    inputColors[3] = <span class="hljs-keyword">ODRGB</span>(pPixels[0], pPixels[1], pPixels[2]); // Top-right corner
}
```

在此示例中（如果优化的像素访问器返回非空数据指针），我们将左下、右下、左上和右上像素颜色存储在 inputColors 数组中。请注意，在 Teigha 内部，栅格图像扫描线是从下到上存储的，因此 scanLines 方法返回的指针指向图像的底部扫描线。

如果栅格图像不提供直接扫描线访问器，我们始终可以使用另一个版本的 scanLines 方法，该方法将像素数组复制到中间的用户定义数组中。此方法支持所有类型的栅格图像：

```
if (!pInputImage->scanLines())
{
    <span class="hljs-title">OdUInt8Array</span> scanLine;
    scanLine.<span class="hljs-keyword">resize</span>(pInputImage-><span class="hljs-keyword">scanLineSize</span>());
    pInputImage-><span class="hljs-keyword">scanLines</span>(scanLine.<span class="hljs-keyword">asArrayPtr</span>(), 0);
    inputColors[0] = <span class="hljs-keyword">ODRGB</span>(scanLine[0], scanLine[1], scanLine[2]); // Bottom-left corner
    inputColors[1] = <span class="hljs-keyword">ODRGB</span>(scanLine[(pInputImage-><span class="hljs-keyword">pixelWidth</span>() - 1) * 3 + 0], // Bottom-right corner
                     scanLine[(pInputImage-><span class="hljs-keyword">pixelWidth</span>() - 1) * 3 + 1],
                     scanLine[(pInputImage-><span class="hljs-keyword">pixelWidth</span>() - 1) * 3 + 2]);
    pInputImage-><span class="hljs-keyword">scanLines</span>(scanLine.<span class="hljs-keyword">asArrayPtr</span>(), pInputImage-><span class="hljs-keyword">pixelHeight</span>() - 1);
    inputColors[2] = <span class="hljs-keyword">ODRGB</span>(scanLine[0], scanLine[1], scanLine[2]); // Top-left corner
    inputColors[3] = <span class="hljs-keyword">ODRGB</span>(scanLine[(pInputImage-><span class="hljs-keyword">pixelWidth</span>() - 1) * 3 + 0], // Top-right corner
                     scanLine[(pInputImage-><span class="hljs-keyword">pixelWidth</span>() - 1) * 3 + 1],
                     scanLine[(pInputImage-><span class="hljs-keyword">pixelWidth</span>() - 1) * 3 + 2]);
}
```

在此示例中，我们将第一条（底部）和最后一条（顶部）扫描线复制到中间数组中，并将它们的第一个和最后一个像素颜色复制到 inputColors 数组中。

## 今天就开始行动

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

[免费试用](https://www.opendesign.com/cn/free-trial)
