FMX制作长条图并在其图上写字美化等操作,delphi做长条图合并图片几分钟的事

时间:2024-04-01 19:04:18

FMX制作长条图并在其图上写字美化等操作,delphi合并图片几分钟的事

一、原理

1、图上写字

    AImage.Bitmap.Canvas.BeginScene;
    AImage.Bitmap.Canvas.Font.Size:=32; //32:12号默认Memo字号对应写出来的size大小
    AImage.Bitmap.Canvas.FillText(
      ARect,  //:在位图的哪个矩形区域写字
      AText,  //:要写的文字
      true,   //:可换行
      1,      //:不透明
      [],     //:写字的方向[TFillTextFlag.RightToLeft]:TFillTextFlags
      TTextAlign.Leading,//:文字水平齐头
      TTextAlign.Center  //:文字垂直居中
    );
    AImage.Bitmap.Canvas.EndScene;

2、图片合并

    ATImageTo.Bitmap.Canvas.BeginScene;
    ATImageTo.Bitmap.Canvas.DrawBitmap(ATBitmap
      ,AScrTRectF //:裁剪原图的矩形区域
      ,ADstTRectF //:在指定的矩形区域显示出来
      ,1,false);
    ATImageTo.Bitmap.Canvas.EndScene;

3、Bitmap的Size限制

    //65535:=MaxAllowedBitmapSize=$FFFF=10000H-1,即十进制16^4-1=65535;
    //:Windows下峰值65535:1080*1920*20(20张高1920的超高清蓝光图)
    //:Windows下峰值38400:720*1280*30(30张高1920的高清图):TImage的画布实际可显示出来的最多只有22张
    //:Android:峰值8160(宽720时的最大值):7680=宽720时高1280*6张=宽360时高640*12张
    //:IOS:峰值3840(宽720时的最大值):3840=宽720时高1280*3张=宽360时高640*6张
      //:超出峰值会报错:Bitmap Size too big
      //:(宽720像素:一般高清手机拍照或截屏值,取决于手机设置)
      //:(宽360像素时:屏幕放大后清晰度较差)
    //:结论:图片以宽720像素按比例加载到TImage时:
      //1280:是加载每张图的理想尺寸

4、分享

  //FMX.Platform平台服务->FMX.MediaLibrary媒体库接口:
  try
    if TPlatformServices.Current
      .SupportsPlatformService(
        IFMXShareSheetActionsService,
        IInterface(LFMXShareService)
       ) then
    begin //两个动作只能2选1://Share第1个参数:本窗体内任意TControl:
      //LFMXShareService.Share(Memo1,'我发的',nil);                   //:为空:执行前面的'我发的'
      LFMXShareService.Share(AImage,'我发的',AImage.Bitmap);//:非空:执行后面的AImage.Bitmap
    end;
  finally
  end;

二、代码

//D:\delphiXEDev\delphi半透明提示框\mergeImageAndWords

unit MergeImageAndWords;

interface

uses
  System.SysUtils, System.Types, System.UITypes,
  System.Classes, System.Variants, System.Math,
  System.Generics.Collections,System.Generics.Defaults,
  FMX.Types, FMX.Controls, FMX.Forms,
  FMX.Graphics, FMX.Dialogs, FMX.Layouts,
  FMX.StdCtrls, FMX.Controls.Presentation,
  FMX.Objects, FMX.ScrollBox, FMX.Memo,
  FMX.Edit, FMX.ExtCtrls, FMX.ListBox,
  FMX.MediaLibrary,FMX.PlatForm, System.Actions, FMX.ActnList, FMX.StdActns,
  FMX.MediaLibrary.Actions
  ;

type
  TfmxMergeImageAndWords = class(TForm)
    Layout1: TLayout;
    Rectangle1: TRectangle;
    ImgMerging03: TImage;
    ImgMerging01: TImage;
    ImgMerging02: TImage;
    LayoutTools: TLayout;
    btnMergeImgs: TSpeedButton;
    btnMergeImgsSave: TSpeedButton;
    ImgDrawed: TImage;
    LayoutAll: TLayout;
    ScrollBox1: TScrollBox;
    btnHome: TSpeedButton;
    StyleBook_MetropolisUIBlue: TStyleBook;
    Memo1: TMemo;
    Selection1: TSelection;
    VertScrollBox1: TScrollBox;
    ImageViewer1: TImageViewer;
    ScrollBoxDecoratImg: TVertScrollBox;
    btnDecoratImg: TSpeedButton;
    ListBoxDecoratImg: TListBox;
    ListBoxItemDecoratImg1: TListBoxItem;
    ListBoxItemDecoratImg2: TListBoxItem;
    ListBoxItemDecoratImg3: TListBoxItem;
    ImgDecorat: TImage;
    btnShare: TSpeedButton;
    Memo2: TMemo;
    procedure ControlAction(Sender: TObject);
    procedure btnMergeImgsClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure ScrollBox1ViewportPositionChange(Sender: TObject;
      const OldViewportPosition, NewViewportPosition: TPointF;
      const ContentSizeChanged: Boolean);
    procedure FormShow(Sender: TObject);
    procedure Selection1Track(Sender: TObject);
    procedure Memo1ChangeTracking(Sender: TObject);
  private
    { Private declarations }
    ///<summary>存取路径:</summary>
    FSavePath:string;
    ///<summary>控制是否滚动要在其中图片写字的当前ScrollBox:</summary>
    FIfScrolling:Boolean;
    ///<summary>要在其中图片写字的当前ScrollBox视口:</summary>
    FScrollBox1ViewportY:Single;
    ///<summary>要在其上写字的图片的当前Y向位置:</summary>
    FImgMergingPositionY:Single;
    ///<summary>当前要在其上写字的图像控件:</summary>
    FImg:TImage;
    ///<summary>写字的Memo控件当前的列数:</summary>
    FMemoColums:Integer;
    ///<summary>写字的Memo控件当前的行数:</summary>
    FMemoRows:Integer;

    procedure FillImageText(AImage:TImage;AText:string);
    procedure ShareImg(AImage:TImage);
  public
    { Public declarations }
  end;

  function IfScrolling(
    ACanScrollControl:TCustomScrollBox;
    Scrolling:Boolean):Boolean;
  procedure DrawLongImage(
    var ATImageTo,ATImageFrom:TImage;
    var AWidthTImageTo,AHeightTImageTo:Integer;
    var ATBitmap:TBitmap; var AScrTRectF,ADstTRectF:TRectF );

var
  fmxMergeImageAndWords: TfmxMergeImageAndWords;

implementation
uses
{$R *.fmx}

{$IFDEF ANDROID}
  Androidapi.Helpers,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.Os,
{$ENDIF}
  FMX.DialogService,
  myFuc_UnifiedPlatForm,
  myFuc_Client
  ;

procedure TfmxMergeImageAndWords.btnMergeImgsClick(Sender: TObject);
var LTBitmap:TBitmap; LQuality:PBitmapCodecSaveParams;
    LDstTRectF,LScrTRectF:TRectF;
    LWidthTImageTo,LHeightTImageTo:Integer;
    LFindImgList:TList<TImage>; LIComparerImgList:IComparer<TList<TImage>>;
    LImgStrList:TStringList;
    LResult:string;
  //procedure EnumControls(const Proc: TFunc<TControl, TEnumControlsResult>); overload;
  //function EnumControls(Proc: TEnumControlsRef; const VisibleOnly: Boolean = True): Boolean; overload;
  //const Proc: TFunc<TFmxObject, TEnumProcResult>
  function FindMergingImg:string;
    Var LImagePrior,LImageCurrt:TImage;
        LBitmapPriorHeight:Single;
        LImageCount:Integer;
  begin
    LImageCurrt:=nil; LBitmapPriorHeight:=0;  LResult:='';
    //LFindImgList:=TList<FMX.Objects.TImage>.Create;
    LImgStrList:=TStringList.Create;
    ScrollBox1.EnumControls(
      procedure (const AControl: TControl; var Done: boolean)
      begin
        if (AControl.ClassName = 'TImage') then
        begin
          //LImagePrior:=LImageCurrt;
          LImageCurrt:=TImage(AControl);
          //LFindImgList.Add(LImageCurrt);
          LImgStrList.AddObject(LImageCurrt.Name,LImageCurrt);
            //:加入TStringList以便全部加入完毕后进行排序
          {
          LScrTRectF.Top:=0;
          LScrTRectF.Left:=0;
          LScrTRectF.Bottom:=
            ImgMerging01.Position.Point.Y+LImageCurrt.Bitmap.Height;
          LScrTRectF.Right:=
            ImgMerging01.Position.Point.X+LImageCurrt.Bitmap.Width;
          if LImagePrior=nil then
          begin
            LDstTRectF.Top:=LScrTRectF.Top;
            LDstTRectF.Left:=LImageCurrt.Position.Point.X;
            LDstTRectF.Bottom:=LDstTRectF.Top +LScrTRectF.Bottom;
            LDstTRectF.Right:=
              LImageCurrt.Position.Point.X+LImageCurrt.Bitmap.Width;
          end;// else
          if LImagePrior<>nil then
          begin
            LBitmapPriorHeight:=LBitmapPriorHeight +LImagePrior.Bitmap.Height;
            LDstTRectF.Top:=LScrTRectF.Top
              +LBitmapPriorHeight    //:该图上面所有合并图的高度
              ;
            LDstTRectF.Left:=LImageCurrt.Position.Point.X;
            LDstTRectF.Bottom:=LDstTRectF.Top +LScrTRectF.Bottom;
            LDstTRectF.Right:=
              LImageCurrt.Position.Point.X+LImageCurrt.Bitmap.Width;
          end;
          try
            DrawLongImage(
              ImgDrawed,LImageCurrt,
              LWidthTImageTo,LHeightTImageTo,LTBitmap,LScrTRectF,LDstTRectF );
          finally
          end;
          LResult:=LResult+'当前枚举的图是:'+LImageCurrt.Name+slinebreak;
          }
        end;
        Done:=false;//:不要停继续找下一个
      end
      ,true //:只枚举可见的组件
      );
    //LFindImgList.Sort; //:枚举类型只能按照索引号index排序
    LImgStrList.Sorted:=true;
      //:枚举完后按TStringList的Strings行次的名称进行排序
    try
      LImageCurrt:=nil;
      for LImageCount:=0 to (LImgStrList.Count-1) do
      begin
        LImagePrior:=LImageCurrt;
        LImageCurrt := TImage(LImgStrList.Objects[LImageCount]);
        //剪切多大的矩形图:
        LScrTRectF.Top:=0;
        LScrTRectF.Left:=0;
        LScrTRectF.Bottom:=
          LImageCurrt.Position.Point.Y+LImageCurrt.Bitmap.Height;
        LScrTRectF.Right:=
          LImageCurrt.Position.Point.X+LImageCurrt.Bitmap.Width;
        //在哪个目标位置矩形画图:
        if LImagePrior=nil then
          LBitmapPriorHeight:=LBitmapPriorHeight;
        if LImagePrior<>nil then
          LBitmapPriorHeight:=LBitmapPriorHeight +LImagePrior.Bitmap.Height;
        LDstTRectF.Top:=LScrTRectF.Top
          +LBitmapPriorHeight;    //:该图上面所有合并图的高度
        LDstTRectF.Left:=LImageCurrt.Position.Point.X;
        LDstTRectF.Bottom:=LDstTRectF.Top +LScrTRectF.Bottom;
        LDstTRectF.Right:=
          LImageCurrt.Position.Point.X+LImageCurrt.Bitmap.Width;
        try //开始画图:
          DrawLongImage(
            ImgDrawed,LImageCurrt,
            LWidthTImageTo,LHeightTImageTo,LTBitmap,LScrTRectF,LDstTRectF );
        finally
        end;
        LResult:=LResult+'枚举后排序的当前图是:'+LImageCurrt.Name+slinebreak;
      end;
    finally
      //FreeAndNil(LFindImgList);
      FreeAndNil(LImgStrList);
    end;
    if LImageCurrt<>nil then
      Result:=LResult+'找到的最后1个排序图是:'+LImageCurrt.Name
    else Result:='没图';
  end;
begin
  if FSavePath.Trim='' then
  begin
    {$IFDEF POSIX}
      try
        {$IFDEF Android}
          //Memo1.Lines.Add(AndoidRequestPermissions('读取文件')); Memo1.Lines.Add(AndoidRequestPermissions('写入文件'));
          AndoidRequestPermissions('读取文件');
          AndoidRequestPermissions('写入文件');
        {$ENDIF Android}
      finally
        SubPathOfAppPublished;
        FSavePath:=GetSubPathOfAppPublished;
      end;
    {$ENDIF POSIX}
  end;

  {$IFDEF IOS}
    LWidthTImageTo:=720;  LHeightTImageTo:=3840;
  {$ENDIF IOS}            //3840:IOS最大值3张
  {$IFDEF Android}
    LWidthTImageTo:=720;  LHeightTImageTo:=7680;
  {$ENDIF Android}        //7680:Android最大值6张
  {$IFDEF MSWINDOWS}
    LWidthTImageTo:=720;   LHeightTImageTo:=28160;
  {$ENDIF MSWINDOWS}      //38400:Wondows最大值30张
  System.TMonitor.Enter(ImgDrawed,0);

  try
    FindMergingImg;
    //Memo1.Lines.Clear; Memo1.Lines.Add(FindMergingImg);
  finally
    ImgDrawed.Bitmap.SaveToFile(FSavePath+'ImgDrawed.jpg');
      //:将文件保存到本地指定路径
  end;
  System.TMonitor.Exit(ImgDrawed);
  VertScrollBox1.BringToFront; VertScrollBox1.Visible:=true;
end;

procedure DrawLongImage(
  var ATImageTo,ATImageFrom:TImage;
  var AWidthTImageTo,AHeightTImageTo:Integer;
  var ATBitmap:TBitmap; var AScrTRectF,ADstTRectF:TRectF );
begin
  if not Assigned(ATImageTo.Bitmap) then
  begin
    ATImageTo.Bitmap.Create;
    //:需要传入的ATImageTo设计期:
      //:设置一个虚拟图片来将其撑大大小为:
      //:AWidthTImageTo,AHeightTImageTo
      //:否则POSIX运行时的宽度显示不全
  end;
  try
    ATBitmap:=TBitmap.Create;
    ATBitmap.Width:=ATImageFrom.Bitmap.Width;
    ATBitmap.Height:=ATImageFrom.Bitmap.Height;
    ATBitmap.SetSize(ATBitmap.Width,ATBitmap.Height);

    ATBitmap.Canvas.BeginScene; //:必须
    ATBitmap.Canvas.DrawBitmap(ATImageFrom.Bitmap
      ,AScrTRectF //:裁剪原图的矩形区域
      ,AScrTRectF //:在原图矩形区域显示出来
      ,1,false);
    ATBitmap.Canvas.EndScene;

    ATImageTo.Bitmap.SetSize(AWidthTImageTo,AHeightTImageTo);
    ATImageTo.Bitmap.Canvas.BeginScene;
    ATImageTo.Bitmap.Canvas.DrawBitmap(ATBitmap
      ,AScrTRectF //:裁剪原图的矩形区域
      ,ADstTRectF //:在指定的矩形区域显示出来
      ,1,false);
    ATImageTo.Bitmap.Canvas.EndScene;

  finally
    FreeAndNil(ATBitmap);
  end;
end;

procedure TfmxMergeImageAndWords.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  fmxMergeImageAndWords:=nil;
  Action:=TCloseAction.caFree;
  //:窗体OnFormDestroy的时候:inherited会自动释放:窗体内的所有:
FreeAndNil(FDConnSQLite);//  ClientModule1.FDManager1.DropConnections;
  inherited;
end;

procedure TfmxMergeImageAndWords.FormCreate(Sender: TObject);
begin
  FIfScrolling:=true;
  VertScrollBox1.Visible:=false;
  ListBoxDecoratImg.Visible:=false;
  FScrollBox1ViewportY:=0;
  FImgMergingPositionY:=0;
  FImg:=nil;
  Memo1ChangeTracking(Sender);

end;

procedure TfmxMergeImageAndWords.FormShow(Sender: TObject);
var CountComponent:Integer; ComponentName:string;
begin
  ScrollBox1.BringToFront;
  ComponentName:='';
  //枚举设置显示方式及点击事件:fmxMergeImageAndWords.ScrollBox1
  //{
  for CountComponent:=0 to ComponentCount-1 do
  begin
    if Components[CountComponent] is TImage then
    begin
      ComponentName:=TImage(Components[CountComponent]).Name;
      if ComponentName.IndexOf('ImgMerging',0,10)>=0 then
      begin
        //Memo1.Lines.Add(ComponentName);
        TImage(Components[CountComponent]).BringToFront;
        TImage(Components[CountComponent]).OnClick:=fmxMergeImageAndWords.ControlAction;
      end;
    end;
  end; //}
  Selection1.BringToFront;

//FMX.Controls.EnumControls枚举不全(同步枚举,非异步):
  { //FMX.Controls.EnumControls枚举不全(同步枚举,非异步):
  fmxMergeImageAndWords.ScrollBox1.EnumControls(
  procedure (const AControl: TControl; var Done: boolean)
  begin
    Done:=false;//:不要停继续找下一个
    ComponentName:=AControl.Name;
    if (AControl.ClassName = 'TImage') then
    begin
      //if (pos('ImgMerging',ComponentName)>0) then
      if (ComponentName.IndexOf('ImgMerging',0,length(ComponentName))>=0) then
      begin
        AControl.BringToFront;
        AControl.OnClick:=fmxMergeImageAndWords.ControlAction;
        //ComponentName:=ComponentName+AControl.Name+SLineBreak;
        Memo1.Lines.BeginUpdate;
        Memo1.Lines.Add(ComponentName);
        Memo1.Lines.EndUpdate;
      end;
    end;
  end
  ,true //:只枚举可见的组件
  );
  //}


end;

procedure TfmxMergeImageAndWords.ScrollBox1ViewportPositionChange(
  Sender: TObject;
  const OldViewportPosition, NewViewportPosition: TPointF;
  const ContentSizeChanged: Boolean);
begin
  FScrollBox1ViewportY:=NewViewportPosition.Y;
//  Memo1.Lines.BeginUpdate;
//  Memo1.Lines.Add(FloatToStr(FScrollBox1ViewportY));
//  Memo1.Lines.EndUpdate;
end;

procedure TfmxMergeImageAndWords.Selection1Track(
  Sender: TObject);
begin
  self.Caption:='合并多图片加文字描述'+
    FloatToStr(Selection1.Position.Y);
end;

function IfScrolling(
  ACanScrollControl:TCustomScrollBox;
  Scrolling:Boolean):Boolean;
begin
  if Scrolling=false then
  begin
    ACanScrollControl.AniCalculations.BeginUpdate;
    ACanScrollControl.AniCalculations.Animation:=false;
    ACanScrollControl.AniCalculations.BoundsAnimation:=false;
    ACanScrollControl.AniCalculations.TouchTracking:=[];
    ACanScrollControl.AniCalculations.EndUpdate;
    Result:=false;
  end else
  begin
    ACanScrollControl.AniCalculations.BeginUpdate;
    ACanScrollControl.AniCalculations.Animation:=true;
    ACanScrollControl.AniCalculations.BoundsAnimation:=true;
    ACanScrollControl.AniCalculations.TouchTracking:=[ttVertical, ttHorizontal];
    ACanScrollControl.AniCalculations.EndUpdate;
    Result:=true;
  end;

end;

procedure TfmxMergeImageAndWords.ControlAction(
  Sender: TObject);
var Scene:IScene; LTControlName:string;
begin
  if (Sender as TControl) is TSpeedButton then
  begin
    FocusMe(Sender as TControl);
    if Sender=btnHome then close;
    if Sender=btnMergeImgsSave then
    begin
      VertScrollBox1.Visible:=false; //:隐藏长条图预览合并
      ScrollBoxDecoratImg.Visible:=false; //:隐藏长条图配文字
    end;

    if Sender=btnDecoratImg then
      ListBoxDecoratImg.Visible:=true;
    if Sender=btnShare then ShareImg(ImgDrawed);
    //...... btnShare
  end;
  if (Sender as TControl) is TListBoxItem then
  begin
    if (Sender=ListBoxItemDecoratImg1) then
    begin
      Memo1.SelectAll;
      Memo1.CopyToClipboard;
      ListBoxDecoratImg.Visible:=false;
      if Selection1.Position.Y=113 then
      begin
        Selection1.Position.Y:=112;
        Selection1.Position.Y:=113;
      end;
      if Memo1.Lines.Text.Trim='' then
      begin
        ShowAMessage('请写好您要发布的文字!',procedure begin end);
        Memo1.CanFocus:=true;  Memo1.SetFocus;
        exit;
      end;

      if FImg<>nil then
      begin
        Memo1.Lines.Clear;
        Memo1.PasteFromClipboard;
        //调用:长条图配文字代码:
        FillImageText(FImg,Memo1.Lines.Text);
      end else
      begin
        ShowAMessage('请点选图片!',procedure begin end);
      end;
    end;
  end;
  if (Sender as TControl) is TSelection then
  begin
    FocusMe(Sender as TControl);
    FIfScrolling:=not FIfScrolling;
    IfScrolling(ScrollBox1,FIfScrolling);
  end;
  if (Sender as TControl) is TImage then
  begin
    LTControlName:=(Sender as TControl).Name;
    FocusMe(Sender as TControl);
    if LTControlName.Indexof('ImgMerging',0,length(LTControlName))>=0 then
    begin
      ShowAMessage((Sender as TControl).Name+'获取了焦点',procedure begin end );
      //Memo1.Lines.Add('图位'+FloatToStr((Sender as TControl).Position.Y)+sLineBreak);
      FImgMergingPositionY:=(Sender as TControl).Position.Y;
      FImg:=TImage(Sender as TControl);
    end;
  end;
end;

procedure TfmxMergeImageAndWords.Memo1ChangeTracking(Sender: TObject);
begin
  Memo1.GoToTextBegin;  Memo1.GoToLineEnd;
  FMemoColums:=Memo1.CaretPosition.Pos;
  if FMemoColums=0 then
    FMemoRows:=0
  else
    FMemoRows:=Ceil(Length((Memo1.Text).Trim)/FMemoColums);

  System.TMonitor.Enter(Memo2,0);
  Memo2.Lines.Clear;
  Memo2.Lines.Add('行'+IntToStr(Memo1.CaretPosition.Line+1)
    +',列'+IntToStr(Memo1.CaretPosition.Pos));
  System.TMonitor.Exit(Memo2);
end;

procedure TfmxMergeImageAndWords.FillImageText(
  AImage:TImage;AText:string);
var ARect: TRectF; ImgPostGapY:Single;
begin
  try
    Memo1.StyledSettings:=Memo1.StyledSettings-[TStyledSetting.Other];
    ImgPostGapY:=FImgMergingPositionY - FScrollBox1ViewportY;
    ARect.Top:=
      ( Selection1.Position.Y
        -(ImgPostGapY) ) *2
      -48
      ;
      //:2比例:原图与显示尺寸的比例:为AImage.Bitmap的高宽与其AImage的高宽
      //:48为窗体顶部工具条LayoutTools的高度
    ARect.Bottom:=ARect.Top+FMemoRows*56.96; //:=(纵横比=1.78)*字号Font.Size
    ARect.Left:=(Selection1.Position.X)*2+20;//:20:左边界调整值
    {$IFDEF POSIX}
      ARect.Right:=720-20-ARect.Left;//720-20//:20*2:左边界调整值
    {$ENDIF POSIX}
    {$IFDEF MSWINDOWS}
      if FMemoRows<=1 then
        ARect.Right:=ARect.Left+(FMemoColums)*32
      else
        ARect.Right:=ARect.Left+(FMemoColums)*32-24*2-20;//720-20//:20*2:左边界调整值
    {$ENDIF MSWINDOWS}

    AImage.Bitmap.Canvas.BeginScene;
    AImage.Bitmap.Canvas.Font.Size:=32; //32:12号默认Memo字号对应写出来的size大小
    AImage.Bitmap.Canvas.FillText(
      ARect,  //:在位图的哪个矩形区域写字
      AText,  //:要写的文字
      true,   //:可换行
      1,      //:不透明
      [],     //:写字的方向[TFillTextFlag.RightToLeft]:TFillTextFlags
      TTextAlign.Leading,//:文字水平齐头
      TTextAlign.Center  //:文字垂直居中
    );
    AImage.Bitmap.Canvas.EndScene;
  finally
    FImg:=nil;
  end;
end;

procedure TfmxMergeImageAndWords.ShareImg(AImage:TImage);
var LFMXShareService:IFMXShareSheetActionsService;
begin
  //FMX.Platform平台服务->FMX.MediaLibrary媒体库接口:
  try
    if TPlatformServices.Current
      .SupportsPlatformService(
        IFMXShareSheetActionsService,
        IInterface(LFMXShareService)
       ) then
    begin //两个动作只能2选1://Share第1个参数:本窗体内任意TControl:
      //LFMXShareService.Share(Memo1,'我发的',nil);//:为空:执行前面的'我发的'
      LFMXShareService.Share(AImage,'我发的',AImage.Bitmap);//:非空:执行后面的AImage.Bitmap
    end;
  finally
  end;
end;

end.

 三、关键要点

1、动态画图为何画出来的图宽度不足

  if not Assigned(ATImageTo.Bitmap) then
  begin
    ATImageTo.Bitmap.Create;
    //:需要传入的ATImageTo设计期:
      //:设置一个虚拟图片来将其撑大,大小为:
      //:AWidthTImageTo,AHeightTImageTo
      //:否则POSIX运行时的宽度显示不全
  end;

2、IOS读取和共享文件

FMX制作长条图并在其图上写字美化等操作,delphi做长条图合并图片几分钟的事

四、运行效果

FMX制作长条图并在其图上写字美化等操作,delphi做长条图合并图片几分钟的事