半月前,回了个关于双色渐变填充矩形的帖(见http://topic.csdn.net/u/20091030/12/74cc8a21-1b63-4051-818c-d4c871b292f6.html),事后,闲来无事,于是,按那个回帖的思路,写了个任意角度双色渐变填充矩形的函数,感觉不错,比GDI+渐变填充速度快不少,又将其扩展为任意角度多色(ARGB)渐变填充矩形、文字,后来灵机一动,不如把这个由简入繁、由浅入深写的代码放到BLOG中,即可实现代码分享,满足实用要求,又可给初学者一个学习参考,于是先后发布了3篇BLOG文章:《实现任意角度渐变填充(一) -- 双色渐变填充矩形
实现任意角度渐变填充(一) -- 多色渐变填充矩形
实现任意角度渐变填充(三) -- 多色渐变填充文字》    文章写完后,却又发现,其实这些代码完全可以改编扩展为其它任意封闭图形,包括Windows区域的填充,但究竟是写成一个个单独的函数好,还是归并为一个类(例如一个扩展填充功能的TCanvas派生类)好呢?这2种方式各有优缺点,因此拿不定主意,特地在此征求各位的意见,当然,也包括对上述文章中代码的改进意见。   以下贴上上述文章中的2张界面截图:4个不同角度多色填充矩形的拼图:3色和5色填充文字(已消除锯齿):

解决方案 »

  1.   

    写成一个单独的函数,做成DLL比较好~~
      

  2.   

    虽然depphi和vb都不懂,这个一定要支持。
      

  3.   

    我倒是想知道如何能用GDI+实现PS中的角度渐变。
      

  4.   

    什么意思?GDI+的渐变填充与PS有什么不同?
      

  5.   


    你看过Photoshop中的渐变填充没,那个效果用GDI+要如何实现呢》
      

  6.   

    是角度渐变填充,Photoshop中渐变有很多中方式的
      

  7.   

    一直矩形4个顶点颜色红、蓝、绿、黄  如何填充矩形颜色 使其均匀过度的Graphics中的方法是什么?
      

  8.   

    回楼主:
    带alpha通道的透明色的渐变色彩的产生方法:起始色彩为rgbaFrom, 终点色彩为rgbato,中间某个偏移的色彩rgba应该为:
    rgbaf.premultiply;
    rgbat.premultiply;
    假设偏移比例为s(1> s> 0)
    r = rf + s * (rt - rf)
    g = gf + s * (gt - gf)
    b = bf + s * (bt - bf)
    a = af + s * (at - af)rgba.demutiply;楼主可以用带透明度的色彩试一下,然后和gdi+作一下对比。支持下楼主的这种共享行为~
      

  9.   

    关键在画刷。
    GradientPathBrush.SetSurroundColors.
    这个画刷的路径得是一个矩形。当然更复杂的也可以,这个是最简单的方法。
      

  10.   


    错了,应该是PathGradientBrush.呵呵~~~
      

  11.   

    我的文章中的填充颜色是ARGB型的,支持透明度色彩填充
      

  12.   

    GDI+可能没办法实现PS的那种角度渐变,但是自己编程实现是可以的,并非太难,它实际上是径向渐变的一种变形。但是这种角度渐变方式同线性渐变、径向渐变、路径渐变等相比较,实用性不是很大。
      

  13.   


    我意思是但凡带透明度的色彩的渐变,需要在渐变之前premutiply一下,然后按照比例去计算渐变色彩,计算完成之后,还要把结果demutiply一下。否则的话,rgb3个通道的色彩会偏低,导致视觉上看起来偏暗色。
      

  14.   


      begin  
        // p^ = alpha * (color2 - color1) + color1   
        p.Alpha := ((I * (c2.Alpha - c1.Alpha)) shr 24) +c1.Alpha;   
        p.Red := ((I * (c2.Red - c1.Red)) shr 24) + c1.Red;   
        p.Green := ((I * (c2.Green - c1.Green)) shr 24) + c1.Green;   
        p.Blue := ((I * (c2.Blue - c1.Blue)) shr 24) + c1.Blue;   
        Inc(I, Delta);   
        Inc(p);   
      end;   貌似你在预先生成渐变色彩的时候,没有premutiply。且计算完成之后没有demutiply。
    建议你用透明色渐变填充下,然后比对下gdi+的效果。
      

  15.   

      首先感谢你的指教,不过恕我愚昧,我始终没明白你的premutiply是什么意思,我在对ARGB颜色的处理上是通过了2次处理的:
      第一次是预生成渐变色彩缓冲区,也就是你引用的这段代码,其中的I就是你所说的偏移比例,只不过是扩大了0x1000000后用定点数处理的,这与你的r = rf + s * (rt - rf) 是完全一样的;
      第二次是在实际填充时处理的,以双色填充为例,如果起始填充色或者结束填充的Alpha分量不等于255,其填充代码为:
      // Alpha填充   
      if Data.AlphaBlend then  
      begin  
        for y := 1 to Data.Height do  
        begin  
          x0 := y0;   
          p := p0;   
          for x := 1 to Data.Width do  
          begin  
            c := ColorBuf[x0 shr 8]; // 取颜色缓冲区的颜色  
            p.Alpha := ((c.Alpha * (c.Alpha - p.Alpha)) shr 8) + p.Alpha;   
            p.Red := ((c.Alpha * (c.Red - p.Red)) shr 8) + p.Red;   
            p.Green := ((c.Alpha * (c.Green - p.Green)) shr 8) + p.Green;   
            p.Blue := ((c.Alpha * (c.Blue - p.Blue)) shr 8) + p.Blue;   
            Inc(Integer(p), Data.ScanDelta);   
            Inc(x0, Data.xDelta);   
          end;   
          Inc(Integer(p0), Data.ScanOffset);   
          Inc(y0, Data.yDelta);   
        end;   
      end
    这上面的代码算法也是与你说的r = rf + s * (rt - rf)是一致的啊,不知还需要在哪里再premutiply
      

  16.   

    to winnuke:
    按照你的建议,我用GDI+和我写的多色填充代码进行了比较,下面是比较的代码和截图图,为了方便比较,分别用45度和135度画成对称的,左边是GDI+画的,右边是我的填充代码画的,都是用128的Alpha。
    var
      g: TGpGraphics;
      brush: TGpLinearGradientBrush;
    begin
      brush := TGpLinearGradientBrush.Create(GpRect(0, 0, 200, 200), 0, 0, 45);
      Brush.SetInterpolationColors([$80008000, $80FFFF00, $80FF0000, $800000FF, $80FFA500], [0, 0.25, 0.5, 0.75, 1]);
      g := TGpGraphics.Create(Canvas.Handle);
      g.FillRectangle(brush, 0, 0, 200, 200);
      g.Free;
      LinearGradientFillRect(Canvas, Rect(200, 0, 400, 200),
        [$80008000, $80FFFF00, $80FF0000, $800000FF, $80FFA500], [0, 0.25, 0.5, 0.75, 1], 135);
    end;
      

  17.   


    你把interpolate color换成alpha值不一样的再试一下。比如ARGB(200, 10, 200, 50)到ARGB(60, 200, 10, 20)就是渐变色之间的透明度也有差距的那种。
      

  18.   

    谢谢winnuke,用不同的Alpha颜色渐变出来的颜色确实是颜色偏暗,需要改进,再次感谢你。
      

  19.   

    premultiply实际上就是得到三个颜色通道在当前alpha值下的有效值(视觉上的比重)
    demultiply就是从有效值反向取到运算值的过程。这里渐变注重的应该是视觉效果上的渐变,也就是有效值的渐变。如果采用运算值当作有效值来渐变,其效果肯定会在预期的视觉效果之外。
      

  20.   

    不好意思,最近很少上CSDN,所以来晚了
      

  21.   

    学习了hardworkhttp://www.爱艺购.com
      

  22.   

    访问你的博客总是提示,你访问的页面上的脚本会导致interent运行变慢,  怎么搞的啊?