NScripterで使われるような、左半分が絵本体で右側がマスクな画像を1枚の透過PNGに戻す処理。
関連
-http://d.hatena.ne.jp/yune_kotomi/20071110/1194698984
-http://d.hatena.ne.jp/ukiya/20071111/1194729728
#code(Csharp,nooutline){{
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
namespace MaskTest {
class Program {
static void Main(string[] args) {
foreach (string file in Directory.GetFiles(".", "*.bmp")) {
//元画像読み込み
Bitmap srcBmp = (Bitmap)Bitmap.FromFile(file);
//元画像を32bppに変換
Bitmap tmpBmp = new Bitmap(srcBmp.Width, srcBmp.Height, PixelFormat.Format32bppArgb);
Graphics tmpG = Graphics.FromImage(tmpBmp);
tmpG.DrawImage(srcBmp, new Rectangle(0, 0, tmpBmp.Width, tmpBmp.Height),
new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), GraphicsUnit.Pixel);
//左側画像作成
Bitmap dstBmp = new Bitmap(srcBmp.Width / 2, srcBmp.Height, PixelFormat.Format32bppArgb);
Graphics dstG = Graphics.FromImage(dstBmp);
dstG.DrawImage(srcBmp, new Rectangle(0, 0, dstBmp.Width, dstBmp.Height),
0, 0, srcBmp.Width / 2, srcBmp.Height, GraphicsUnit.Pixel);
//右側画像作成
Bitmap mskBmp = new Bitmap(srcBmp.Width / 2, srcBmp.Height, PixelFormat.Format32bppArgb);
Graphics mskG = Graphics.FromImage(mskBmp);
mskG.DrawImage(srcBmp, new Rectangle(0, 0, dstBmp.Width, dstBmp.Height),
srcBmp.Width/2 , 0, srcBmp.Width / 2, srcBmp.Height, GraphicsUnit.Pixel);
//マスク処理
Mask(dstBmp, mskBmp,true);
//保存
dstBmp.Save(file.ToLower().Replace(".bmp", ".png"), ImageFormat.Png);
}
}
public unsafe static void Mask(Bitmap srcBmp,Bitmap mskBmp,bool isNegate){
int w = srcBmp.Width;
int h = srcBmp.Height;
if (mskBmp.Width != w || mskBmp.Height != h) {
throw new ArgumentException("bitmap size unmatch");
}
if (srcBmp.PixelFormat != PixelFormat.Format32bppArgb ||
mskBmp.PixelFormat != PixelFormat.Format32bppArgb) {
throw new ArgumentException("bitmap must be 32bpp");
}
//ビットマップをロックしてポインタを取得
BitmapData srcData = srcBmp.LockBits(new Rectangle(0, 0, w, h),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
BitmapData mskData = mskBmp.LockBits(new Rectangle(0, 0, w, h),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte* pSrcBase = (byte*)srcData.Scan0.ToPointer();
byte* pMskBase = (byte*)mskData.Scan0.ToPointer();
//ピクセル毎にマスク処理
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
byte* pSrc = pSrcBase + (y * w + x) * 4;
byte* pMsk = pMskBase + (y * w + x) * 4;
//mask RGB-> src A 罠:Argbといいつつ格納の順番は逆のBGRA
int rgbsum = (*(pMsk + 0) + *(pMsk + 1) + *(pMsk + 2))/3;
if (isNegate) {
rgbsum = 255 - rgbsum;
}
*(pSrc + 3) = (byte)rgbsum;
}
}
//アンロック
srcBmp.UnlockBits(srcData);
mskBmp.UnlockBits(mskData);
}
}
}
}}