Jpeg save to base64 in TThread
我在Delphi中遇到了一些问题。
我写了两个简单的函数来制作屏幕截图,将其转换为jpeg并解码为base64流。
如果我在主流程序上做到这一点,它的效果很好。但是,如果我创建一个TThread类并在Execute上启动此函数,则Windows会冻结,并且我只能重新启动我的PC。
通过几次尝试,我发现通过过程
如果我不将位图转换为jpeg,它的效果很好,并且我得到了图像字符串。
请帮助。
这里是代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | procedure TEvReader.ScreenShot(DestBitmap : TBitmap) ; var DC : HDC; begin DC := GetDC (GetDesktopWindow) ; try DestBitmap.Width := GetDeviceCaps (DC, HORZRES) ; DestBitmap.Height := GetDeviceCaps (DC, VERTRES) ; BitBlt(DestBitmap.Canvas.Handle, 0, 0, DestBitmap.Width, DestBitmap.Height, DC, 0, 0, SRCCOPY) ; finally ReleaseDC (GetDesktopWindow, DC) ; end; end; function TEvReader.Base64FromBitmap(Bitmap: TBitmap): string; var Input: TBytesStream; Output: TStringStream; JpegImg:TJPEGImage; begin Input := TBytesStream.Create; try JpegImg:=TJPEGImage.Create; JpegImg.Assign(Bitmap); JpegImg.SaveToStream(Input); {here a problem.When i replace"JpegImg" to"Bitmap" all works good } Input.Position := 0; Output := TStringStream.Create('', TEncoding.ASCII); try Soap.EncdDecd.EncodeStream(Input, Output); Result := Output.DataString; finally Output.Free; end; finally Input.Free; end; end; procedure TOutThread.Execute; var bmp:TBitmap; strrr:String; begin bmp:=TBitmap.Create; mObj.ScreenShot(bmp); strrr := mObj.Base64FromBitmap(bmp); Form2.Memo4.Text := strrr; end; |
TJPEGImage不是线程安全的。虽然在Delphi XE6中已解决了http://qc.embarcadero.com/wc/qcmain.aspx?d=55871中提到的线程安全绘图问题(通过暴露Canvas属性,您必须锁定自己),但在您的情况下,它将可能没有太大帮助。
您必须将TJPEGImage处理与主线程同步。
由于从未发布过JpgImg和Bmp对象,因此在代码中还创建了一些内存泄漏。
尝试以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | procedure TEvReader.ScreenShot(DestBitmap: TBitmap); var DC: HDC; begin DC := GetDC(GetDesktopWindow); DestBitmap.Canvas.Lock; try DestBitmap.Width := GetDeviceCaps(DC, HORZRES); DestBitmap.Height := GetDeviceCaps(DC, VERTRES); BitBlt(DestBitmap.Canvas.Handle, 0, 0, DestBitmap.Width, DestBitmap.Height, DC, 0, 0, SRCCOPY); finally DestBitmap.Canvas.Unlock; ReleaseDC(GetDesktopWindow, DC); end; end; function TEvReader.Base64FromBitmap(Bitmap: TBitmap): string; var Input: TBytesStream; Output: TStringStream; JpegImg: TJPEGImage; begin Input := TBytesStream.Create; try JpegImg := TJPEGImage.Create; try TThread.Synchronize(nil, procedure begin JpegImg.Assign(Bitmap); JpegImg.SaveToStream(Input); end); finally JpegImg.Free; end; Input.Position := 0; Output := TStringStream.Create('', TEncoding.ASCII); try Soap.EncdDecd.EncodeStream(Input, Output); Result := Output.DataString; finally Output.Free; end; finally Input.Free; end; end; procedure TOutThread.Execute; var mObj: TEvReader; bmp: TBitmap; strrr: string; begin mObj := TEvReader.Create; bmp := TBitmap.Create; try mObj.ScreenShot(bmp); strrr := mObj.Base64FromBitmap(bmp); finally bmp.Free; mObj.Free; end; Synchronize(nil, procedure begin Form2.Memo4.Text := strrr; end); end; |