[解決済み] フォトショップで2つの画像をブレンドする方法とは?[クローズド]
2023-04-11 05:47:55
質問
私のアプリケーションで同じ効果を再現するために、Photoshopがどのように2つの画像を混ぜ合わせるのか、どなたか説明していただけませんか。
どのように解決するのですか?
Photoshop は、画像 B の対応するピクセルに対して画像 A の各ピクセルでブレンド処理を実行することにより、2 つの画像をブレンドします。各ピクセルは、複数のチャンネルからなる色です。RGB ピクセルで作業していると仮定すると、各ピクセルのチャンネルは、赤、緑、青になります。2 つのピクセルをブレンドするには、それぞれのチャンネルをブレンドします。
Photoshopの各ブレンドモードで行われるブレンド操作は、以下のマクロに集約されます。
#define ChannelBlend_Normal(A,B) ((uint8)(A))
#define ChannelBlend_Lighten(A,B) ((uint8)((B > A) ? B:A))
#define ChannelBlend_Darken(A,B) ((uint8)((B > A) ? A:B))
#define ChannelBlend_Multiply(A,B) ((uint8)((A * B) / 255))
#define ChannelBlend_Average(A,B) ((uint8)((A + B) / 2))
#define ChannelBlend_Add(A,B) ((uint8)(min(255, (A + B))))
#define ChannelBlend_Subtract(A,B) ((uint8)((A + B < 255) ? 0:(A + B - 255)))
#define ChannelBlend_Difference(A,B) ((uint8)(abs(A - B)))
#define ChannelBlend_Negation(A,B) ((uint8)(255 - abs(255 - A - B)))
#define ChannelBlend_Screen(A,B) ((uint8)(255 - (((255 - A) * (255 - B)) >> 8)))
#define ChannelBlend_Exclusion(A,B) ((uint8)(A + B - 2 * A * B / 255))
#define ChannelBlend_Overlay(A,B) ((uint8)((B < 128) ? (2 * A * B / 255):(255 - 2 * (255 - A) * (255 - B) / 255)))
#define ChannelBlend_SoftLight(A,B) ((uint8)((B < 128)?(2*((A>>1)+64))*((float)B/255):(255-(2*(255-((A>>1)+64))*(float)(255-B)/255))))
#define ChannelBlend_HardLight(A,B) (ChannelBlend_Overlay(B,A))
#define ChannelBlend_ColorDodge(A,B) ((uint8)((B == 255) ? B:min(255, ((A << 8 ) / (255 - B)))))
#define ChannelBlend_ColorBurn(A,B) ((uint8)((B == 0) ? B:max(0, (255 - ((255 - A) << 8 ) / B))))
#define ChannelBlend_LinearDodge(A,B)(ChannelBlend_Add(A,B))
#define ChannelBlend_LinearBurn(A,B) (ChannelBlend_Subtract(A,B))
#define ChannelBlend_LinearLight(A,B)((uint8)(B < 128)?ChannelBlend_LinearBurn(A,(2 * B)):ChannelBlend_LinearDodge(A,(2 * (B - 128))))
#define ChannelBlend_VividLight(A,B) ((uint8)(B < 128)?ChannelBlend_ColorBurn(A,(2 * B)):ChannelBlend_ColorDodge(A,(2 * (B - 128))))
#define ChannelBlend_PinLight(A,B) ((uint8)(B < 128)?ChannelBlend_Darken(A,(2 * B)):ChannelBlend_Lighten(A,(2 * (B - 128))))
#define ChannelBlend_HardMix(A,B) ((uint8)((ChannelBlend_VividLight(A,B) < 128) ? 0:255))
#define ChannelBlend_Reflect(A,B) ((uint8)((B == 255) ? B:min(255, (A * A / (255 - B)))))
#define ChannelBlend_Glow(A,B) (ChannelBlend_Reflect(B,A))
#define ChannelBlend_Phoenix(A,B) ((uint8)(min(A,B) - max(A,B) + 255))
#define ChannelBlend_Alpha(A,B,O) ((uint8)(O * A + (1 - O) * B))
#define ChannelBlend_AlphaF(A,B,F,O) (ChannelBlend_Alpha(F(A,B),A,O))
RGBの1つのピクセルをブレンドするには、次のようにします。
ImageTColorR = ChannelBlend_Glow(ImageAColorR, ImageBColorR);
ImageTColorB = ChannelBlend_Glow(ImageAColorB, ImageBColorB);
ImageTColorG = ChannelBlend_Glow(ImageAColorG, ImageBColorG);
ImageTColor = RGB(ImageTColorR, ImageTColorB, ImageTColorG);
特定の不透明度、例えば50%でブレンド操作を行いたい場合。
ImageTColorR = ChannelBlend_AlphaF(ImageAColorR, ImageBColorR, Blend_Subtract, 0.5F);
画像A、B、T(ターゲット)の画像データへのポインタがあれば、このマクロを使って3つのチャンネルすべてのブレンドを簡略化することができます。
#define ColorBlend_Buffer(T,A,B,M) (T)[0] = ChannelBlend_##M((A)[0], (B)[0]),
(T)[1] = ChannelBlend_##M((A)[1], (B)[1]),
(T)[2] = ChannelBlend_##M((A)[2], (B)[2])
そして、以下のRGBカラーブレンドマクロを導き出すことができます。
#define ColorBlend_Normal(T,A,B) (ColorBlend_Buffer(T,A,B,Normal))
#define ColorBlend_Lighten(T,A,B) (ColorBlend_Buffer(T,A,B,Lighten))
#define ColorBlend_Darken(T,A,B) (ColorBlend_Buffer(T,A,B,Darken))
#define ColorBlend_Multiply(T,A,B) (ColorBlend_Buffer(T,A,B,Multiply))
#define ColorBlend_Average(T,A,B) (ColorBlend_Buffer(T,A,B,Average))
#define ColorBlend_Add(T,A,B) (ColorBlend_Buffer(T,A,B,Add))
#define ColorBlend_Subtract(T,A,B) (ColorBlend_Buffer(T,A,B,Subtract))
#define ColorBlend_Difference(T,A,B) (ColorBlend_Buffer(T,A,B,Difference))
#define ColorBlend_Negation(T,A,B) (ColorBlend_Buffer(T,A,B,Negation))
#define ColorBlend_Screen(T,A,B) (ColorBlend_Buffer(T,A,B,Screen))
#define ColorBlend_Exclusion(T,A,B) (ColorBlend_Buffer(T,A,B,Exclusion))
#define ColorBlend_Overlay(T,A,B) (ColorBlend_Buffer(T,A,B,Overlay))
#define ColorBlend_SoftLight(T,A,B) (ColorBlend_Buffer(T,A,B,SoftLight))
#define ColorBlend_HardLight(T,A,B) (ColorBlend_Buffer(T,A,B,HardLight))
#define ColorBlend_ColorDodge(T,A,B) (ColorBlend_Buffer(T,A,B,ColorDodge))
#define ColorBlend_ColorBurn(T,A,B) (ColorBlend_Buffer(T,A,B,ColorBurn))
#define ColorBlend_LinearDodge(T,A,B) (ColorBlend_Buffer(T,A,B,LinearDodge))
#define ColorBlend_LinearBurn(T,A,B) (ColorBlend_Buffer(T,A,B,LinearBurn))
#define ColorBlend_LinearLight(T,A,B) (ColorBlend_Buffer(T,A,B,LinearLight))
#define ColorBlend_VividLight(T,A,B) (ColorBlend_Buffer(T,A,B,VividLight))
#define ColorBlend_PinLight(T,A,B) (ColorBlend_Buffer(T,A,B,PinLight))
#define ColorBlend_HardMix(T,A,B) (ColorBlend_Buffer(T,A,B,HardMix))
#define ColorBlend_Reflect(T,A,B) (ColorBlend_Buffer(T,A,B,Reflect))
#define ColorBlend_Glow(T,A,B) (ColorBlend_Buffer(T,A,B,Glow))
#define ColorBlend_Phoenix(T,A,B) (ColorBlend_Buffer(T,A,B,Phoenix))
そして、例としては
ColorBlend_Glow(TargetPtr, ImageAPtr, ImageBPtr);
フォトショップのブレンドモードの残りは、RGBをHLSに変換し、また元に戻すというものです。
#define ColorBlend_Hue(T,A,B) ColorBlend_Hls(T,A,B,HueB,LuminationA,SaturationA)
#define ColorBlend_Saturation(T,A,B) ColorBlend_Hls(T,A,B,HueA,LuminationA,SaturationB)
#define ColorBlend_Color(T,A,B) ColorBlend_Hls(T,A,B,HueB,LuminationA,SaturationB)
#define ColorBlend_Luminosity(T,A,B) ColorBlend_Hls(T,A,B,HueA,LuminationB,SaturationA)
#define ColorBlend_Hls(T,A,B,O1,O2,O3) {
float64 HueA, LuminationA, SaturationA;
float64 HueB, LuminationB, SaturationL;
Color_RgbToHls((A)[2],(A)[1],(A)[0], &HueA, &LuminationA, &SaturationA);
Color_RgbToHls((B)[2],(B)[1],(B)[0], &HueB, &LuminationB, &SaturationB);
Color_HlsToRgb(O1,O2,O3,&(T)[2],&(T)[1],&(T)[0]);
}
これらの関数は、RGBをHLSに変換する際に役に立ちます。
int32 Color_HueToRgb(float64 M1, float64 M2, float64 Hue, float64 *Channel)
{
if (Hue < 0.0)
Hue += 1.0;
else if (Hue > 1.0)
Hue -= 1.0;
if ((6.0 * Hue) < 1.0)
*Channel = (M1 + (M2 - M1) * Hue * 6.0);
else if ((2.0 * Hue) < 1.0)
*Channel = (M2);
else if ((3.0 * Hue) < 2.0)
*Channel = (M1 + (M2 - M1) * ((2.0F / 3.0F) - Hue) * 6.0);
else
*Channel = (M1);
return TRUE;
}
int32 Color_RgbToHls(uint8 Red, uint8 Green, uint8 Blue, float64 *Hue, float64 *Lumination, float64 *Saturation)
{
float64 Delta;
float64 Max, Min;
float64 Redf, Greenf, Bluef;
Redf = ((float64)Red / 255.0F);
Greenf = ((float64)Green / 255.0F);
Bluef = ((float64)Blue / 255.0F);
Max = max(max(Redf, Greenf), Bluef);
Min = min(min(Redf, Greenf), Bluef);
*Hue = 0;
*Lumination = (Max + Min) / 2.0F;
*Saturation = 0;
if (Max == Min)
return TRUE;
Delta = (Max - Min);
if (*Lumination < 0.5)
*Saturation = Delta / (Max + Min);
else
*Saturation = Delta / (2.0 - Max - Min);
if (Redf == Max)
*Hue = (Greenf - Bluef) / Delta;
else if (Greenf == Max)
*Hue = 2.0 + (Bluef - Redf) / Delta;
else
*Hue = 4.0 + (Redf - Greenf) / Delta;
*Hue /= 6.0;
if (*Hue < 0.0)
*Hue += 1.0;
return TRUE;
}
int32 Color_HlsToRgb(float64 Hue, float64 Lumination, float64 Saturation, uint8 *Red, uint8 *Green, uint8 *Blue)
{
float64 M1, M2;
float64 Redf, Greenf, Bluef;
if (Saturation == 0)
{
Redf = Lumination;
Greenf = Lumination;
Bluef = Lumination;
}
else
{
if (Lumination <= 0.5)
M2 = Lumination * (1.0 + Saturation);
else
M2 = Lumination + Saturation - Lumination * Saturation;
M1 = (2.0 * Lumination - M2);
Color_HueToRgb(M1, M2, Hue + (1.0F / 3.0F), &Redf);
Color_HueToRgb(M1, M2, Hue, &Greenf);
Color_HueToRgb(M1, M2, Hue - (1.0F / 3.0F), &Bluef);
}
*Red = (uint8)(Redf * 255);
*Blue = (uint8)(Bluef * 255);
*Green = (uint8)(Greenf * 255);
return TRUE;
}
主にこのトピックに関するより多くのリソースがあります。
関連
-
[解決済み] テスト
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] 家系図ソフトのサイクル
-
[解決済み] 簡単な面接問題が難しくなった:1~100の数字が与えられたとき、ちょうどk個の数字が欠けていることを見つけなさい。
-
[解決済み】画像処理。コカ・コーラ缶」認識のためのアルゴリズム改良
-
[解決済み】高放射能環境下で使用するアプリケーションのコンパイルについて
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み] [Solved] Error C1083: Cannot open include file: 'stdafx.h'
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較