none
谁有图片改色的代码? RRS feed

  • 问题

  • 将某颜色替换成某颜色,比如红色替换成白色,红色的RGB值不是固定的,因为有深有浅.

    希望有效率高点的算法,SetPixel这个效率比较低,耗时比较长,用ColorMatrix或BitmapData效率高点,但是自己不会写,网上找不到,诶.

    2010年9月3日 4:10

答案

  • 用BitmapData, 得到位图RGBA分量的数据,然后按照你的逻辑去改变其中的值:

        #region Create8BitsBitmapFrom24BitsBitmap
        public static Bitmap Create8BitsBitmapFrom24BitsBitmap(Bitmap srcImage, byte bValue)
        {
          Bitmap dstImage = new Bitmap(srcImage.Width, srcImage.Height, PixelFormat.Format8bppIndexed);
          //锁定位图对象至内存,存为24位,自动将表示透明度的8位舍去
          BitmapData srcData = srcImage.LockBits(new Rectangle(0, 0, srcImage.Width, srcImage.Height),
            ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
          BitmapData dstData = dstImage.LockBits(new Rectangle(0, 0, srcImage.Width, srcImage.Height),
            ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
          unsafe
          {
            //void*指针表示可以指向任意类型的指针
            byte* pSource = (byte*)srcData.Scan0.ToPointer();//获取第一行开头的地址
            byte* pTarget = (byte*)dstData.Scan0.ToPointer();//同上
            for (int y = 0; y < srcData.Height; y++) //位图对象扫描的行数
            {
              for (int x = 0; x < srcData.Width; x++) //位图对象扫描的列数
              {
                //pSource是指向字节的指针。三个字节表示红,绿,蓝三个通道,共24位。
                int value = (pSource[0] * 721 + pSource[1] * 7154 + pSource[2] * 2125) / 10000; //计算该像素的灰度
                pTarget[0] = (value > bValue) ? byte.MaxValue : byte.MinValue; //如果灰度大于指定的灰度值,则灰度图的该像素设置为最大值,否则设置为最小值
                pSource += 3; //彩图向后走三个字节,查看下一个像素
                pTarget++;//灰度图向后走一个字节
              }
    
              //Stride一定是4的倍数,因为内存存在补齐的问题
              //取得下一行的首地址
              pSource += srcData.Stride - srcData.Width * 3;
              pTarget += dstData.Stride - dstData.Width;
            }
          }
          srcImage.UnlockBits(srcData);
          dstImage.UnlockBits(dstData);
          return dstImage;
        }
    
    2010年9月9日 3:22
  • 你好:

    这有一个例子你可以参考一下。

    17   public void ProcessRequest(HttpContext context)
    18   {
    19     imagepath += context.Request.QueryString["imagename"] + ".jpg";//获得图片名称
    20     Image image; //图片类
    21     //如果文件夹内存在图片context.Request.MapPath获得物理地址
    22     if (File.Exists(context.Request.MapPath(imagepath)))
    23     {
    24       image = Image.FromFile(context.Request.MapPath(imagepath));//将图片内容放到image对象
    25       Graphics g = Graphics.FromImage(image); //获得Graphics 对象
    26       Image watermark = Image.FromFile(context.Request.MapPath(waterimage));//将水印图片放入watermark 对象
    27       //关于透明度(使用颜色矩阵)
    28       float[][] nArray ={ new float[] {1, 0, 0, 0, 0},
    29       new float[] {0, 1, 0, 0, 0},
    30       new float[] {0, 0, 1, 0, 0},
    31       new float[] {0, 0, 0,alpha , 0},
    32       new float[] {0, 0, 0, 0, 1}};
    33       ColorMatrix colormatrix = new ColorMatrix(nArray);
    34       ImageAttributes attributes = new ImageAttributes();
    35       attributes.SetColorMatrix(colormatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
    36       g.DrawImage(watermark, new Rectangle(image.Width - watermark.Width, image.Height - watermark.Height,
    37 watermark.Width, watermark.Height), 0, 0, watermark.Width, watermark.Height, GraphicsUnit.Pixel, attributes);//在图片指定坐标处放入一个矩形图片内容为水印图片
    38       g.Dispose();
    39       watermark.Dispose();
    40     }
    41     else
    42     {
    43       image = Image.FromFile(context.Request.MapPath(defaultimage));//如果不存在图片就输出defaultimage。
    44     }
    45     context.Response.ContentType = "image/jpeg";//输出图片的类型
    46     image.Save(context.Response.OutputStream, ImageFormat.Jpeg);//将图片存入输出流
    47     image.Dispose();
    48     context.Response.End();
    49   }
    

    http://kb.cnblogs.com/a/1507866/
    http://www.cnblogs.com/freeliver54/archive/2008/09/10/1288301.html

    希望对你有所帮助。

    2010年9月6日 7:00
    版主

全部回复

  • 你好:

    这有一个例子你可以参考一下。

    17   public void ProcessRequest(HttpContext context)
    18   {
    19     imagepath += context.Request.QueryString["imagename"] + ".jpg";//获得图片名称
    20     Image image; //图片类
    21     //如果文件夹内存在图片context.Request.MapPath获得物理地址
    22     if (File.Exists(context.Request.MapPath(imagepath)))
    23     {
    24       image = Image.FromFile(context.Request.MapPath(imagepath));//将图片内容放到image对象
    25       Graphics g = Graphics.FromImage(image); //获得Graphics 对象
    26       Image watermark = Image.FromFile(context.Request.MapPath(waterimage));//将水印图片放入watermark 对象
    27       //关于透明度(使用颜色矩阵)
    28       float[][] nArray ={ new float[] {1, 0, 0, 0, 0},
    29       new float[] {0, 1, 0, 0, 0},
    30       new float[] {0, 0, 1, 0, 0},
    31       new float[] {0, 0, 0,alpha , 0},
    32       new float[] {0, 0, 0, 0, 1}};
    33       ColorMatrix colormatrix = new ColorMatrix(nArray);
    34       ImageAttributes attributes = new ImageAttributes();
    35       attributes.SetColorMatrix(colormatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
    36       g.DrawImage(watermark, new Rectangle(image.Width - watermark.Width, image.Height - watermark.Height,
    37 watermark.Width, watermark.Height), 0, 0, watermark.Width, watermark.Height, GraphicsUnit.Pixel, attributes);//在图片指定坐标处放入一个矩形图片内容为水印图片
    38       g.Dispose();
    39       watermark.Dispose();
    40     }
    41     else
    42     {
    43       image = Image.FromFile(context.Request.MapPath(defaultimage));//如果不存在图片就输出defaultimage。
    44     }
    45     context.Response.ContentType = "image/jpeg";//输出图片的类型
    46     image.Save(context.Response.OutputStream, ImageFormat.Jpeg);//将图片存入输出流
    47     image.Dispose();
    48     context.Response.End();
    49   }
    

    http://kb.cnblogs.com/a/1507866/
    http://www.cnblogs.com/freeliver54/archive/2008/09/10/1288301.html

    希望对你有所帮助。

    2010年9月6日 7:00
    版主
  • 用BitmapData, 得到位图RGBA分量的数据,然后按照你的逻辑去改变其中的值:

        #region Create8BitsBitmapFrom24BitsBitmap
        public static Bitmap Create8BitsBitmapFrom24BitsBitmap(Bitmap srcImage, byte bValue)
        {
          Bitmap dstImage = new Bitmap(srcImage.Width, srcImage.Height, PixelFormat.Format8bppIndexed);
          //锁定位图对象至内存,存为24位,自动将表示透明度的8位舍去
          BitmapData srcData = srcImage.LockBits(new Rectangle(0, 0, srcImage.Width, srcImage.Height),
            ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
          BitmapData dstData = dstImage.LockBits(new Rectangle(0, 0, srcImage.Width, srcImage.Height),
            ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
          unsafe
          {
            //void*指针表示可以指向任意类型的指针
            byte* pSource = (byte*)srcData.Scan0.ToPointer();//获取第一行开头的地址
            byte* pTarget = (byte*)dstData.Scan0.ToPointer();//同上
            for (int y = 0; y < srcData.Height; y++) //位图对象扫描的行数
            {
              for (int x = 0; x < srcData.Width; x++) //位图对象扫描的列数
              {
                //pSource是指向字节的指针。三个字节表示红,绿,蓝三个通道,共24位。
                int value = (pSource[0] * 721 + pSource[1] * 7154 + pSource[2] * 2125) / 10000; //计算该像素的灰度
                pTarget[0] = (value > bValue) ? byte.MaxValue : byte.MinValue; //如果灰度大于指定的灰度值,则灰度图的该像素设置为最大值,否则设置为最小值
                pSource += 3; //彩图向后走三个字节,查看下一个像素
                pTarget++;//灰度图向后走一个字节
              }
    
              //Stride一定是4的倍数,因为内存存在补齐的问题
              //取得下一行的首地址
              pSource += srcData.Stride - srcData.Width * 3;
              pTarget += dstData.Stride - dstData.Width;
            }
          }
          srcImage.UnlockBits(srcData);
          dstImage.UnlockBits(dstData);
          return dstImage;
        }
    
    2010年9月9日 3:22