| 订阅 | 在线投稿
分享
 
 
 

C#图像处理之-给你的图片打上LOGO

2008-12-13 08:23:56 编辑來源:互联网 国际版 评论
 
 
本文为【C#图像处理之-给你的图片打上LOGO】的汉字拼音对照版显示拼音
  zuotupianchuliruanjiankendinghuiyudaozheyangdexuqiuruhebayizhangtupianfangzailingyizhangtupianshangbiruzaidatupianzhongdashanggongsihuogerendeLogodengdeng

  qishiyuanlihenjiandanjiashewomenyouyizhang 800 * 600 dedatupian(Bitmap b0)xiangzai(10,10)deweizhishangdashangLogo(Bitmap b1)Logotupiandaxiaoshi 150 * 30henjiandanwomenyidatupiande(10,10)weizhizuoweiqishiweizhizuoyige150 * 30 dejuxingbaLogotupianzhenggetihuanzhegejuxing

  laoguijuhuanshiyongBitmapDatalaibangzhuwomenshixianzhegegongnengview plaincopy to clipboardprint?

  // quyidatu(X,Y)weiqidian,w * h dejuxingquyu

  BitmapData srcData = b0.LockBits(new Rectangle(X,Y,w,h),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb);

  

  // quzhenggeLogo

  BitmapData dstData = b1.LockBits(new Rectangle(0,0,w,h),ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

  

  unsafe

  {

  byte* pIn = (byte*)srcData.Scan0.ToPointer();

  byte* pLogo = (byte*)dstData.Scan0.ToPointer();

  

  for (int y = 0; y < h; y++)

  {

  for (int x = 0; x < w; x++)

  {

  

  // fuzhiLogotudexiangsu

  pIn[0] = (byte)pLogo[0];

  pIn[1] = (byte)pLogo[1];

  pIn[2] = (byte)pLogo[2];

  

  pIn += 3;

  pLogo += 3;

  }

  

  pIn += srcData.Stride - w * 3;

  pLogo += dstData.Stride - w * 3;

  }

  

  b0.UnlockBits(srcData);

  b1.UnlockBits(dstData);

  }

  // quyidatu(X,Y)weiqidian,w * h dejuxingquyu

  BitmapData srcData = b0.LockBits(new Rectangle(X,Y,w,h),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb);

  // quzhenggeLogo

  BitmapData dstData = b1.LockBits(new Rectangle(0,0,w,h),ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

  unsafe

  {

  byte* pIn = (byte*)srcData.Scan0.ToPointer();

  byte* pLogo = (byte*)dstData.Scan0.ToPointer();

  for (int y = 0; y < h; y++)

  {

  for (int x = 0; x < w; x++)

  {

  // fuzhiLogotudexiangsu

  pIn[0] = (byte)pLogo[0];

  pIn[1] = (byte)pLogo[1];

  pIn[2] = (byte)pLogo[2];

  pIn += 3;

  pLogo += 3;

  }

  pIn += srcData.Stride - w * 3;

  pLogo += dstData.Stride - w * 3;

  }

  b0.UnlockBits(srcData);

  b1.UnlockBits(dstData);

  }zheyangweitupiandaLogodegongnengjiushixianledangranhuankeyiyoubiedefangfabiruyongBitBltzhegeAPIhanshuhuozhe使shiyongGDI+deDrawImagehanshu

  danzheyangyougexiaowentiLogoquyuyongyuanshigejuxingjiaruwodeLogoshigeyuanxingzhixiwangzaidatushangchuxianyuanxingdeLogoerbushizhengkuaijuxingnayougairuheshixianne

  zhegewentiqishikeyizheyanglijiewomenrangLogodebeijingbiantoumingersuoweitoumingjiushiliangzhangtupiandiejiashishangcengtupiantoumingquyuzhongdexiangsurengran使shiyongxiacengtudexiangyingxiangsulaidaitidanzaiRGBmoshixiabingmeiyoutoumingzhegegainianwomendetaolundouzaiyongPixelFormat.Format24bppRgbPixelFormat.Format32bppArgbzhongdeAlphafenliangzhichitoumingduyinciwomenxuyaozijiguidingyizhongyansefanshizhegeyansededouzuoweitoumingchuli

  biruwomendeLogoshiheididenamejiuzhidingheisezuoweitoumingse

  xiugaisuanfayehenjiandanfanshiyudaoLogotuzhongxiangsuyanseshiheisedangranzheshigeshenshukeyizijigaidejiuyongdatuxiangyingweizhideyanselaidaitifouzehuanshi使shiyongLogodexiangsusexiamianshisuanfaview plaincopy to clipboardprint?

  // yinweiyoukenengyaohuixiesuoyiyuantude ImageLockMode zhecishi ReadWrite

  BitmapData srcData = b0.LockBits(new Rectangle(X, Y, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

  

  BitmapData dstData = b1.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

  

  unsafe

  {

  byte* pIn = (byte*)srcData.Scan0.ToPointer();

  byte* pLogo = (byte*)dstData.Scan0.ToPointer();

  

  for (int y = 0; y < h; y++)

  {

  for (int x = 0; x < w; x++)

  {

  

  // panduandangqiandianshifoutoumingse

  // qudedangqianse

  Color c = Color.FromArgb(pLogo[2], pLogo[1], pLogo[0]);

  if (!ColorIsSimilar(c, TransColor, delta))

  {

  // bushitoumingseb0dangqianweizhideyanseyongb1duiyingweizhidelaidaiti

  pIn[0] = (byte)pLogo[0];

  pIn[1] = (byte)pLogo[1];

  pIn[2] = (byte)pLogo[2];

  }

  

  pIn += 3;

  pLogo += 3;

  }

  

  pIn += srcData.Stride - w * 3;

  pLogo += dstData.Stride - w * 3;

  }

  

  b0.UnlockBits(srcData);

  b1.UnlockBits(dstData);

  }

  // yinweiyoukenengyaohuixiesuoyiyuantude ImageLockMode zhecishi ReadWrite

  BitmapData srcData = b0.LockBits(new Rectangle(X, Y, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

  BitmapData dstData = b1.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

  unsafe

  {

  byte* pIn = (byte*)srcData.Scan0.ToPointer();

  byte* pLogo = (byte*)dstData.Scan0.ToPointer();

  for (int y = 0; y < h; y++)

  {

  for (int x = 0; x < w; x++)

  {

  // panduandangqiandianshifoutoumingse

  // qudedangqianse

  Color c = Color.FromArgb(pLogo[2], pLogo[1], pLogo[0]);

  if (!ColorIsSimilar(c, TransColor, delta))

  {

  // bushitoumingseb0dangqianweizhideyanseyongb1duiyingweizhidelaidaiti

  pIn[0] = (byte)pLogo[0];

  pIn[1] = (byte)pLogo[1];

  pIn[2] = (byte)pLogo[2];

  }

  pIn += 3;

  pLogo += 3;

  }

  pIn += srcData.Stride - w * 3;

  pLogo += dstData.Stride - w * 3;

  }

  b0.UnlockBits(srcData);

  b1.UnlockBits(dstData);

  }womenzaishangmiandesuanfazhongchuxianlelingyigexiaosuanfapanduanyanseC0,C1shifouxiangdengdangranruguolianggeyansedeRGBfenliangdouxiangdengnajiukendingshixiangdengledankaolvdaorongchafangmiandeyinsuwomenxuyaoyigegenglinghuodesuanfa

  womenzhidaoyigeyanseyouRGBsangefenliangzuchengmeigefenliangquzhi[0255]dezhengshuzheyangrenyiyigeyansedoushizhegeyouxiankongjianzhongdeyigedianlianggeyansedexiangsidushifouzaifazhifanweineidewentizuijiandandesiluyejiukeyirenweiqiuzhengkongjianliangdiandejulishifouzaifazhifanweinei

  kongjianliangdianjuligongshir2 = (x0-x1)2 + (y0-y1)2 + (z0-z1)2

  xiamianshiwodesuanfaview plaincopy to clipboardprint?

  /// <summary>

  /// yanseshifoujinsi

  /// </summary>

  /// <param name="c0">yanse0</param>

  /// <param name="c1">yanse1</param>

  /// <param name="delta">rongcha</param>

  /// <returns>shi/fou</returns>

  public static bool ColorIsSimilar(Color c0, Color c1, int delta)

  {

  int r0, r1, g0, g1, b0, b1;

  

  r0 = c0.R;

  r1 = c1.R;

  

  g0 = c0.G;

  g1 = c1.G;

  

  b0 = c0.B;

  b1 = c1.B;

  

  if ((r0-r1)*(r0-r1) + (g0-g1) * (g0-g1) + (b0-b1) * (b0-b1) <= delta * delta)

  {

  return true;

  }

  else

  {

  return false;

  }

  

  }

  /// <summary>

  /// yanseshifoujinsi

  /// </summary>

  /// <param name="c0">yanse0</param>

  /// <param name="c1">yanse1</param>

  /// <param name="delta">rongcha</param>

  /// <returns>shi/fou</returns>

  public static bool ColorIsSimilar(Color c0, Color c1, int delta)

  {

  int r0, r1, g0, g1, b0, b1;

  r0 = c0.R;

  r1 = c1.R;

  g0 = c0.G;

  g1 = c1.G;

  b0 = c0.B;

  b1 = c1.B;

  if ((r0-r1)*(r0-r1) + (g0-g1) * (g0-g1) + (b0-b1) * (b0-b1) <= delta * delta)

  {

  return true;

  }

  else

  {

  return false;

  }

  }zuihouzailaikankanyizhongqingkuangwomenxuyaoLogobantoumingdechengxianmaosishuiyinyangdexiaoguoyouleshangmianliangzhongchulitupiandejingyanbunanrenshidaodatub0dezhidingquyuzhongxuyaohunheyuanshixiangsuheLogotupianb1xiangsuhoudexinxiangsutianchong

  bunanxiangxiangxinxiangsuzhiyinggaijieheledatuheLogotuliangfangmianyinsudeLogotuyuetoumingdatushoudeyingxiangyuexiaosuoyizheliwomenkeyicaiyongjiaquanpingyundefangfalaidedaohunhehoudexinzhi

  xinzhi = 1 - butoumingdu%* datuxiangsuzhi + butoumingdu% * Logotuxiangsuzhi

  wanzhengdehanshuruxiaview plaincopy to clipboardprint?

  /// <summary>

  /// hebingliangzhangtupianzhichibutoumingduhetoumingse

  /// </summary>

  /// <param name="b0">tupianyi</param>

  /// <param name="b1">tupianer</param>

  /// <param name="X">qishizuobiaoX</param>

  /// <param name="Y">qishizuobiaoY</param>

  /// <param name="b1_alpha">tupianerdebutoumingdu</param>

  /// <param name="TransColor">beizuoweitoumingsechulideyanse</param>

  /// <param name="delta">toumingsederongcha</param>

  /// <returns>hebinghoudetupian</returns>

  public static Bitmap KiMerge(Bitmap b0, Bitmap b1, int X, int Y, int b1_alpha,Color TransColor,int delta)

  {

  if (b0.Equals(null) || b1.Equals(null))

  {

  return null;

  }

  

  int w0 = b0.Width;

  int h0 = b0.Height;

  

  int w1 = b1.Width;

  int h1 = b1.Height;

  

  int w, h;

  

  if (X + w1 > w0)

  {

  w = w0 - X;

  }

  else

  {

  w = w1;

  }

  

  if (Y + h1 > h0)

  {

  h = h0 - Y;

  }

  else

  {

  h = h1;

  }

  

  BitmapData srcData = b0.LockBits(new Rectangle(X, Y, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

  BitmapData dstData = b1.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

  

  unsafe

  {

  byte* pIn = (byte*)srcData.Scan0.ToPointer();

  byte* pLogo = (byte*)dstData.Scan0.ToPointer();

  

  for (int y = 0; y < h; y++)

  {

  for (int x = 0; x < w; x++)

  {

  

  // panduantoumingse

  Color c = Color.FromArgb(pLogo[2], pLogo[1], pLogo[0]);

  if (!ColorIsSimilar(c, TransColor, delta))

  {

  

  float bili = (float)b1_alpha / (float)255; // bushitoumingsejiaquanpingyun

  float inbili = 1.0f - bili;

  

  int r, g, b;

  

  b = (int)(pIn[0] * inbili + pLogo[0] * bili);

  g = (int)(pIn[1] * inbili + pLogo[1] * bili);

  r = (int)(pIn[2] * inbili + pLogo[2] * bili);

  

  pIn[0] = (byte)b;

  pIn[1] = (byte)g;

  pIn[2] = (byte)r;

  }

  pIn += 3;

  pLogo += 3;

  }

  

  pIn += srcData.Stride - w * 3;

  pLogo += dstData.Stride - w * 3;

  }

  

  b0.UnlockBits(srcData);

  b1.UnlockBits(dstData);

  }

  

  return b0;

  }

  /// <summary>

  /// hebingliangzhangtupianzhichibutoumingduhetoumingse

  /// </summary>

  /// <param name="b0">tupianyi</param>

  /// <param name="b1">tupianer</param>

  /// <param name="X">qishizuobiaoX</param>

  /// <param name="Y">qishizuobiaoY</param>

  /// <param name="b1_alpha">tupianerdebutoumingdu</param>

  /// <param name="TransColor">beizuoweitoumingsechulideyanse</param>

  /// <param name="delta">toumingsederongcha</param>

  /// <returns>hebinghoudetupian</returns>

  public static Bitmap KiMerge(Bitmap b0, Bitmap b1, int X, int Y, int b1_alpha,Color TransColor,int delta)

  {

  if (b0.Equals(null) || b1.Equals(null))

  {

  return null;

  }

  int w0 = b0.Width;

  int h0 = b0.Height;

  int w1 = b1.Width;

  int h1 = b1.Height;

  int w, h;

  if (X + w1 > w0)

  {

  w = w0 - X;

  }

  else

  {

  w = w1;

  }

  if (Y + h1 > h0)

  {

  h = h0 - Y;

  }

  else

  {

  h = h1;

  }

  BitmapData srcData = b0.LockBits(new Rectangle(X, Y, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

  BitmapData dstData = b1.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

  unsafe

  {

  byte* pIn = (byte*)srcData.Scan0.ToPointer();

  byte* pLogo = (byte*)dstData.Scan0.ToPointer();

  for (int y = 0; y < h; y++)

  {

  for (int x = 0; x < w; x++)

  {

  // panduantoumingse

  Color c = Color.FromArgb(pLogo[2], pLogo[1], pLogo[0]);

  if (!ColorIsSimilar(c, TransColor, delta))

  {

  float bili = (float)b1_alpha / (float)255; // bushitoumingsejiaquanpingyun

  float inbili = 1.0f - bili;

  int r, g, b;

  b = (int)(pIn[0] * inbili + pLogo[0] * bili);

  g = (int)(pIn[1] * inbili + pLogo[1] * bili);

  r = (int)(pIn[2] * inbili + pLogo[2] * bili);

  pIn[0] = (byte)b;

  pIn[1] = (byte)g;

  pIn[2] = (byte)r;

  }

  pIn += 3;

  pLogo += 3;

  }

  pIn += srcData.Stride - w * 3;

  pLogo += dstData.Stride - w * 3;

  }

  b0.UnlockBits(srcData);

  b1.UnlockBits(dstData);

  }

  return b0;

  }dangranfangfayouhenduozhelizhishicongyuanlidejiaoduchanshuleyixiawodeguandianshuiyougenghaodefangfaqingrangwozhidao原文
 
 
做图片处理软件,肯定会遇到这样的需求:如何把一张图片放在另一张图片上,比如在大图片中打上公司或个人的Logo等等。 其实原理很简单。假设我们有一张 800 * 600 的大图片(Bitmap b0),想在(10,10)的位置上打上Logo(Bitmap b1),Logo图片大小是 150 * 30。很简单,我们以大图片的(10,10)位置作为起始位置,做一个150 * 30 的矩形,把Logo图片整个替换这个矩形。 老规矩,还是用BitmapData来帮助我们实现这个功能。view plaincopy to clipboardprint? // 取以大图(X,Y)为起点,w * h 的矩形区域 BitmapData srcData = b0.LockBits(new Rectangle(X,Y,w,h),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb); // 取整个Logo BitmapData dstData = b1.LockBits(new Rectangle(0,0,w,h),ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); unsafe { byte* pIn = (byte*)srcData.Scan0.ToPointer(); byte* pLogo = (byte*)dstData.Scan0.ToPointer(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { // 复制Logo图的像素 pIn[0] = (byte)pLogo[0]; pIn[1] = (byte)pLogo[1]; pIn[2] = (byte)pLogo[2]; pIn += 3; pLogo += 3; } pIn += srcData.Stride - w * 3; pLogo += dstData.Stride - w * 3; } b0.UnlockBits(srcData); b1.UnlockBits(dstData); } // 取以大图(X,Y)为起点,w * h 的矩形区域 BitmapData srcData = b0.LockBits(new Rectangle(X,Y,w,h),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb); // 取整个Logo BitmapData dstData = b1.LockBits(new Rectangle(0,0,w,h),ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); unsafe { byte* pIn = (byte*)srcData.Scan0.ToPointer(); byte* pLogo = (byte*)dstData.Scan0.ToPointer(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { // 复制Logo图的像素 pIn[0] = (byte)pLogo[0]; pIn[1] = (byte)pLogo[1]; pIn[2] = (byte)pLogo[2]; pIn += 3; pLogo += 3; } pIn += srcData.Stride - w * 3; pLogo += dstData.Stride - w * 3; } b0.UnlockBits(srcData); b1.UnlockBits(dstData); }这样,为图片打Logo的功能就实现了。当然,还可以有别的方法,比如用BitBlt这个API函数,或者使用GDI+的DrawImage函数。 但这样有个小问题,Logo区域永远是个矩形。假如我的Logo是个圆形,只希望在大图上出现圆形的Logo而不是整块矩形,那又该如何实现呢? 这个问题其实可以这样理解:我们让Logo的背景变透明。而所谓透明,就是两张图片叠加时,上层图片“透明”区域中的像素,仍然使用下层图的相应像素来代替。但在RGB模式下,并没有“透明”这个概念(我们的讨论都在用PixelFormat.Format24bppRgb,PixelFormat.Format32bppArgb中的Alpha分量支持“透明度”),因此我们需要自己规定一种颜色,凡是这个颜色的,都作为“透明”处理。 比如,我们的Logo是黑底的,那么就指定黑色作为透明色。 修改算法也很简单,凡是遇到Logo图中像素颜色是黑色(当然这是个参数,可以自己改)的,就用大图相应位置的颜色来代替,否则还是使用Logo的像素色。下面是算法:view plaincopy to clipboardprint? // 因为有可能要回写,所以原图的 ImageLockMode 这次是 ReadWrite BitmapData srcData = b0.LockBits(new Rectangle(X, Y, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData dstData = b1.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); unsafe { byte* pIn = (byte*)srcData.Scan0.ToPointer(); byte* pLogo = (byte*)dstData.Scan0.ToPointer(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { // 判断当前点是否透明色 // 取得当前色 Color c = Color.FromArgb(pLogo[2], pLogo[1], pLogo[0]); if (!ColorIsSimilar(c, TransColor, delta)) { // 不是透明色,b0当前位置的颜色用b1对应位置的来代替 pIn[0] = (byte)pLogo[0]; pIn[1] = (byte)pLogo[1]; pIn[2] = (byte)pLogo[2]; } pIn += 3; pLogo += 3; } pIn += srcData.Stride - w * 3; pLogo += dstData.Stride - w * 3; } b0.UnlockBits(srcData); b1.UnlockBits(dstData); } // 因为有可能要回写,所以原图的 ImageLockMode 这次是 ReadWrite BitmapData srcData = b0.LockBits(new Rectangle(X, Y, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData dstData = b1.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); unsafe { byte* pIn = (byte*)srcData.Scan0.ToPointer(); byte* pLogo = (byte*)dstData.Scan0.ToPointer(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { // 判断当前点是否透明色 // 取得当前色 Color c = Color.FromArgb(pLogo[2], pLogo[1], pLogo[0]); if (!ColorIsSimilar(c, TransColor, delta)) { // 不是透明色,b0当前位置的颜色用b1对应位置的来代替 pIn[0] = (byte)pLogo[0]; pIn[1] = (byte)pLogo[1]; pIn[2] = (byte)pLogo[2]; } pIn += 3; pLogo += 3; } pIn += srcData.Stride - w * 3; pLogo += dstData.Stride - w * 3; } b0.UnlockBits(srcData); b1.UnlockBits(dstData); }我们在上面的算法中出现了另一个小算法,判断颜色C0,C1是否相等。当然如果两个颜色的RGB分量都相等那就肯定是相等了,但考虑到容差方面的因素,我们需要一个更灵活的算法。 我们知道,一个颜色由RGB三个分量组成,每个分量取值[0,255]的整数。这样,任意一个颜色都是这个有限空间中的一个点。两个颜色的“相似度”是否在阀值范围内的问题,最简单的思路也就可以认为求证空间两点的距离是否在阀值范围内。 空间两点距离公式:r2 = (x0-x1)2 + (y0-y1)2 + (z0-z1)2 下面是我的算法。view plaincopy to clipboardprint? /// <summary> /// 颜色是否近似 /// </summary> /// <param name="c0">颜色0</param> /// <param name="c1">颜色1</param> /// <param name="delta">容差</param> /// <returns>是/否</returns> public static bool ColorIsSimilar(Color c0, Color c1, int delta) { int r0, r1, g0, g1, b0, b1; r0 = c0.R; r1 = c1.R; g0 = c0.G; g1 = c1.G; b0 = c0.B; b1 = c1.B; if ((r0-r1)*(r0-r1) + (g0-g1) * (g0-g1) + (b0-b1) * (b0-b1) <= delta * delta) { return true; } else { return false; } } /// <summary> /// 颜色是否近似 /// </summary> /// <param name="c0">颜色0</param> /// <param name="c1">颜色1</param> /// <param name="delta">容差</param> /// <returns>是/否</returns> public static bool ColorIsSimilar(Color c0, Color c1, int delta) { int r0, r1, g0, g1, b0, b1; r0 = c0.R; r1 = c1.R; g0 = c0.G; g1 = c1.G; b0 = c0.B; b1 = c1.B; if ((r0-r1)*(r0-r1) + (g0-g1) * (g0-g1) + (b0-b1) * (b0-b1) <= delta * delta) { return true; } else { return false; } }最后再来看看一种情况。我们需要Logo半透明的呈现,貌似水印样的效果。有了上面两种处理图片的经验,不难认识到,大图b0的指定区域中需要混合原始像素和Logo图片b1像素后的新像素填充。 不难想象,新像素值应该结合了大图和Logo图两方面因素的。Logo图越透明,大图受的影响越小。所以这里我们可以采用加权平均的方法来得到混合后的新值。 新值 = (1 - 不透明度%)* 大图像素值 + 不透明度% * Logo图像素值 完整的函数如下:view plaincopy to clipboardprint? /// <summary> /// 合并两张图片,支持不透明度和透明色 /// </summary> /// <param name="b0">图片一</param> /// <param name="b1">图片二</param> /// <param name="X">起始坐标X</param> /// <param name="Y">起始坐标Y</param> /// <param name="b1_alpha">图片二的不透明度</param> /// <param name="TransColor">被作为透明色处理的颜色</param> /// <param name="delta">透明色的容差</param> /// <returns>合并后的图片</returns> public static Bitmap KiMerge(Bitmap b0, Bitmap b1, int X, int Y, int b1_alpha,Color TransColor,int delta) { if (b0.Equals(null) || b1.Equals(null)) { return null; } int w0 = b0.Width; int h0 = b0.Height; int w1 = b1.Width; int h1 = b1.Height; int w, h; if (X + w1 > w0) { w = w0 - X; } else { w = w1; } if (Y + h1 > h0) { h = h0 - Y; } else { h = h1; } BitmapData srcData = b0.LockBits(new Rectangle(X, Y, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData dstData = b1.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); unsafe { byte* pIn = (byte*)srcData.Scan0.ToPointer(); byte* pLogo = (byte*)dstData.Scan0.ToPointer(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { // 判断透明色 Color c = Color.FromArgb(pLogo[2], pLogo[1], pLogo[0]); if (!ColorIsSimilar(c, TransColor, delta)) { float bili = (float)b1_alpha / (float)255; // 不是透明色,加权平均 float inbili = 1.0f - bili; int r, g, b; b = (int)(pIn[0] * inbili + pLogo[0] * bili); g = (int)(pIn[1] * inbili + pLogo[1] * bili); r = (int)(pIn[2] * inbili + pLogo[2] * bili); pIn[0] = (byte)b; pIn[1] = (byte)g; pIn[2] = (byte)r; } pIn += 3; pLogo += 3; } pIn += srcData.Stride - w * 3; pLogo += dstData.Stride - w * 3; } b0.UnlockBits(srcData); b1.UnlockBits(dstData); } return b0; } /// <summary> /// 合并两张图片,支持不透明度和透明色 /// </summary> /// <param name="b0">图片一</param> /// <param name="b1">图片二</param> /// <param name="X">起始坐标X</param> /// <param name="Y">起始坐标Y</param> /// <param name="b1_alpha">图片二的不透明度</param> /// <param name="TransColor">被作为透明色处理的颜色</param> /// <param name="delta">透明色的容差</param> /// <returns>合并后的图片</returns> public static Bitmap KiMerge(Bitmap b0, Bitmap b1, int X, int Y, int b1_alpha,Color TransColor,int delta) { if (b0.Equals(null) || b1.Equals(null)) { return null; } int w0 = b0.Width; int h0 = b0.Height; int w1 = b1.Width; int h1 = b1.Height; int w, h; if (X + w1 > w0) { w = w0 - X; } else { w = w1; } if (Y + h1 > h0) { h = h0 - Y; } else { h = h1; } BitmapData srcData = b0.LockBits(new Rectangle(X, Y, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData dstData = b1.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); unsafe { byte* pIn = (byte*)srcData.Scan0.ToPointer(); byte* pLogo = (byte*)dstData.Scan0.ToPointer(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { // 判断透明色 Color c = Color.FromArgb(pLogo[2], pLogo[1], pLogo[0]); if (!ColorIsSimilar(c, TransColor, delta)) { float bili = (float)b1_alpha / (float)255; // 不是透明色,加权平均 float inbili = 1.0f - bili; int r, g, b; b = (int)(pIn[0] * inbili + pLogo[0] * bili); g = (int)(pIn[1] * inbili + pLogo[1] * bili); r = (int)(pIn[2] * inbili + pLogo[2] * bili); pIn[0] = (byte)b; pIn[1] = (byte)g; pIn[2] = (byte)r; } pIn += 3; pLogo += 3; } pIn += srcData.Stride - w * 3; pLogo += dstData.Stride - w * 3; } b0.UnlockBits(srcData); b1.UnlockBits(dstData); } return b0; }当然方法有很多,这里只是从原理的角度阐述了一下我的观点,谁有更好的方法请让我知道。
󰈣󰈤
日版宠物情人插曲《Winding Road》歌词

日版宠物情人2017的插曲,很带节奏感,日语的,女生唱的。 最后听见是在第8集的时候女主手割伤了,然后男主用嘴帮她吸了一下,插曲就出来了。 歌手:Def...

兄弟共妻,我成了他们夜里的美食

老钟家的两个儿子很特别,就是跟其他的人不太一样,魔一般的执着。兄弟俩都到了要结婚的年龄了,不管自家老爹怎么磨破嘴皮子,兄弟俩说不娶就不娶,老父母为兄弟两操碎了心...

网络安全治理:国家安全保障的主要方向是打击犯罪,而不是处置和惩罚受害者

来源:中国青年报 新的攻击方法不断涌现,黑客几乎永远占据网络攻击的上风,我们不可能通过技术手段杜绝网络攻击。国家安全保障的主要方向是打击犯罪,而不是处置和惩罚...

 
 
 
>>返回首页<<
 为你推荐
 
 
 
 转载本文
 UBB代码 HTML代码
复制到剪贴板...
 
 
 热帖排行
 
黑色魅力_醉人的美
梦幻蒙眬_如痴如醉
北京的“尖叫”建筑
高天上流云
 
 
王朝网络微信公众号
微信扫码关注本站公众号wangchaonetcn
 
  免责声明:本文仅代表作者个人观点,与王朝网络无关。王朝网络登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
©2005- 王朝网络 版权所有