なんとなく、ふわっと・・

写真と画像処理関係とひとりごとをなんとなく書き溜めていきたい

Crop と SmoothEdge

2008-03-24 19:02:31 | C#(Graphics)

旧ブログからのコード移植、その3。

Crop は、Mask をつかって、指定色領域を指定の色許容度で透明にする。
SmoothEdge は、Crop された画像のエッジのアルファ値を傾斜をかけて滑らかにする。



全コードをしめす。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using ImageUtils;

namespace CropSmoothEdge
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public static bool Crop(ref Bitmap bmp, Bitmap mask, Color maskColor,
                                                      int tolerance)
        {
            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

            if (mask.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

            if ((tolerance < 0) | (tolerance > 100))
                return false;

            int w = bmp.Width;
            int h = bmp.Height;

            if ((w != mask.Width) | (h != mask.Height)) return false;

            byte redSmall = ImgUtils.AdjustByte(maskColor.R - tolerance);
            byte redLarge = ImgUtils.AdjustByte(maskColor.R + tolerance);
            byte greenSmall = ImgUtils.AdjustByte(maskColor.G - tolerance);
            byte greenLarge = ImgUtils.AdjustByte(maskColor.G + tolerance);
            byte blueSmall = ImgUtils.AdjustByte(maskColor.B - tolerance);
            byte blueLarge = ImgUtils.AdjustByte(maskColor.B + tolerance);

            Bitmap tmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);

            Graphics g = Graphics.FromImage(tmp);
            g.DrawImageUnscaled(bmp, 0, 0);
            g.Dispose();

            BmpProc24 src = new BmpProc24(mask);
            BmpProc32 dst = new BmpProc32(tmp);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                {
                    src.SetXY(x, y);
                    if ((src.R < redSmall) | (src.R > redLarge) |
                        (src.G < greenSmall) | (src.G > greenLarge) |
                        (src.B < blueSmall) | (src.B > blueLarge)) continue;

                    dst[x, y, eRGB.a] = 0;
                }

            ImgUtils.CallDispose(dst, src, bmp);

            bmp = tmp;

            return true;
        }

        public static bool SmoothEdge(ref Bitmap bmp, int zone)
        {
            if (bmp.PixelFormat != PixelFormat.Format32bppArgb)
                return false;

            int w = bmp.Width;
            int h = bmp.Height;

            Bitmap tmp = bmp.Clone() as Bitmap;

            ImgUtils.Blur32(ref bmp, zone);

            BmpProc32 src = new BmpProc32(tmp);
            BmpProc32 dst = new BmpProc32(bmp);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                {
                    src.SetXY(x, y);
                    dst.SetXY(x, y);

                    if (dst.A == 0) continue;

                    if (src.A == dst.A)
                    {
                        dst.R = src.R;
                        dst.G = src.G;
                        dst.B = src.B;
                    }
                }

            ImgUtils.CallDispose(dst, src, tmp);

            return true;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Bitmap bmp = new Bitmap(@"c:\Home\ImgWork\CropSample.png");

            Bitmap mask = new Bitmap(@"c:\Home\ImgWork\CropMask.png");

            Bitmap haikei = new Bitmap(@"c:\Home\ImgWork\CropBack.png");

            Color maskColor = mask.GetPixel(50, 50);

            Crop(ref bmp, mask, maskColor, 40);            

            Graphics g = Graphics.FromImage(haikei);
            g.DrawImage(bmp, -160, 0, bmp.Width, bmp.Height);
            SmoothEdge(ref bmp, 2);
            g.DrawImage(bmp, 230, 0, bmp.Width, bmp.Height);
            g.Dispose();

            g = this.CreateGraphics();
            g.DrawImageUnscaled(haikei, 5, 35);
            Clipboard.SetImage(haikei);
            g.Dispose();

            haikei.Dispose();
            mask.Dispose();
            bmp.Dispose();
        }
    }
}


CropSample



CropMask



CropBack



Comments (4)    この記事についてブログを書く
« crane #1 | TOP | N »

4 Comments

コメント日が  古い順  |   新しい順
ななちゃんだいかつやく (myugaru)
2008-03-24 19:33:55
こんばんわ、最近不調な私です^^;
でも今日は愚痴じゃないのでご安心ください。
ネットで色々画像処理を辿ってちょっとおもしろい作品を見つけました。
http://www.hikarigekijo.com/s064066.html
作者さんにコンタクトとってもいいんですけど、
どうせならどういう仕組みか想像するのも楽しいかなって思って。
この光線ってやつを実行するととても懐かしいような動きをするのです。
でもどうやっているのかイマイチわからなくて。
どうやら素直にGDIだけで書いてるようです。
DirectXとか3Dとかに頼らなくても十分迫力ある動きのある画面ができるんだなあってちょっと紹介したくなったんです。よかったら見てみてください。
junkiさんももし時間あったら動きに挑戦してほしいです。
私のほうは最近さっぱりですがもうちょっとしたら気合入れようと思ってます(笑
返信する
光線 (junki)
2008-03-24 20:18:49

myugaru さん、こんばんは。

この光線セーバ、すんごいですね。

MSDOS のときから、当時はスクリーンセーバとは言わなかったのですが、こういう作品がたくさん出て、わたしも買った覚えがあります。Windows になって、スクリーンセーバに特化して、すばらしい作品を発表している集団がありました。まだ、Win32 の前、Win16 で WinG というライブラリを使って、当時の描画機能を最大限使ってゲームやスクリーンセーバを発表していました。

この、光線ですが、たしかにワープを連想させますね。動画ではなく、一本の線に集中してみてみると、反時計周りになるようにずらしながら線を引いているだけのようです。

なにより色の変化のグラデーションの仕方が美しいですね。動きの速さは、まさに名人芸ですね。ほかのもDLして遊んでみます。

コメント、ありがとうございます。
返信する
Unknown (shockatz)
2008-03-24 21:33:55
C#のソースコードにビックリ!
マスクカラーの部分を、しっかりアンチエイリアス処理で合成しているところなんか感動ものです。
こういう数学的な処理は、Photoshopにはできない芸当ですね。
幾何学的な処理とかに使うと面白そうですね!
返信する
アンチエイリアス (junki)
2008-03-25 00:48:00

shockatz さん、こんばんは。

Crop はともかく、SmoothEdge は一晩考えました。手でマスクをつくっていたので、どうしてもはめ込むときギザギザが目立ちます。それで、アンチエイリアスのようにするためにはエッジ部分のアルファ値に傾斜をかければいいことはすぐにわかりますが、どうしたらエッジだけそのように操作できるか悩みました。ソースを見ればすぐ分かりますように、アルファ値ごとぼかしてしまうと、エッジ部分が透明部分に滲み出すことと、不透明部分のアルファ値はぼかしに影響受けないことを利用すると、ほんとに簡単に傾斜部分だけ処理を残すことに成功しました。コードは、だからもの凄く簡単ですよね。

コメント、ありがとうございます。

返信する

post a comment