Skip to content

Commit

Permalink
feat: rotate webcam in Mjpegstreamer-adaptive mode (#923)
Browse files Browse the repository at this point in the history
  • Loading branch information
meteyou authored Aug 1, 2022
1 parent 5ce78fa commit f27a777
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 7 deletions.
23 changes: 23 additions & 0 deletions src/components/settings/SettingsWebcamsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -242,6 +253,7 @@ interface webcamForm {
targetFps: number
urlStream: string
urlSnapshot: string
rotate: number
flipX: boolean
flipY: boolean
}
Expand Down Expand Up @@ -272,6 +284,7 @@ export default class SettingsWebcamsTab extends Mixins(BaseMixin, WebcamMixin) {
targetFps: 15,
urlStream: '',
urlSnapshot: '',
rotate: 0,
flipX: false,
flipY: false,
}
Expand All @@ -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: '' },
{ value: 90, text: '90°' },
{ value: 180, text: '180°' },
{ value: 270, text: '270°' },
]
declare $refs: {
webcamForm: any
}
Expand Down Expand Up @@ -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
Expand All @@ -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,
}
Expand All @@ -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
}
Expand Down
43 changes: 36 additions & 7 deletions src/components/webcams/MjpegstreamerAdaptive.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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()
Expand All @@ -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
}
Expand Down Expand Up @@ -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>
1 change: 1 addition & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,7 @@
"Name": "Name",
"NameAlreadyExists": "Name already exists",
"Required": "required",
"Rotate": "Rotate",
"SaveWebcam": "Save Webcam",
"Service": "Service",
"TargetFPS": "Target FPS",
Expand Down
1 change: 1 addition & 0 deletions src/store/gui/webcams/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface GuiWebcamStateWebcam {
targetFps: number
urlStream: string
urlSnapshot: string
rotate?: number
flipX: boolean
flipY: boolean
}

0 comments on commit f27a777

Please sign in to comment.