mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-25 15:44:04 -06:00
Remove CameraImageProvider and NetworkCamera
This commit is contained in:
parent
c187b6a25c
commit
484b1e5ec6
3 changed files with 0 additions and 154 deletions
|
@ -1,40 +0,0 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
|
||||||
|
|
||||||
from PyQt5.QtGui import QImage
|
|
||||||
from PyQt5.QtQuick import QQuickImageProvider
|
|
||||||
from PyQt5.QtCore import QSize
|
|
||||||
|
|
||||||
from UM.Application import Application
|
|
||||||
|
|
||||||
## Creates screenshots of the current scene.
|
|
||||||
class CameraImageProvider(QQuickImageProvider):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__(QQuickImageProvider.Image)
|
|
||||||
|
|
||||||
## Request a new image.
|
|
||||||
#
|
|
||||||
# The image will be taken using the current camera position.
|
|
||||||
# Only the actual objects in the scene will get rendered. Not the build
|
|
||||||
# plate and such!
|
|
||||||
# \param id The ID for the image to create. This is the requested image
|
|
||||||
# source, with the "image:" scheme and provider identifier removed. It's
|
|
||||||
# a Qt thing, they'll provide this parameter.
|
|
||||||
# \param size The dimensions of the image to scale to.
|
|
||||||
def requestImage(self, id, size):
|
|
||||||
for output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices():
|
|
||||||
try:
|
|
||||||
image = output_device.activePrinter.camera.getImage()
|
|
||||||
if image.isNull():
|
|
||||||
image = QImage()
|
|
||||||
|
|
||||||
return image, QSize(15, 15)
|
|
||||||
except AttributeError:
|
|
||||||
try:
|
|
||||||
image = output_device.activeCamera.getImage()
|
|
||||||
|
|
||||||
return image, QSize(15, 15)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return QImage(), QSize(15, 15)
|
|
|
@ -96,7 +96,6 @@ from . import PrintInformation
|
||||||
from . import CuraActions
|
from . import CuraActions
|
||||||
from cura.Scene import ZOffsetDecorator
|
from cura.Scene import ZOffsetDecorator
|
||||||
from . import CuraSplashScreen
|
from . import CuraSplashScreen
|
||||||
from . import CameraImageProvider
|
|
||||||
from . import PrintJobPreviewImageProvider
|
from . import PrintJobPreviewImageProvider
|
||||||
from . import MachineActionManager
|
from . import MachineActionManager
|
||||||
|
|
||||||
|
@ -525,7 +524,6 @@ class CuraApplication(QtApplication):
|
||||||
CuraApplication.Created = True
|
CuraApplication.Created = True
|
||||||
|
|
||||||
def _onEngineCreated(self):
|
def _onEngineCreated(self):
|
||||||
self._qml_engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider())
|
|
||||||
self._qml_engine.addImageProvider("print_job_preview", PrintJobPreviewImageProvider.PrintJobPreviewImageProvider())
|
self._qml_engine.addImageProvider("print_job_preview", PrintJobPreviewImageProvider.PrintJobPreviewImageProvider())
|
||||||
|
|
||||||
@pyqtProperty(bool)
|
@pyqtProperty(bool)
|
||||||
|
|
|
@ -1,112 +0,0 @@
|
||||||
from UM.Logger import Logger
|
|
||||||
|
|
||||||
from PyQt5.QtCore import QUrl, pyqtProperty, pyqtSignal, QObject, pyqtSlot
|
|
||||||
from PyQt5.QtGui import QImage
|
|
||||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager
|
|
||||||
|
|
||||||
|
|
||||||
class NetworkCamera(QObject):
|
|
||||||
newImage = pyqtSignal()
|
|
||||||
|
|
||||||
def __init__(self, target = None, parent = None):
|
|
||||||
super().__init__(parent)
|
|
||||||
self._stream_buffer = b""
|
|
||||||
self._stream_buffer_start_index = -1
|
|
||||||
self._manager = None
|
|
||||||
self._image_request = None
|
|
||||||
self._image_reply = None
|
|
||||||
self._image = QImage()
|
|
||||||
|
|
||||||
self._target = target
|
|
||||||
self._started = False
|
|
||||||
|
|
||||||
@pyqtSlot(str)
|
|
||||||
def setTarget(self, target):
|
|
||||||
restart_required = False
|
|
||||||
if self._started:
|
|
||||||
self.stop()
|
|
||||||
restart_required = True
|
|
||||||
|
|
||||||
self._target = target
|
|
||||||
|
|
||||||
if restart_required:
|
|
||||||
self.start()
|
|
||||||
|
|
||||||
@pyqtProperty(QImage, notify=newImage)
|
|
||||||
def latestImage(self):
|
|
||||||
return self._image
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def start(self):
|
|
||||||
# Ensure that previous requests (if any) are stopped.
|
|
||||||
self.stop()
|
|
||||||
if self._target is None:
|
|
||||||
Logger.log("w", "Unable to start camera stream without target!")
|
|
||||||
return
|
|
||||||
self._started = True
|
|
||||||
url = QUrl(self._target)
|
|
||||||
self._image_request = QNetworkRequest(url)
|
|
||||||
if self._manager is None:
|
|
||||||
self._manager = QNetworkAccessManager()
|
|
||||||
|
|
||||||
self._image_reply = self._manager.get(self._image_request)
|
|
||||||
self._image_reply.downloadProgress.connect(self._onStreamDownloadProgress)
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def stop(self):
|
|
||||||
self._stream_buffer = b""
|
|
||||||
self._stream_buffer_start_index = -1
|
|
||||||
|
|
||||||
if self._image_reply:
|
|
||||||
try:
|
|
||||||
# disconnect the signal
|
|
||||||
try:
|
|
||||||
self._image_reply.downloadProgress.disconnect(self._onStreamDownloadProgress)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
# abort the request if it's not finished
|
|
||||||
if not self._image_reply.isFinished():
|
|
||||||
self._image_reply.close()
|
|
||||||
except Exception as e: # RuntimeError
|
|
||||||
pass # It can happen that the wrapped c++ object is already deleted.
|
|
||||||
|
|
||||||
self._image_reply = None
|
|
||||||
self._image_request = None
|
|
||||||
|
|
||||||
self._manager = None
|
|
||||||
|
|
||||||
self._started = False
|
|
||||||
|
|
||||||
def getImage(self):
|
|
||||||
return self._image
|
|
||||||
|
|
||||||
## Ensure that close gets called when object is destroyed
|
|
||||||
def __del__(self):
|
|
||||||
self.stop()
|
|
||||||
|
|
||||||
def _onStreamDownloadProgress(self, bytes_received, bytes_total):
|
|
||||||
# An MJPG stream is (for our purpose) a stream of concatenated JPG images.
|
|
||||||
# JPG images start with the marker 0xFFD8, and end with 0xFFD9
|
|
||||||
if self._image_reply is None:
|
|
||||||
return
|
|
||||||
self._stream_buffer += self._image_reply.readAll()
|
|
||||||
|
|
||||||
if len(self._stream_buffer) > 2000000: # No single camera frame should be 2 Mb or larger
|
|
||||||
Logger.log("w", "MJPEG buffer exceeds reasonable size. Restarting stream...")
|
|
||||||
self.stop() # resets stream buffer and start index
|
|
||||||
self.start()
|
|
||||||
return
|
|
||||||
|
|
||||||
if self._stream_buffer_start_index == -1:
|
|
||||||
self._stream_buffer_start_index = self._stream_buffer.indexOf(b'\xff\xd8')
|
|
||||||
stream_buffer_end_index = self._stream_buffer.lastIndexOf(b'\xff\xd9')
|
|
||||||
# If this happens to be more than a single frame, then so be it; the JPG decoder will
|
|
||||||
# ignore the extra data. We do it like this in order not to get a buildup of frames
|
|
||||||
|
|
||||||
if self._stream_buffer_start_index != -1 and stream_buffer_end_index != -1:
|
|
||||||
jpg_data = self._stream_buffer[self._stream_buffer_start_index:stream_buffer_end_index + 2]
|
|
||||||
self._stream_buffer = self._stream_buffer[stream_buffer_end_index + 2:]
|
|
||||||
self._stream_buffer_start_index = -1
|
|
||||||
self._image.loadFromData(jpg_data)
|
|
||||||
|
|
||||||
self.newImage.emit()
|
|
Loading…
Add table
Add a link
Reference in a new issue