Commit dabc86aa authored by Flemming Stäbler's avatar Flemming Stäbler
Browse files

Frame TAR Export

parent 75fabd7b
......@@ -12,7 +12,6 @@
},
"dependencies": {
"core-js": "^3.16.1",
"jszip": "^3.7.1",
"lru_map": "^0.4.1",
"marked": "^2.1.3",
"vue": "^2.6.14",
......
......@@ -311,6 +311,12 @@
d="M 1 1.5 C 0.72386906 1.5000276 0.50002761 1.7238691 0.5 2 L 0.5 10 C 0.50002761 10.276131 0.72386906 10.499972 1 10.5 L 11 10.5 C 11.276131 10.499972 11.499972 10.276131 11.5 10 L 11.5 2 C 11.499972 1.7238691 11.276131 1.5000276 11 1.5 L 1 1.5 z M 1.4882812 2 A 0.5 0.5 0 0 1 1.5 2 L 2 2 A 0.5 0.5 0 0 1 2.5 2.5 A 0.5 0.5 0 0 1 2 3 L 1.5 3 A 0.5 0.5 0 0 1 1 2.5 A 0.5 0.5 0 0 1 1.4882812 2 z M 3.9882812 2 A 0.5 0.5 0 0 1 4 2 L 5 2 A 0.5 0.5 0 0 1 5.5 2.5 A 0.5 0.5 0 0 1 5 3 L 4 3 A 0.5 0.5 0 0 1 3.5 2.5 A 0.5 0.5 0 0 1 3.9882812 2 z M 6.9882812 2 A 0.5 0.5 0 0 1 7 2 L 8 2 A 0.5 0.5 0 0 1 8.5 2.5 A 0.5 0.5 0 0 1 8 3 L 7 3 A 0.5 0.5 0 0 1 6.5 2.5 A 0.5 0.5 0 0 1 6.9882812 2 z M 9.9882812 2 A 0.5 0.5 0 0 1 10 2 L 10.5 2 A 0.5 0.5 0 0 1 11 2.5 A 0.5 0.5 0 0 1 10.5 3 L 10 3 A 0.5 0.5 0 0 1 9.5 2.5 A 0.5 0.5 0 0 1 9.9882812 2 z M 2 3.5 L 10 3.5 C 10.276131 3.5000276 10.499972 3.7238691 10.5 4 L 10.5 8 C 10.499972 8.2761309 10.276131 8.4999724 10 8.5 L 2 8.5 C 1.7238691 8.4999724 1.5000276 8.2761309 1.5 8 L 1.5 4 C 1.5000276 3.7238691 1.7238691 3.5000276 2 3.5 z M 5.9941406 3.625 C 5.473537 3.6287376 4.9729044 3.9043458 4.7011719 4.375 A 0.5 0.5 0 0 0 4.8847656 5.0566406 A 0.5 0.5 0 0 0 5.5664062 4.875 C 5.6893904 4.661986 5.940741 4.5701709 6.171875 4.6542969 C 6.403009 4.7384229 6.5348985 4.9687065 6.4921875 5.2109375 C 6.4494755 5.4531675 6.245967 5.625 6 5.625 A 0.5 0.5 0 0 0 5.5 6.125 L 5.5 6.625 A 0.5 0.5 0 0 0 6 7.125 A 0.5 0.5 0 0 0 6.5 6.625 L 6.5 6.5351562 C 6.9966467 6.35766 7.3810049 5.9267037 7.4765625 5.3847656 C 7.6023915 4.6711536 7.1945919 3.9626777 6.5136719 3.7148438 C 6.3434419 3.6528848 6.1676752 3.6237541 5.9941406 3.625 z M 5.9882812 7.4238281 A 0.5 0.5 0 0 0 5.5 7.9238281 A 0.5 0.5 0 0 0 6 8.4238281 A 0.5 0.5 0 0 0 6.5 7.9238281 A 0.5 0.5 0 0 0 6 7.4238281 A 0.5 0.5 0 0 0 5.9882812 7.4238281 z M 1.4882812 9 A 0.5 0.5 0 0 1 1.5 9 L 2 9 A 0.5 0.5 0 0 1 2.5 9.5 A 0.5 0.5 0 0 1 2 10 L 1.5 10 A 0.5 0.5 0 0 1 1 9.5 A 0.5 0.5 0 0 1 1.4882812 9 z M 3.9882812 9 A 0.5 0.5 0 0 1 4 9 L 5 9 A 0.5 0.5 0 0 1 5.5 9.5 A 0.5 0.5 0 0 1 5 10 L 4 10 A 0.5 0.5 0 0 1 3.5 9.5 A 0.5 0.5 0 0 1 3.9882812 9 z M 6.9882812 9 A 0.5 0.5 0 0 1 7 9 L 8 9 A 0.5 0.5 0 0 1 8.5 9.5 A 0.5 0.5 0 0 1 8 10 L 7 10 A 0.5 0.5 0 0 1 6.5 9.5 A 0.5 0.5 0 0 1 6.9882812 9 z M 9.9882812 9 A 0.5 0.5 0 0 1 10 9 L 10.5 9 A 0.5 0.5 0 0 1 11 9.5 A 0.5 0.5 0 0 1 10.5 10 L 10 10 A 0.5 0.5 0 0 1 9.5 9.5 A 0.5 0.5 0 0 1 9.9882812 9 z "
transform="translate(-82,-54)" />
</symbol>
<symbol
id="record">
<path
d="M 6 1.5 C 3.5206409 1.5 1.5 3.5206409 1.5 6 C 1.5 8.4793591 3.5206409 10.5 6 10.5 C 8.4793591 10.5 10.5 8.4793591 10.5 6 C 10.5 3.5206409 8.4793591 1.5 6 1.5 z M 6 2.5 C 7.9389189 2.5 9.5 4.0610811 9.5 6 C 9.5 7.9389189 7.9389189 9.5 6 9.5 C 4.0610811 9.5 2.5 7.9389189 2.5 6 C 2.5 4.0610811 4.0610811 2.5 6 2.5 z "
id="path1127" />
</symbol>
</defs>
<sodipodi:namedview
id="base"
......@@ -319,9 +325,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="9.3227675"
inkscape:cx="-19.726287"
inkscape:cy="10.154487"
inkscape:zoom="37.29107"
inkscape:cx="20.759265"
inkscape:cy="25.506889"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
......@@ -974,5 +980,13 @@
width="100%"
height="100%"
transform="translate(164.51172,121)" />
<use
xlink:href="#record"
id="use1136"
transform="translate(10,25.5)"
x="0"
y="0"
width="100%"
height="100%" />
</g>
</svg>
......@@ -27,7 +27,7 @@
<a href="https://nubes.helmholtz-berlin.de/s/jDtA3rEMzzSJGys" target="_blank"><div title="User Manual..." class="button symbol continue"><SvgIcon name="book-help"></SvgIcon></div></a>
</div>
<div class="button-group">
<div title="Record" class="button symbol continue" @click="showRecording">R</div>
<div title="Record" class="button symbol continue" @click="showRecording"><SvgIcon name="record"></SvgIcon></div>
</div>
<!--<div class="button-group">
......
......@@ -5,21 +5,20 @@
<div>Playback: {{isPlayingBack}} ({{playbackEventCount}} actions)</div>
<div id="recording-buttons" class="row">
<div class="button symbol continue" @click="start()"><SvgIcon name="fast-start"></SvgIcon></div>
<div class="button symbol continue" :recording="isRecording" @mousedown.stop="record()">R</div>
<div class="button symbol continue" :recording="isRecording" @mousedown.stop="record()"><SvgIcon name="record"></SvgIcon></div>
<div class="button symbol continue" @click="playpause()"><span v-if="isPlayingBack"><SvgIcon name="pause"></SvgIcon></span><span v-else><SvgIcon name="play"></SvgIcon></span></div>
<div class="button symbol continue" @click="end()"><SvgIcon name="fast-end"></SvgIcon></div>
</div>
<div>
<progress style="width: 100%;" :max="recordingEventCount" :value="playbackEventCount"></progress>
</div>
<div class="button" @click="frameRecord()">Export ZIP of PNGs</div>
<div class="button" @click="frameRecord()">Export TAR of PNGs</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';
import SvgIcon from './guikit/svgIcon.vue';
import { FormattingService } from '../services/FormattingService';
import { Services } from '../services/Services';
import { PlaybackStateEvent, RecordingStateEvent } from '../services/RecordingService';
@Component({
......
//This file is licensed under EUPL v1.2 as part of the Digital Earth Viewer
import { FormattingService } from "@/services/FormattingService";
export class TarBall {
static gen_header(name: string, size: number): ArrayBuffer {
let buf = new Uint8Array(512);
let tenc = new TextEncoder();
// filename
tenc.encode(name).forEach((c, i) => {
if(i < 99){
buf[i] = c;
}
});
// permissions
tenc.encode("0100777").forEach((c, i) => {
if(i < 7){
buf[i + 100] = c;
}
});
// user & group
tenc.encode("0000000").forEach((c, i) => {
if(i < 7){
buf[i + 108] = c;
buf[i + 116] = c;
}
});
// file size
tenc.encode(FormattingService.leftpad(size.toString(8), "0", 11)).forEach((c, i) => {
if(i < 11){
buf[i + 124] = c;
}
});
// file creation date (now)
tenc.encode(FormattingService.leftpad(((Date.now() / 1000) | 0).toString(8), "0", 11)).forEach((c, i) => {
if(i < 11){
buf[i + 136] = c;
}
});
// 8 spaces as placeholder for the header checksum
tenc.encode(" ").forEach((c, i) => {
if(i < 8){
buf[i + 148] = c;
}
});
// type = 0
buf[156] = 48;
// magic
tenc.encode("ustar").forEach((c, i) => {
if(i < 5){
buf[i + 257] = c;
}
});
// version
tenc.encode("00").forEach((c, i) => {
if(i < 2){
buf[i + 263] = c;
}
});
// actual checksum
let checksum = 0;
buf.forEach(c => {
checksum += c;
});
// set all checksum bits to 0x00
for(var i = 148; i < 156; i++){
buf[i] = 0;
}
// overwrite with string
tenc.encode(checksum.toString(8)).forEach((c, i) => {
if(i < 7){
buf[i + 148] = c;
}
});
return buf.buffer;
}
}
\ No newline at end of file
//This file is licensed under EUPL v1.2 as part of the Digital Earth Viewer
import { ServiceBarrier, Services } from "./Services";
import { SynchronizationMessageEvent } from "./SynchronizationService";
import {SynchronizationMessage} from "./SynchronizationService";
import JSZip from "jszip";
import { FormattingService } from "./FormattingService";
import { thresholdScott } from "@/d3";
import { TarBall } from "@/modules/tar";
export class RecordingMessage{
message: SynchronizationMessage;
......@@ -45,7 +45,7 @@ export class RecordingService extends EventTarget{
private playbackOffsetTime: number = 0;
private callback_id = null;
private zipInstance: JSZip = null;
private frameArray: (Blob | ArrayBuffer)[] = null;
private render_frame_number: number = 0;
public startRecording(){
......@@ -67,7 +67,8 @@ export class RecordingService extends EventTarget{
public startPlayback(with_frame_capture: boolean = false){
if(this.recordingActions.length == 0) return;
if(with_frame_capture){
this.zipInstance = JSZip();
this.frameArray = [];
console.log(this.frameArray);
Services.FlexibleTimeBaseService.set_lock_state(true);
}
this.stopRecording();
......@@ -100,18 +101,15 @@ export class RecordingService extends EventTarget{
}
private saveZipFrames(){
if(this.zipInstance){
console.log("Saving zip file...");
this.zipInstance.generateAsync({type: "blob"}, (m) => {
console.log(m.percent + "%");
}).then((b) => {
console.log(this.frameArray);
if(this.frameArray){
let b = new Blob(this.frameArray);
let a_elem = document.getElementById('downloadlink') as HTMLAnchorElement;
a_elem.setAttribute("download", "frames.zip");
a_elem.setAttribute("download", "frames.tar");
a_elem.setAttribute("href", URL.createObjectURL(b));
a_elem.click();
});
}
this.zipInstance = null;
this.frameArray = null;
this.render_frame_number = 0;
}
......@@ -164,12 +162,16 @@ export class RecordingService extends EventTarget{
}
public acceptsFrames(): boolean {
return !!this.zipInstance
return !(this.frameArray === null);
}
public submitFrameBlob(b: Blob) {
if(!this.zipInstance)return;
this.zipInstance.file(FormattingService.leftpad("" + this.render_frame_number , "0", 5) + ".png", b, {binary: true});
console.log(this.frameArray);
if(!this.frameArray)return;
this.frameArray.push(TarBall.gen_header(FormattingService.leftpad("" + this.render_frame_number , "0", 5) + ".png", b.size));
this.frameArray.push(b);
this.frameArray.push(new ArrayBuffer(512 - (b.size % 512)));
console.log(this.frameArray);
this.render_frame_number += 1;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment