zoukankan      html  css  js  c++  java
  • JPEG图像压缩出现资源不足问题的解决

    1,问题的提出

    公司开发了一个图像压缩上传程序。采用Delphi语言实现。大致步骤如下:

    1,上传前将文件打开装载到TJpegImage,

    2,创建一个TBitmap组件,设置其大小,采用StretchDraw方法将TJpegImage的图像绘制到TBitmap组件,

    3,将TBitmap组件的图像赋值给TJpegImage,

    4,设定TJpegImage的压缩率,调用压缩方法执行压缩,

    5,最后保存新的图像到文件中

    代码如下:

    //输入:要转换大小的图片文件路径
    //输出:转换后文件的路径
    function ConvertJPGFile(const inFile: string): string;
    var
      img1, img2: TImage;
      bmp: TBitmap;
      JPEGImage : TJpegImage;
      Stream:TFileStream;
      i: integer;
    const
      compress_ratio: array[1..6] of integer=(75,50,25,10,5,2);
    begin
    
      JPEGImage := TJpegImage.Create;
      bmp := TBitmap.Create;
    
      EnterCriticalSection(RTLCriticalSection2);
      try
          result := GetTempFilePath + ExtractFilename(inFile);
        JPEGImage.LoadFromFile(inFile);
    
        //要求图像分辨率不小于704×576个像素点
        if  (1.0 * JPEGImage.Width)/JPEGImage.Height >= (704.0/576.0)
        then begin
          //原图宽度足够。应以高度为准进行缩小
          bmp.Height := 600;//新图像高度
          bmp.Width := (bmp.Height*JPEGImage.Width) div JPEGImage.Height;//新图像宽度,按比例
        end else begin
          //原图高度足够。应以宽度为准进行缩小
              bmp.Width := 1024;//新图像宽度
          bmp.Height := (bmp.Width*JPEGImage.Height) div JPEGImage.Width;//新图像高度,按比例
        end;
    
        bmp.Canvas.StretchDraw(bmp.Canvas.ClipRect, JPEGImage);
        JPEGImage.Assign(bmp);
    
        for i:=1 to 1 do begin
            JPEGImage.CompressionQuality := compress_ratio[i];
            JPEGImage.Compress;
    
          JPEGImage.SaveToFile(result);
        end;
    
      finally
        JpegImage.Free;      
        bmp.Free;
    
        LeaveCriticalSection(RTLCriticalSection2);
      end;
    
    end;

    此代码在正常环境下执行没有问题,但发现若在子线程中调用,则会频繁出现“Out of system resources”、“存储空间不足,无法处理此命令”等错误。

    分析原因可能是JpegImage组件不支持多线程,只在主线程中是安全的。因此,应该在主线程中调用ConvertJPGFile方法。

    那么子线程如何让主线程中调用ConvertJPGFile方法呢?转换前后的文件名称如何传递呢?

    2,解决思路

     可以采用子线程向主线程发送消息,主线程收到消息后,转换图片,然后向子线程发送消息,子线程等到转换完毕的消息后,继续执行。

     1,子线程调用postMessage,向主线程发送特定消息WM_5001,然后调用GetMessage函数等候主线程消息

    2,主线程的WndProc过程,收到消息WM_5001后,执行图片压缩,然后向子线程PostThreadMessage,发送消息WM_5002

    3,子线程收到主线程消息,继续处理

    按以上思路 实现后,图片压缩不再出现错误。要说明的是,采用Message的WParam传递字符串参数不可靠,有时会出现字符串截断。因此程序采用全局变量进行参数传递。

    3,程序实现

    子线程调用:

    //调用主线程函数处理图像压缩,否则会出现“out of resource”之类的错误
    function Thread_tcp.ConvertJPGFile(inFile: string; var outFile: string;
      var outFileSize: integer): Boolean;
    var
      Msg: tagMsg;  
    begin
        g_convert_fn_in := inFile;
        postMessage(GetMainHandler, WM_5001,0,0);
    
        while GetMessage(Msg,0,0,0) do begin
          if Msg.message=WM_5002 then begin
            outFile := g_convert_fn_out;
            outFileSize := GetFileSize(outFile);
    
            Result := outFileSize>0;
            Exit;
          end;
        end;
    
    end;

    主线程响应:

    procedure TfMain.WndProc(var Message: TMessage);
    var
      fn: string;
      p: PChar;
    begin
        if Message.Msg = WM_5001 then begin
          g_convert_fn_out := ConvertJPGFile(g_convert_fn_in);
    
        if  getTcpThreadID>0 then
            PostThreadMessage(getTcpThreadID, WM_5002,0,0);
        end else
          inherited;
    
    end;

    全局变量声明:

    var
      g_convert_fn_in: string;  //转换图片输入文件
      g_convert_fn_out: string; //转换图片输出文件
    
    const
      WM_5001=WM_USER+5001;  //子线程向主线程发送消息,由主线程压缩图片
      WM_5002=WM_USER+5002;  //主线程向子线程发送消息,压缩图片完毕  
  • 相关阅读:
    git 多人协作
    git 版本管理
    git 安装配置
    git 忽略文件
    git 分支管理
    linux文件管理 文件操作
    linux文件管理 文件搜索
    linux文件管理 文件权限
    linux系统管理 基本指令
    003.html
  • 原文地址:https://www.cnblogs.com/jackkwok/p/7199332.html
Copyright © 2011-2022 走看看