游戏开发论坛

 找回密码
 立即注册
搜索
查看: 8416|回复: 8

用getpixel和setpixel实现混合加,效果达到了,就是慢得窗口

[复制链接]

8

主题

23

帖子

48

积分

注册会员

Rank: 2

积分
48
发表于 2012-9-22 10:24:00 | 显示全部楼层 |阅读模式
发现效率低下的原因好像主要是getpixel和setpixel函数,帮帮忙给个简单的优化方法至少在30帧以上的
void CBitImage::drawImageToAlpha( HDC hBufferDC,int nX, int nY, double fAlpha , COLORREF color)
{
        struct                ColorRGB
        {
                int                byRed;
                int                byGreen;
                int                byBlue;
        };
        COLORREF        nC1;        //源点颜色
        COLORREF        nC2;        //目标点颜色


        HDC                        hDC;        //缓冲hdc
        HBITMAP                m_hBitmapTmp;

        hDC = CreateCompatibleDC( m_hDC );
        m_hBitmapTmp = (HBITMAP)SelectObject( hDC, CreateCompatibleBitmap( m_hDC, m_nWidth, m_nHeight ) );
        ColorRGB sRGB[3];

        for ( int ni = 0; ni < m_nHeight; ni++ )
                for ( int nj = 0; nj < m_nWidth; nj++ )
                {
                        //背景图
       
                        nC1 =GetPixel( hBufferDC, nX + nj, nY + ni );
                       sRGB[0].byRed = GetRValue( nC1 );
                          sRGB[0].byGreen = GetGValue( nC1 );
                        sRGB[0].byBlue = GetBValue( nC1 );
                        //目标图
                        nC2 =GetPixel( m_hDC, nj, ni );
                        sRGB[1].byRed = GetRValue( nC2 );
                        sRGB[1].byGreen = GetGValue( nC2 );
                        sRGB[1].byBlue = GetBValue( nC2 );

                        if ( nC2==color )
                        {
                                SetPixel(hDC, nj, ni, nC1 );   //为透明色则不显示
                        }
                        else
                        {


         sRGB[2].byRed = (int)( sRGB[0].byRed+ sRGB[1].byRed );
                 sRGB[2].byGreen = (int)( sRGB[0].byGreen + sRGB[1].byGreen);
         sRGB[2].byBlue = (int)( sRGB[0].byBlue+ sRGB[1].byBlue);
                                  if(sRGB[2].byRed>255)
                                           sRGB[2].byRed=255;
                                  if(sRGB[2].byGreen>255)
                                           sRGB[2].byGreen=255;
                                   if(sRGB[2].byBlue>255)
                                          sRGB[2].byBlue=255;
               

                                SetPixel( hDC, nj, ni, RGB( sRGB[2].byRed, sRGB[2].byGreen, sRGB[2].byBlue ) );
                        }
                }
                BitBlt( hBufferDC, nX, nY, m_nWidth, m_nHeight, hDC, 0, 0, SRCCOPY );
}

11

主题

95

帖子

658

积分

高级会员

Rank: 4

积分
658
发表于 2012-9-22 10:39:00 | 显示全部楼层

Re:用getpixel和setpixel实现混合加,效果达到了,就是慢得

你是一个一个点的画在和hDC上,画完才copy到hBufferDC。那当然很慢啊,建议使用多线程试试!图片越大速度越慢!

8

主题

23

帖子

48

积分

注册会员

Rank: 2

积分
48
 楼主| 发表于 2012-9-22 10:44:00 | 显示全部楼层

Re: 用getpixel和setpixel实现混合加,效果达到了,就是慢得

不光是这个setpixel上面循环里面的getpixel影响也很大,除了多线程还有其他方法吗?

8

主题

23

帖子

48

积分

注册会员

Rank: 2

积分
48
 楼主| 发表于 2012-9-22 10:51:00 | 显示全部楼层

Re:用getpixel和setpixel实现混合加,效果达到了,就是慢得

我在网上下载了一个别人的delphi源码实现的alpha混合,和我的程序结构几乎是一样的,为什么他得基本上不占cpu啊!!!!!!!!!
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Image2: TImage;
    Image3: TImage;
    BitBtn1: TBitBtn;
    Image4: TImage;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    procedure BitBtn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
var i, j, k: integer;
  beta: integer;
  r, g, b, r1, g1, b1, r2, g2, b2: integer;
begin
  for i := 0 to image1.height - 1 do
  begin
    for j := 0 to image1.Width - 1 do
    begin
      //alpha ֵ
      r := GetRValue(image2.Canvas.Pixels[i, j]);
      //g := GetGValue(image1.Canvas.Pixels[i,j]);
      //b := GetBValue(image1.Canvas.Pixels[i,j]);

      r1 := GetRValue(image1.Canvas.Pixels[i, j]);
      g1 := GetGValue(image1.Canvas.Pixels[i, j]);
      b1 := GetBValue(image1.Canvas.Pixels[i, j]);

      r2 := GetRValue(image3.Canvas.Pixels[i, j]);
      g2 := GetGValue(image3.Canvas.Pixels[i, j]);
      b2 := GetBValue(image3.Canvas.Pixels[i, j]);

      r2 := (r1 * r + r2 * (255 - r)) div 255;
      g2 := (g1 * r + g2 * (255 - r)) div 255;
      b2 := (b1 * r + b2 * (255 - r)) div 255;

      image4.Canvas.Pixels[i, j] := RGB(r2, g2, b2);
    end;
  end;
end;

end.

50

主题

236

帖子

454

积分

中级会员

Rank: 3Rank: 3

积分
454
发表于 2012-9-22 12:28:00 | 显示全部楼层

Re: 用getpixel和setpixel实现混合加,效果达到了,就是慢得

楼主把需求讲一下吧,
因为看你的代码,可以感觉到,你的方式不对.
对于gdi,我很少使用BitBlt、DrawText、SelectObject这些接口,因为太麻烦,而且效率不高,
更好的方式是直接用C++数组管理这些像素,你可以随心所欲实现你想达到各类特效,最后一次性把这些像素flip到屏幕上(SetDIBitsToDevice())即可.

看看这个半透明不规则窗口,或许你会感兴趣.

8

主题

23

帖子

48

积分

注册会员

Rank: 2

积分
48
 楼主| 发表于 2012-9-22 12:56:00 | 显示全部楼层

Re: 用getpixel和setpixel实现混合加,效果达到了,就是慢得

就是把一个24位的技能特效图片和另一个背景图片的像素进行饱和加实现显示特效的目的

         sRGB[2].byRed = (int)( sRGB[0].byRed+ sRGB[1].byRed );
         sRGB[2].byGreen = (int)( sRGB[0].byGreen + sRGB[1].byGreen);
         sRGB[2].byBlue = (int)( sRGB[0].byBlue+ sRGB[1].byBlue);
   if(sRGB[2].byRed>255)
   sRGB[2].byRed=255;
   if(sRGB[2].byGreen>255)
   sRGB[2].byGreen=255;
   if(sRGB[2].byBlue>255)
   sRGB[2].byBlue=255;
只是效率太低,你的意思是自己读取ddb位图然后对像素数组直接操作最后在显示出来吗?为什么我发那个delphi写得代码和我的差不多怎么他得cpu占用率那么低啊???我现在只是做一个demo不想做得太复杂

50

主题

236

帖子

454

积分

中级会员

Rank: 3Rank: 3

积分
454
发表于 2012-9-22 13:08:00 | 显示全部楼层

Re: Re: 用getpixel和setpixel实现混合加,效果达到了,就是慢

xyczy20: Re: 用getpixel和setpixel实现混合加,效果达到了,就是慢得窗口都动不了,cpu%50+,新手求助,在线等...

就是把一个24位的技能特效图片和另一个背景图片的像素进行饱和加实现显示特效的目的

         sRGB[2].b...


我的混合代码仅57行,是用mmx汇编实现的,并不复杂.
相反,你写的代码比我的复杂多了,你用了大量的gdi操作,而我没有这些东西,只是纯粹的UINT类型像素操作,唯一用到的win32 api就是SetDIBitsToDevice()

50

主题

236

帖子

454

积分

中级会员

Rank: 3Rank: 3

积分
454
发表于 2012-9-22 13:35:00 | 显示全部楼层

Re: 用getpixel和setpixel实现混合加,效果达到了,就是慢得

这是演示代码,整个代码量仅232行,
PS:图像数据也在代码里

9

主题

86

帖子

200

积分

中级会员

Rank: 3Rank: 3

积分
200
发表于 2012-9-29 18:26:00 | 显示全部楼层

Re:用getpixel和setpixel实现混合加,效果达到了,就是慢得

快一点的方法就是 Lock一下,然后用指针。。。应该是你这个的几十倍。。。
再快一点的方法就是直接用D3D。。。应该是你这个的几百倍。。。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-2-27 16:38

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表