DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: hebhanax
今日帖子: 49
在线用户: 15
导航: 论坛 -> 移动应用开发 斑竹:flyers,iamdream  
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2021/12/23 0:56:39
标题:
请教一下,如何优化存储读取图片的速度 浏览:2000
加入我的收藏
楼主: 安卓下,
1、手机拍照或者调用相册里的照片后,如何将图片的变小,方便加快用流存储到数据库的速度?
2、Imagecontrol、ImageViewer里没有stretch属性,怎么才能填充满呢?

FMX与VCL差距还是挺大的,请赐教具体的方法,谢谢
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2021/12/23 6:40:01
1楼: 1) you can use the class from Android API directly on FMX project
---> android.graphics.Bitmap.CompressFormat


unit FMX.Graphics.Android;
**********
function TBitmapCodecAndroid.SaveToStream(const AStream: TStream; const Bitmap: TBitmapSurface;
  const Extension: string; const SaveParams: PBitmapCodecSaveParams): Boolean;

**********

but if the image already compressed nothing will be done!!!

2) you can "zip" it, but... normally images on Android use compress-format by default (JPeg, Gif, PNG, Webp, etc...) - zip can help on size just!!!

for image "stretch/original/etc.. mode" you need use a TImage as target.
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2021/12/23 6:41:00
2楼: procedure TForm1.Button3Click(Sender: TObject);
var
  AStream      : TStream;
  NativeBitmap : JBitmap;
  SaveFormat   : JBitmap_CompressFormat;
  SaveQuality  : Integer;
  OutByteStream: JByteArrayOutputStream;
  ContentBytes : TJavaArray<Byte>;
  resulted     : boolean;
begin
  NativeBitmap := TJBitmap.JavaClass.createBitmap(Image1.Bitmap.Width, Image1.Bitmap.Height, TJBitmap_Config.JavaClass.ARGB_8888);
  try
    if not(SurfaceToJBitmap(TBitmapSurface(Image1.Bitmap), NativeBitmap)) then
      exit;
    //
    SaveFormat := TJBitmap_CompressFormat.JavaClass.PNG;
    //
    OutByteStream := TJByteArrayOutputStream.JavaClass.init(0);
    //
    SaveQuality := 75 { default quality };
    //
    resulted := NativeBitmap.compress(SaveFormat, SaveQuality, OutByteStream);
  finally
    NativeBitmap.recycle;
  end;
  //
  AStream := TStream.Create;
  try
    if resulted and (OutByteStream.size > 0) then
    begin
      ContentBytes := OutByteStream.toByteArray;
      try
        AStream.WriteBuffer(ContentBytes.Data^, OutByteStream.size);
      finally
        FreeAndNil(ContentBytes);
      end;
    end;
  finally
    ///  ??????? 
    ////
    AStream.Free;
  end;
  //
  // resulted := resulted and (OutByteStream.size > 0);
end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 emailx45 (emailx45) ▲▲▲▲△ -
普通会员
2021/12/23 6:41:55
3楼: uses
  Androidapi.JNI.GraphicsContentViewText,
  FMX.Graphics, FMX.Surfaces, FMX.Helpers.Android;

function BitmapToJBitmap(const ABitmap: TBitmap): JBitmap;
var
  LSurface: TBitmapSurface;
begin
  Result := TJBitmap.JavaClass.createBitmap(ABitmap.Width, ABitmap.Height, TJBitmap_Config.JavaClass.ARGB_8888);
  LSurface := TBitmapSurface.Create;
  try
    LSurface.Assign(ABitmap);
    SurfaceToJBitmap(LSurface, Result);
  finally
    LSurface.Free;
  end;
end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
作者:
男 luckyso999 (luckyso) ★☆☆☆☆ -
盒子活跃会员
2021/12/23 9:09:16
4楼: emailx45能力真强,各种代码都能来得
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/12/23 10:41:35
5楼: 楼主问题没描述清楚。

是把图片文件变小?那就是压缩图片为 JPG 等格式;

是把图片尺寸变小?

如果图片尺寸过大 -- 现在手机拍照的像素太多,导致图片尺寸太大,如果你的应用需求不需要那么大的图片,可以对图片尺寸(分辨率)做一次缩放,然后对缩小尺寸后的图片,再做 JPG 压缩。这样可以得到比较小的数据量。
----------------------------------------------
-
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2021/12/23 12:23:25
6楼: pcplayer 您好
主要是实现手机拍照后像素太大,照片体积太大,网路传输及读取数据库时速度太慢,而几乎不需要太好质量的图片,以提高显示及读取速度

问题就是不知道如何把图片尺寸(分辨率)降低,再转成JPG格式
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/12/23 16:10:04
7楼: 你的问题不是语言的问题,是库的问题。比如,在 VCL 底下,可能是用什么函数,在 FMX 底下,又是用另外的函数。你现在说的是手机,那么我假设你是在 FMX 底下。

我需要打开 Delphi 自己写个代码试试。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/12/23 16:53:00
8楼: 上网查了一下资料,测试通过的代码如下:

uses FMX.Surfaces;

procedure TForm1.Button1Click(Sender: TObject);
var
  Bmp: TBitmap;
  Src, Trg: TRectF;
  NewWidth, NewHeight: Integer;
  AStream: TFileStream;
  Surf: TBitmapSurface;
begin
  if OpenDialog1.Execute then
  begin
    Image1.Bitmap.LoadFromFile(OpenDialog1.FileName);
    Src := RectF(0, 0, Image1.Bitmap.Width, Image1.Bitmap.Height);

    //这里缩小一半
    NewWidth := Trunc(Image1.Bitmap.Width / 2);
    NewHeight := Trunc(Image1.Bitmap.Height / 2);
    Trg := RectF(0, 0, NewWidth, NewHeight);

    Bmp := TBitmap.Create;
    try
      Bmp.Width := NewWidth;
      Bmp.Height := NewHeight;
      Bmp.Canvas.BeginScene;
      try
        Bmp.Canvas.DrawBitmap(Image1.Bitmap, Src, Trg, 1)
      finally
        Bmp.Canvas.EndScene;
      end;

      Image2.Bitmap.Assign(Bmp);

      // 保存的文件名带 jpg ,自动压缩为 JPG
      Bmp.SaveToFile('D:\testAAA.jpg');

      //保存到 Stream 看看
      Surf := TBitmapSurface.Create;
      AStream := TFileStream.Create('D:\testAAABB.jpg', fmCreate);
      try
        Surf.Assign(Bmp);
        //这个方法,通过字符串 .jpg 指定它输出时编码为 jpg,测试通过。
        TBitmapCodecManager.SaveToStream(AStream, Surf, '.jpg', nil);
      finally
        AStream.Free;
        Surf.Free;
      end;
    finally
      Bmp.Free;
    end;
  end;
end
----------------------------------------------
-
作者:
男 letianwuji (大器晚成) ▲▲▲▲▲ -
普通会员
2021/12/24 17:40:18
9楼: 1,指针读写;
2,多线程分段读写。
要快么?
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2021/12/25 1:11:16
10楼: 各位大哥:
是做的安卓APP,调用的摄像头或者相册里的照片作为商品的图片,现在是每次存入商品图片时非常的耗时,读取显示存入数据库的时候也特别费时间,
为了提高读取显示,存入速度,牺牲一些照片的清晰度都没关系。只要能看清除是啥东西就行。
目前根据  pcplayer   提供的代码这样做的:
var Stream:TMemoryStream;
var  Bmp: TBitmap;
var   Src, Trg: TRectF;
var   NewWidth, NewHeight: Integer;
//var   AStream: TFileStream;
var   Surf: TBitmapSurface;

begin
  //图片
  if CheckBox1.IsChecked=True then
  begin
    Src := RectF(0, 0, ImageControl1.Bitmap.Width, ImageControl1.Bitmap.Height);
    NewWidth := Trunc(ImageControl1.Bitmap.Width / 20);
    NewHeight := Trunc(ImageControl1.Bitmap.Height / 20);
    Trg := RectF(0, 0, NewWidth, NewHeight);
    Bmp := TBitmap.Create;

    try
      Bmp.Width := NewWidth;
      Bmp.Height := NewHeight;
      Bmp.Canvas.BeginScene;
      try
        Bmp.Canvas.DrawBitmap(ImageControl1.Bitmap, Src, Trg, 1);
      finally
        Bmp.Canvas.EndScene;
      end;

      Surf := TBitmapSurface.Create;
      Stream := TMemoryStream.Create; // 创建内存流
      try
        Surf.Assign(Bmp);
        TBitmapCodecManager.SaveToStream(Stream, Surf, '.jpg', nil);
      finally
        Stream.Free;
        Surf.Free;
      end;
    finally
      Bmp.Free;
    end;

    sql:='insert into Fc_GoodsImage (PTypeID,Picture) values ( ';
    sql:=sql+':ID,:pic)';
    ClientModule1.ClientDataSet1.Close;
    ClientModule1.ClientDataSet1.CommandText:=sql;
    ClientModule1.ClientDataSet1.ParamByName('id').Value:=cBaseNo;
    ClientModule1.ClientDataSet1.ParamByName('pic').LoadFromStream(Stream,ftBlob);
    ClientModule1.ClientDataSet1.Execute;

end;


但是,效果不是很明显,速度还是挺慢的

请大神赐教
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 xxz1314 (xxz1314) ★☆☆☆☆ -
普通会员
2021/12/26 9:41:37
11楼: 给你换个思路吧,你是调用摄像头,那么你直接程序自开摄像头拍照的时候直接拍成成小图存储就好了,非要调用摄像头图片吗?fmx下不是有摄像头例子吗?简单看看换个思路就可以解决你的需求,解决需求可以多种方法,达到目的就可以了~,图片压缩不管你在什么平台下都耗时的~
----------------------------------------------
-
作者:
男 xxz1314 (xxz1314) ★☆☆☆☆ -
普通会员
2021/12/26 9:44:40
12楼: 还有一点,感觉有点不合理的地方~图片资源一般不存入数据库的吧~
----------------------------------------------
-
作者:
男 sxfgf (FC_FGF) ★☆☆☆☆ -
普通会员
2021/12/26 23:51:06
13楼: xxz1314:
  是的如果不把数据库存入数据库里,那还得搞一个图片服务器
  存入数据库把的确影响速度,但是相对独立经济一些
  不过,直接拍成小图这个思路挺好
----------------------------------------------
偶尔做做代码应付一下工作,却发现Delphi已成必配
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/12/27 11:45:59
14楼: 楼上,你的代码:
1. 你前面 Stream.Free 了,后面 ClientModule1.ClientDataSet1.ParamByName('pic').LoadFromStream(Stream,ftBlob);

2. 你的代码,你可以逐行加上 GetTickCount 获取当前时间,后面的时间减前面的时间,看看你的时间消耗,究竟在哪里。比如,是在缩放图片那里,还是在 ClientModule1.ClientDataSet1.Execute; 这里。

因为不知道你的 ClientDataSet 和服务器之间的带宽,不好判断你的时间花在哪里。
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行62.5毫秒 RSS