捕捉图像(Capturing Images)

Camera元素一个关键特性就是可以用来拍照。我们将在一个简单的定格动画程序中使用到它。在这章中,你将学习如何显示一个视图查找器,截图和追踪拍摄的图片。

用户界面如下所示。它由三部分组成,背景是一个视图查找器,右边有一列按钮,底部有一连串拍摄的图片。我们想要拍摄一系列的图片,然后点击Play Sequence按钮。这将回放图片,并创建一个简单的定格电影。

捕捉图像(Capturing Images) - 图1

相机的视图查找器部分是在VideoOutput中使用一个简单的Camera元素作为资源。这将给用户显示一个来自相机的流媒体视频。

  1. VideoOutput {
  2. anchors.fill: parent
  3. source: camera
  4. }
  5. Camera {
  6. id: camera
  7. }

使用一个水平放置的ListView显示来自ListModel的图片,这个部件叫做imagePaths。在背景中使用一个半透明的Rectangle。

  1. ListModel {
  2. id: imagePaths
  3. }
  4. ListView {
  5. id: listView
  6. anchors.left: parent.left
  7. anchors.right: parent.right
  8. anchors.bottom: parent.bottom
  9. anchors.bottomMargin: 10
  10. height: 100
  11. orientation: ListView.Horizontal
  12. spacing: 10
  13. model: imagePaths
  14. delegate: Image { source: path; fillMode: Image.PreserveAspectFit; height: 100; }
  15. Rectangle {
  16. anchors.fill: parent
  17. anchors.topMargin: -10
  18. color: "black"
  19. opacity: 0.5
  20. }
  21. }

为了拍摄图像,你需要知道Camera元素包含了一组子对象用来完成各种工作。使用Camera.imageCapture用来捕捉图像。当你调用capture方法时,一张图片就被拍摄下来了。Camera.imageCapture的结果将会发送imageCaptured信号,接着发送imageSaved信号。

  1. Button {
  2. id: shotButton
  3. width: 200
  4. height: 75
  5. text: "Take Photo"
  6. onClicked: {
  7. camera.imageCapture.capture();
  8. }
  9. }

为了拦截子元素的信号,需要一个Connections元素。在这个例子中,我们不需要显示预览图片,仅仅只是将结果图片加入底部的ListView中。就如下面的例子展示的一样,图片保存的路径由信号的path参数提供。

  1. Connections {
  2. target: camera.imageCapture
  3. onImageSaved: {
  4. imagePaths.append({"path": path})
  5. listView.positionViewAtEnd();
  6. }
  7. }

为了显示预览,连接imageCaptured信号,并且使用preview信号参数作为Image元素的source。requestId信号参数与imageCaptured和imageSaved一起发送。这个值由capture方法返回。这样,就可以完整的跟踪拍摄的图片了。预览的图片首先被使用,然后替换为保存的图片。然而在这个例子中我们不需要这样做。

最后是自动回放的部分。使用Timer元素来驱动它,并且加上一些JavaScript。_imageIndex变量被用来跟踪当前显示的图片。当最后一张图片被显示时,回放停止。在例子中,当播放序列时,root.state被用来隐藏用户界面。

  1. property int _imageIndex: -1
  2. function startPlayback()
  3. {
  4. root.state = "playing";
  5. setImageIndex(0);
  6. playTimer.start();
  7. }
  8. function setImageIndex(i)
  9. {
  10. _imageIndex = i;
  11. if (_imageIndex >= 0 && _imageIndex < imagePaths.count)
  12. image.source = imagePaths.get(_imageIndex).path;
  13. else
  14. image.source = "";
  15. }
  16. Timer {
  17. id: playTimer
  18. interval: 200
  19. repeat: false
  20. onTriggered: {
  21. if (_imageIndex + 1 < imagePaths.count)
  22. {
  23. setImageIndex(_imageIndex + 1);
  24. playTimer.start();
  25. }
  26. else
  27. {
  28. setImageIndex(-1);
  29. root.state = "";
  30. }
  31. }
  32. }