简体   繁体   English

重新激活时 Firemonkey TCameraComponent 质量发生变化

[英]Firemonkey TCameraComponent quality change when reactivated

I'm building a barcode reader application in Delphi 10.1 Berlin with firemonkey for Android.我正在使用适用于 Android 的 firemonkey 在 Delphi 10.1 Berlin 中构建条形码阅读器应用程序。 Based on the CameraComponent sample and using the ZXing library , it was possible to read the barcode.基于CameraComponent 示例并使用ZXing 库,可以读取条码。

To initialize the camera, I'm using this code:要初始化相机,我使用以下代码:

procedure TfrmMain.btnOpenReaderClick(Sender: TObject);
begin
  CameraComponent.Active := False;
  CameraComponent.FocusMode := FMX.Media.TFocusMode.ContinuousAutoFocus;
  CameraComponent.Quality := TVideoCaptureQuality.MediumQuality;
  CameraComponent.Active := True;
  CameraComponent.SampleBufferToBitmap(imgCamera.Bitmap, True);
end;

To scan the barcode, I'm running this:要扫描条形码,我正在运行:

procedure TfrmMain.GetImage;
var
  ReadResult: TReadResult;
begin
  CameraComponent.SampleBufferToBitmap(imgCamera.Bitmap, True);

  if (FScanInProgress) then
    Exit;

  { This code will take every 4 frames. }
  inc(FFrameTake);
  if (FFrameTake mod 4 <> 0) then
    Exit;

  ReadResult := nil;

  ITask(TTask.Create(
    procedure
    begin
      try
        FScanInProgress := True;

        ReadResult := FScanManager.Scan(imgCamera.Bitmap);

        TThread.Synchronize(nil,
          procedure
          begin
          try
            if (ReadResult <> nil) then
            begin
              Label1.Text := ReadResult.text;
              CameraComponent.Active := False;
            end;
          except
            on E: Exception do
              ShowMessage(E.Message);
          end;
        end);
      finally
        ReadResult.Free;
        imgCamera.Bitmap.Free;
        FScanInProgress := false;
      end;
    end)).Start;
end;

After reading the barcode, when I set CameraComponent.Active := True;读取条码后,当我设置CameraComponent.Active := True; to start reading a new barcode, the CameraComponent quality is automatically set to high quality, even if the property is set as medium quality when starting the component.要开始读取新条码,CameraComponent 质量会自动设置为高质量,即使在启动组件时将该属性设置为中等质量。 This causes the preview of the camera to show at low frame rate.这会导致相机的预览以低帧率显示。 Is there a way to set the default capture setting to medium when reactivating the CameraComponent?重新激活 CameraComponent 时,有没有办法将默认捕获设置设置为中等?

Yes you have to setup the camera before you activate it.是的,您必须在激活相机之前对其进行设置。 Like:喜欢:

CameraComponent1.Quality := TVideoCaptureQuality.MediumQuality;
CameraComponent1.Active := true;

btw: I only stop the camera on Android and not with IOS.顺便说一句:我只在 Android 上停止相机,而不是在 IOS 上。 That's too slow.那太慢了。 I'll close the camera with IOS on application stop.我将在应用程序停止时使用 IOS 关闭相机。 The canvas is not updated anymore then.画布不再更新。

procedure TdmGetBarcodeStatus.StopCamera();
begin
    CameraIsActivated := false;
{$IFDEF ANDROID}
    CameraComponent1.Active := false;
{$ENDIF}
end;

Also implement the camera optimization technique in the link provided by Dave.还在 Dave 提供的链接中实现相机优化技术。 Its speeds up the camera frame rate tremendously.它极大地加快了相机的帧速率。

For a little, I think better scan strategy you can run the image scan progress in a continuous Task.有一点,我认为更好的扫描策略可以在连续任务中运行图像扫描进度。

This is how it can be done:这是如何做到的:

FParseImagesInProgress is a flag which controls the parsing of the images coming from a TRectangle (RectImage.Fill.Bitmap.Bitmap). FParseImagesInProgress 是一个标志,它控制来自 TRectangle (RectImage.Fill.Bitmap.Bitmap) 的图像的解析。 Before you stop the camera you set FParseImagesInProgress to false.在停止相机之前,将 FParseImagesInProgress 设置为 false。

procedure TFormCamera.StartParseImageTaskService();
var
    ReadResult: TReadResult;
begin

    if FParseImagesInProgress then
        Exit;

    FParseImagesInProgress := true;

    TTask.Run(
        procedure
        var
            hints: TDictionary<TDecodeHintType, TObject>;
            PossibleFormats: TList<TBarcodeFormat>;
            ScanManager: TScanManager;
            scanBitmap: TBitmap;
        begin
            PossibleFormats := TList<TBarcodeFormat>.Create();
            PossibleFormats.Add(TBarcodeFormat.QR_CODE);

            hints := TDictionary<TDecodeHintType, TObject>.Create();
            hints.Add(TDecodeHintType.POSSIBLE_FORMATS, PossibleFormats);

            ScanManager := TScanManager.Create(TBarcodeFormat.CODE_128, hints);
            scanBitmap := TBitmap.Create();

            try

                while (FParseImagesInProgress) do
                begin

                    ReadResult := nil;

                    try

                        TThread.Synchronize(nil,
                            procedure
                            begin
                                scanBitmap.Assign(RectImage.Fill.Bitmap.Bitmap);
                            end);

                        ReadResult := ScanManager.Scan(scanBitmap);

                    except
                        if Assigned(ReadResult) then
                            FreeAndNil(ReadResult);
                    end;

                    if Assigned(ReadResult) then
                    begin
                        TThread.Synchronize(nil,
                            procedure
                            begin
                                // PlaySound(TATSounds.Good);
                                MarkBarcode(ReadResult, TalphaColors.Deepskyblue);

                                if WasNotLastBarcodeInTimeWindow(ReadResult.Text) then
                                    FBarcodeRequestManager.RequestBarcodeStatus(ReadResult.Text, HotMember, 'myDevice', HotUser,
                                        HotPassword);

                                FLastBarcode := ReadResult.Text;

                            end);

                        FreeAndNil(ReadResult);
                    end;

                    Sleep(MS_BETWEEN_SCAN_FRAMES);

                end; // while

            finally

                if Assigned(scanBitmap) then
                    scanBitmap := nil;

                FreeAndNil(ScanManager);

                if Assigned(PossibleFormats) then
                begin
                    PossibleFormats.Clear;
                    PossibleFormats := nil;
                end;

                if Assigned(ReadResult) then
                    FreeAndNil(ReadResult);

            end;

        end); // end TTask

end;

It is really fast.它真的很快。

Anyway, hope it helps!总之,希望有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM