好久没来了,昨天一朋友程序调试程序出错,当是正忙,没时间看,晚上回去研究了一下,帖子却结了,我只好自己来发一个,希望熟悉gdi+的朋友来讨论一下。(其他gdi+方面的也欢迎留言,我刚用gdi+不久,希望多交流)
先留下联络方式:66434721(这个群算得上火爆,虽然废话比较多……)
var       //这个是他的源码
  Stream: TMemoryStream;
  istreamTest: IStream;
  GPImage: TGPImage;
  Graphic: TGPGraphics;
begin
  Stream := TMemoryStream.Create;
  Stream.LoadFromFile('c:\1.png');
  istreamTest:= TStreamAdapter.Create(Stream);
  Graphic := TGPGraphics.Create(Canvas.Handle);
  try
    GPImage := TGPImage.Create(istreamTest);  
//这句会报错,如果图片是BMP就没错
    Graphic.DrawImage(GPImage, 0, 0);
  finally
    Stream.Free;
    GPImage.Free;
    Graphic.Free;
  end;
end;
回去后调试了一下,
TStreamAdapter = class(TInterfacedObject, IStream)可参考下面文章
http://delphi.sharpplus.com/Delphi/Delphi-adapter.htm
我的实现方法
type 
TCFStreamAdapter = class(TStreamAdapter)
public
  function Stat(out statstg: TStatStg; grfStatFlag: Longint): HResult; override; stdcall;
end;
function TCFStreamAdapter.Stat(out statstg : TStatStg; grfStatFlag : Integer): HResult;
begin
  result := inherited
  Stat(statstg, grfStatFlag);
//TStatStg结构下面2个属性在TStreamAdapter.Stat里并没有初始化
  statstg.pwcsName := nil;
  statstg.reserved:=0;
end;
//改他的过程如下
var
  Stream: TMemoryStream;
  GPImage: TGPImage;
  LIStream: TCFStreamAdapter;
  MYGUID: TGUID;
  Graphic: TGPGraphics;
begin
  Stream  := TMemoryStream.Create;
  Stream.LoadFromFile('c:\1.png');
  LIStream := TCFStreamAdapter.Create(Stream);
  GPImage := TGpImage.Create(LiStream);
  edit1.Text:=inttostr(LiStream.Stream.Size);
  Graphic := TGPGraphics.Create(Canvas.Handle);
  try
    Graphic.DrawImage(GPImage, 0, 0);
    GetEncoderClsid('image/bmp', MYGUID); {先获取格式编码}
    GPImage.Save('c:\1.bmp', MYGUID);
  finally
    Stream.Free;
    GPImage.Free;
    Graphic.free;
  end;
end;
下面方法来自阿发伯的日志,实现的更简单,据说是翻译自C++,希望有熟悉C++
的朋友能给出原理
var
  tmp: TGpBitmap;
  Adapter: TStreamAdapter;
  Stream: TMemoryStream;
  Clsid: TGUID;
  Graphic: TGPGraphics;
begin
  Stream := TMemoryStream.Create;
  Adapter := TStreamAdapter.Create(Stream, soOwned);
  Stream.LoadFromFile('c:\1.png');
  GetEncoderClsid('image/bmp', Clsid);
  IStream(Adapter)._AddRef;
  Graphic := TGPGraphics.Create(Canvas.Handle);
  tmp := TGpBitmap.Create(Adapter);
  try
    tmp.Save('c:\1.bmp',Clsid);
    Graphic.DrawImage(tmp, 0, 0);
  finally
    tmp.Free;
    Graphic.free;
    IStream(Adapter)._Release;
  end;
end;

解决方案 »

  1.   

    还是opencv处理起来更简洁一些
    IplImage *input = cvLoadImage("E:\\1.png",1);
    CvSize outputSize = { input->width, input->height };
    IplImage* output = cvCreateImage( outputSize, input->depth, input->nChannels );
    cvResize( input, output ,CV_INTER_AREA);
    cvResetImageROI( output );
    cvSaveImage( "E:\\1.bmp",output );
    cvReleaseImage( &input );
    cvReleaseImage( &output );
      

  2.   

    顶啊顶,接啊接……
    阿发伯的那个是建立一个内存流,然后用GetEncoderClsid为编码器获取类标示符(就是Clsid),建立一个画布。而TStreamAdapter是从TInterfacedObject继承下来的操纵IStream接口的对象。通过TStreamAdapter对象可以实现Delphi内部TStream对象对ISTream接口对象的操纵,最后将临时画布的文件保存为bmp然后释放,可以参考流的方法实现
      

  3.   

    IStream(Adapter)._AddRef; 
    IStream(Adapter)._Release; 
    主要还是想搞明白上面2个做了什么工作。
    论坛能侃的越来越少了呵呵
      

  4.   

    IStream是一个Com对象_AddRef 接口是引用计数。因此在对象中当获得接口指针时,对象被引用的次数就增加了。当结束使用接口时,对象的
    引用次数就下降了。当引用次数到达零时,就自动销毁对象。_AddRef是负责增大引用计数的函数。如何物理上存储引用计数由读者决定,但是典型情况下将建立整型(Integer)变量去保存计数。_Release既是个负责降低引用计数的函数。当引用计数达到零时,就自动销毁对象。
      

  5.   

    楼上的先谢了,现在好想很多热门软件都用的Com得去深入看一下了
    怎么也没能侃的过来策会。
    顺便再说一下Ghost-J是那个群的群主,外号鸡头,这下不知道有人对那群感情趣没有,哈哈
    下周结贴,分就大家分了吧。
    我发扬风格就不分大家的了
      

  6.   

    我的是用流加载png图片 
    弹出窗口 第一次不显示
    弹出窗口 第二次就会显示图片  一直都没找到原因