ラスター画像ラッパーは、元のラスター画像を修正することなく、ラスター画像データを修正する方法を提供します。各ラスター画像ラッパーは、元の画像へのスマートポインタを格納し、元の画像から任意のデータを取得し、修正の有無にかかわらずそれを返すことができます。実際、ラスター画像ラッパーを使用することで、マルチパス画像処理のためのコンベアを構築できます。
ラスター画像ラッパーを使用したラスター画像作成の簡素化
ラスター画像ラッパーを使用して、本シリーズのパート2「ゼロからのラスター画像作成」で説明したGeneratedRasterImageクラスを簡素化できます。入力画像から一部のデータを使用するため、GeneratedRasterImageクラスをOdGiRasterImageの代わりにOdGiRasterImageWrapperクラスから継承し、ファイルから読み込む入力ラスター画像をこのラスター画像ラッパーの元の画像として設定するだけです。
class GeneratedRasterImage : public OdGiRasterImageWrapper
{
protected:
OdUInt32 m_pixW, m_pixH;
ODCOLORREF m_cornerColors[4];
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);
}
public:
virtual OdUInt32 pixelWidth() const { return m_pixW; }
virtual OdUInt32 pixelHeight() const { return m_pixH; }
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);
}
}
GeneratedRasterImage() : m_pixW(1), m_pixH(1) {}
void configureImage(OdUInt32 nWidth, OdUInt32 nHeight, const OdGiRasterImage *pOriginal, const ODCOLORREF *pColors)
{
setOriginal(pOriginal);
m_pixW = nWidth; m_pixH = nHeight;
for (int i = 0; i < 4; i++)
m_cornerColors[i] = pColors[i];
}
};
OdSmartPtr<GeneratedRasterImage> pImage = OdRxObjectImpl<GeneratedRasterImage>::createObject();
pImage->configureImage(256, 256, pInputImage, inputColors);
pOutputImage = pImage;
新しいバージョンのコードでは、OdGiRasterImageインターフェースからの純粋仮想メソッドの実装やスタブの追加などは必要ありません。デフォルトでは、OdGiRasterImageWrapperクラスはすべてのラスター画像インターフェースメソッドを実装し、元のラスター画像からラスター画像データをリダイレクトします。この例では、生成されたラスター画像の寸法を返すpixelWidth/pixelHeightメソッドと、元のラスター画像からのピクセルではなく生成された画像のピクセルを返すscanLinesメソッドのみをオーバーライドします。ピクセル形式やその他の画像プロパティは元のラスター画像から返されます。
画像処理ラッパーの作成
ラスターイメージラッパーを使用すると、OdGiRasterImageインターフェース機能の最小限の実装で、あらゆる種類のイメージモディファイア、エフェクトなどを作成できます。この種のTeigha機能を示すために、以下に、元のラスターイメージのピクセル色の強度を変更して、水面に円が浮かんでいるような視覚効果を作成するイメージモディファイアを示します。
class RasterImageWrapperEx : public OdGiRasterImageWrapper
{
protected:
void increaseIntensity(OdUInt8 &color, double intensity) const
{
intensity = intensity * color;
if (intensity > 255.0) intensity = 255.0;
if (intensity < 0.0) intensity = 0.0;
color = (OdUInt8)intensity;
}
void processPixel(OdUInt32 x, OdUInt32 y, OdUInt8 *pOutput) const
{
const OdGeVector2d imageCenter(original()->pixelWidth() / 2, original()->pixelHeight() / 2);
const double maxLength = imageCenter.length();
const double lengthFromCenter = (OdGeVector2d(x, y) - imageCenter).length();
// Define noise level parameters
const double frequency = 50.0 / OdaPI;
const double intensity = 0.5;
// Compute noise level
const double noiseLevel = (cos((lengthFromCenter / maxLength) * frequency) + 1.0) * intensity + intensity;
// Apply noise level to pixel color
increaseIntensity(pOutput[0], noiseLevel);
increaseIntensity(pOutput[1], noiseLevel);
increaseIntensity(pOutput[2], noiseLevel);
}
public:
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);
original()->scanLines(pScanLine, i);
for (OdUInt32 j = 0; j < original()->pixelWidth(); j++, pScanLine += 3)
processPixel(j, i, pScanLine);
}
}
RasterImageWrapperEx() {}
};
このラスターイメージラッパーは、scanLinesメソッドを実装して元のイメージからピクセルを取得し、各イメージピクセルに対してprocessPixelメソッドを呼び出して、その色にコサインノイズを適用するだけです。この実装にはメンバーがなく、すべてのコサインノイズパラメータは例を簡素化するためにハードコードされています。
これで、ラスターイメージモディファイアの新しいインスタンスを作成し、生成されたラスターイメージをオリジナルとして設定し、さらなる処理のためにラスターイメージモディファイアのスマートポインタを保持できます。
OdSmartPtr<RasterImageWrapperEx> pImage = OdRxObjectImpl<RasterImageWrapperEx>::createObject();
pImage->setOriginal(pOutputImage);
pOutputImage = pImage;
最後に、このシリーズのパート1にある「ファイルへのラスターイメージの保存」のコードを使用して、生成されたラスターイメージを保存し、結果のファイルを確認できます。
定義済みラスターイメージラッパー
GiRasterWrappers.hヘッダーファイルには、Teighaベースのプロジェクトのどこでも使用できる、一連の定義済みラスターイメージラッパーが含まれています。
最も単純な定義済みラスターイメージラッパーの1つは、上下反転ラスターイメージトランスフォーマーです。これは、1行のコードを使用して画像処理コンベアにアタッチできます。
pOutputImage = OdGiUpsideDownRasterTransformer::createObject(pOutputImage);
画像のスキャンラインを単に逆順で返すため、結果として画像が上下反転して表示されます。
同様に、左右反転画像トランスフォーマー (OdGiLeftToRightRasterTransformer クラス) を使用して、画像スキャンラインのピクセルを逆順に反転させることができます。
OdGiInversionRasterTransformer は、元のラスター画像のピクセルカラーを反転するために使用できます。
pOutputImage = OdGiInversionRasterTransformer::createObject(pOutputImage);
元のラスター画像に反転した色を含むパレットが含まれている場合、それ以外の場所では画像のピクセルカラーが反転されます。
OdGiGrayscaleRasterTransformer は、ラスター画像内の色をグレースケールに変換します。
pOutputImage = OdGiGrayscaleRasterTransformer::createObject(pOutputImage);
このラッパーを使用した後の最終画像は、グレーの濃淡のみを含みます。
OdGiMonochromaticRasterTransformer は、ラスター画像の色をモノクロームカラー (白黒のみ) に変換するために使用できます。
pOutputImage = OdGiMonochromaticRasterTransformer::createObject(pOutputImage, 127);
このラスター画像修飾子には、暗い色と明るい色の間のピクセルカラー強度制限を設定するために使用できる追加パラメーター「しきい値」が含まれています。デフォルト (範囲の中央) のしきい値で生成された最終画像:
結論
例に従って、5つの画像修飾子を使用して最終的なモノクロラスター画像を生成しました。最終的なファイル保存中のラスターサービスは、最後のラスター画像ラッパーの scanLines メソッドを呼び出すことにより、ラスター画像ラッパー間の scanLines メソッド呼び出しのチェーンを開始します。まず、GeneratedRasterImage クラスが初期グラデーションピクセルを返し、次に RasterImageWrapperEx がグラデーション画像に水円の効果を追加します。次に、scanLines メソッドは、画像スキャンラインのミラーリング、画像カラーの反転、画像カラーのグレースケールへの変換、そして最後にモノクロカラー効果の適用という一連の処理を呼び出します。この画像処理チェーンでのメモリ使用量は最小限です。なぜなら、ラスター画像ラッパーはピクセルのコピーを保存しないからです。画像修飾子を適用しても、初期ラスター画像のどのパラメーターも変更されません。最終的なラスター画像は、どのAPIからも OdGiRasterImage インターフェースとして認識されるため、ファイルから読み込んだ元のラスター画像と同様に、変更されたラスター画像をどこでも使用できます。