feat: rotate webcam in Mjpegstreamer-adaptive mode (#923)
This commit is contained in:
parent
5ce78fae4a
commit
f27a7770a9
@ -163,6 +163,17 @@
|
||||
:label="$t('Settings.WebcamsTab.TargetFPS')"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row v-if="form.service === 'mjpegstreamer-adaptive'">
|
||||
<v-col class="py-2">
|
||||
<v-select
|
||||
v-model="form.rotate"
|
||||
:items="rotateItems"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
:label="$t('Settings.WebcamsTab.Rotate')"></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col class="py-1">
|
||||
<v-checkbox
|
||||
@ -242,6 +253,7 @@ interface webcamForm {
|
||||
targetFps: number
|
||||
urlStream: string
|
||||
urlSnapshot: string
|
||||
rotate: number
|
||||
flipX: boolean
|
||||
flipY: boolean
|
||||
}
|
||||
@ -272,6 +284,7 @@ export default class SettingsWebcamsTab extends Mixins(BaseMixin, WebcamMixin) {
|
||||
targetFps: 15,
|
||||
urlStream: '',
|
||||
urlSnapshot: '',
|
||||
rotate: 0,
|
||||
flipX: false,
|
||||
flipY: false,
|
||||
}
|
||||
@ -281,6 +294,13 @@ export default class SettingsWebcamsTab extends Mixins(BaseMixin, WebcamMixin) {
|
||||
unique: (value: string) => !this.existsWebcamName(value) || this.$t('Settings.WebcamsTab.NameAlreadyExists'),
|
||||
}
|
||||
|
||||
private rotateItems = [
|
||||
{ value: 0, text: '0°' },
|
||||
{ value: 90, text: '90°' },
|
||||
{ value: 180, text: '180°' },
|
||||
{ value: 270, text: '270°' },
|
||||
]
|
||||
|
||||
declare $refs: {
|
||||
webcamForm: any
|
||||
}
|
||||
@ -348,6 +368,7 @@ export default class SettingsWebcamsTab extends Mixins(BaseMixin, WebcamMixin) {
|
||||
this.form.targetFps = webcam.targetFps
|
||||
this.form.urlStream = webcam.urlStream
|
||||
this.form.urlSnapshot = webcam.urlSnapshot
|
||||
this.form.rotate = webcam.rotate ?? 0
|
||||
this.form.flipX = webcam.flipX
|
||||
this.form.flipY = webcam.flipY
|
||||
|
||||
@ -368,6 +389,7 @@ export default class SettingsWebcamsTab extends Mixins(BaseMixin, WebcamMixin) {
|
||||
targetFps: this.form.targetFps,
|
||||
urlStream: this.form.urlStream,
|
||||
urlSnapshot: this.form.urlSnapshot,
|
||||
rotate: this.form.rotate,
|
||||
flipX: this.form.flipX,
|
||||
flipY: this.form.flipY,
|
||||
}
|
||||
@ -392,6 +414,7 @@ export default class SettingsWebcamsTab extends Mixins(BaseMixin, WebcamMixin) {
|
||||
this.form.targetFps = 15
|
||||
this.form.urlStream = '/webcam/?action=stream'
|
||||
this.form.urlSnapshot = '/webcam/?action=snapshot'
|
||||
this.form.rotate = 0
|
||||
this.form.flipX = false
|
||||
this.form.flipY = false
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Component from 'vue-class-component'
|
||||
import { Mixins, Prop } from 'vue-property-decorator'
|
||||
import { Mixins, Prop, Watch } from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
|
||||
@Component
|
||||
@ -70,8 +70,9 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) {
|
||||
}
|
||||
|
||||
let transforms = ''
|
||||
if ('flipX' in this.camSettings && this.camSettings.flipX) transforms += ' scaleX(-1)'
|
||||
if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)'
|
||||
if (this.camSettings.flipX ?? false) transforms += ' scaleX(-1)'
|
||||
if (this.camSettings.flipY ?? false) transforms += ' scaleY(-1)'
|
||||
if ((this.camSettings.rotate ?? 0) === 180) transforms += ' rotate(180deg)'
|
||||
if (transforms.trimStart().length) output.transform = transforms.trimStart()
|
||||
|
||||
if (this.aspectRatio) output.aspectRatio = this.aspectRatio
|
||||
@ -83,6 +84,10 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) {
|
||||
return this.currentFPS < 10 ? '0' + this.currentFPS.toString() : this.currentFPS
|
||||
}
|
||||
|
||||
get rotate() {
|
||||
return [90, 270].includes(this.camSettings.rotate ?? 0)
|
||||
}
|
||||
|
||||
refreshFrame() {
|
||||
if (this.isVisible) {
|
||||
this.refresh = new Date().getTime()
|
||||
@ -105,12 +110,31 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) {
|
||||
const frame: any = await this.loadImage(url.toString())
|
||||
|
||||
canvas.width = canvas.clientWidth
|
||||
canvas.height = canvas.clientWidth * (frame.height / frame.width)
|
||||
if (this.aspectRatio === null) {
|
||||
this.aspectRatio = frame.width / frame.height
|
||||
if (this.rotate) {
|
||||
if (this.aspectRatio === null) this.aspectRatio = frame.height / frame.width
|
||||
canvas.height = canvas.clientWidth / (frame.height / frame.width)
|
||||
} else {
|
||||
if (this.aspectRatio === null) this.aspectRatio = frame.width / frame.height
|
||||
canvas.height = canvas.clientWidth * (frame.width / frame.height)
|
||||
}
|
||||
|
||||
await ctx?.drawImage(frame, 0, 0, frame.width, frame.height, 0, 0, canvas.width, canvas.height)
|
||||
if (this.rotate) {
|
||||
const scale = canvas.height / frame.width
|
||||
const x = canvas.width / 2
|
||||
const y = canvas.height / 2
|
||||
ctx.translate(x, y)
|
||||
ctx.rotate((this.camSettings.rotate * Math.PI) / 180)
|
||||
await ctx?.drawImage(
|
||||
frame,
|
||||
(-frame.width / 2) * scale,
|
||||
(-frame.height / 2) * scale,
|
||||
frame.width * scale,
|
||||
frame.height * scale
|
||||
)
|
||||
ctx.rotate(-((this.camSettings.rotate * Math.PI) / 180))
|
||||
ctx.translate(-x, -y)
|
||||
} else await ctx?.drawImage(frame, 0, 0, frame.width, frame.height, 0, 0, canvas.width, canvas.height)
|
||||
|
||||
this.isLoaded = true
|
||||
}
|
||||
|
||||
@ -190,5 +214,10 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) {
|
||||
clearTimeout(this.timer)
|
||||
this.timer = undefined
|
||||
}
|
||||
|
||||
@Watch('camSettings', { immediate: true, deep: true })
|
||||
camSettingsChanged() {
|
||||
this.aspectRatio = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -950,6 +950,7 @@
|
||||
"Name": "Name",
|
||||
"NameAlreadyExists": "Name already exists",
|
||||
"Required": "required",
|
||||
"Rotate": "Rotate",
|
||||
"SaveWebcam": "Save Webcam",
|
||||
"Service": "Service",
|
||||
"TargetFPS": "Target FPS",
|
||||
|
@ -12,6 +12,7 @@ export interface GuiWebcamStateWebcam {
|
||||
targetFps: number
|
||||
urlStream: string
|
||||
urlSnapshot: string
|
||||
rotate?: number
|
||||
flipX: boolean
|
||||
flipY: boolean
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user