Skip to content

Commit

Permalink
tar from dataurl example
Browse files Browse the repository at this point in the history
  • Loading branch information
reindernijhoff committed May 27, 2024
1 parent 41eecfc commit 73487ab
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 74 deletions.
15 changes: 11 additions & 4 deletions example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
.grid-item {
margin: 0;
padding: 0;
width: 50vw;
width: 33.333333vw;
height: 50vh;
line-height: 0;
position: relative;
Expand Down Expand Up @@ -57,14 +57,21 @@
<body>
<div class="grid-item">
<div class="control">
<button class="control-button" id="prev-button">&lt;</button>
<input type="range" min="0" max="1" value="0" step="0.0001" class="control-slider" id="slider-input">
<button class="control-button" id="next-button">&gt;</button>
<button class="control-button" id="prev-button-1">&lt;</button>
<input type="range" min="0" max="1" value="0" step="0.0001" class="control-slider" id="slider-input-1">
<button class="control-button" id="next-button-1">&gt;</button>
</div>
</div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item"></div>
<div class="grid-item">
<div class="control">
<button class="control-button" id="prev-button-2">&lt;</button>
<input type="range" min="0" max="1" value="0" step="0.0001" class="control-slider" id="slider-input-2">
<button class="control-button" id="next-button-2">&gt;</button>
</div>
</div>

<script type="module" src="./src/index.js"></script>
</body>
Expand Down
11 changes: 0 additions & 11 deletions example/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 65 additions & 0 deletions example/src/exampleLoadTar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {FastImageSequence} from '../../src/index';

const prevButton = document.getElementById('prev-button-2');
const nextButton = document.getElementById('next-button-2');
const progress = document.getElementById('slider-input-2');

function blobToDataURL(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = _e => resolve(reader.result);
reader.onerror = _e => reject(reader.error);
reader.onabort = _e => reject(new Error("Read aborted"));
reader.readAsDataURL(blob);
});
}

export async function initExampleLoadTar(container) {
// load tar file with lowres previews
fetch('lowrespreviews.tar').then(async (response) => {
const blob = await response.blob();
const dataURL = await blobToDataURL(blob);

const fastImageSequence = new FastImageSequence(container, {
name: 'PlayWithControlTest',
frames: 89,
src: [
{
tarURL: dataURL,
imageURL: (i) => `${('' + (i + 1)).padStart(4, '0')}.jpg`,
}
],
// optional arguments:
loop: true, // default false
objectFit: 'contain', // default 'cover'
fillStyle: '#00000000', // default #00000000
clearCanvas: false, // default false
showDebugInfo: true,
});

await fastImageSequence.ready();

fastImageSequence.tick((dt) => {
if (fastImageSequence.playing) {
progress.value = fastImageSequence.progress;
}
});

prevButton.addEventListener('click', () => {
fastImageSequence.play(-30);
});
nextButton.addEventListener('click', () => {
fastImageSequence.play(30);
});
progress.addEventListener('mousedown', (e) => {
fastImageSequence.stop();
});
progress.addEventListener('input', () => {
if (fastImageSequence.paused) {
fastImageSequence.progress = progress.value;
}
});

fastImageSequence.play(30);
});
}
6 changes: 3 additions & 3 deletions example/src/exampleWithControl.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {FastImageSequence} from '../../src/index';

const prevButton = document.getElementById('prev-button');
const nextButton = document.getElementById('next-button');
const progress = document.getElementById('slider-input');
const prevButton = document.getElementById('prev-button-1');
const nextButton = document.getElementById('next-button-1');
const progress = document.getElementById('slider-input-1');

export async function initExampleWithControl(container) {
const fastImageSequence = new FastImageSequence(container, {
Expand Down
4 changes: 3 additions & 1 deletion example/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import {initExampleWithControl} from "./exampleWithControl.js";
import {initExamplePlayBackwards} from "./examplePlayBackwards.js";
import {initExampleStillImage} from "./exampleStillImage.js";
import {constructDestructTest} from "./exampleConstructDestructTest.js";
import {initExampleLoadTar} from "./exampleLoadTar.js";

initExampleWithControl(document.getElementsByClassName('grid-item')[0]);
initExamplePlayBackwards(document.getElementsByClassName('grid-item')[1]);
initExampleStillImage(document.getElementsByClassName('grid-item')[2]);
constructDestructTest(document.getElementsByClassName('grid-item')[3]);
constructDestructTest(document.getElementsByClassName('grid-item')[3]);
initExampleLoadTar(document.getElementsByClassName('grid-item')[4]);
3 changes: 0 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,5 @@
},
"engines": {
"node": ">=16.0.0"
},
"dependencies": {
"@mediamonks/fast-image-sequence": "^0.6.4"
}
}
29 changes: 15 additions & 14 deletions src/lib/FastImageSequence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Frame from "./Frame.js";
import {createLogElement, logToScreen} from "./LogToScreen.js";
import ImageSource, {type ImageSourceOptions, INPUT_SRC} from "./ImageSource.js";
import ImageSourceTar from "./ImageSourceTar.js";
import ImageSourceFetch from "./ImageSourceFetch.js";

export function isMobile(): boolean {
return (typeof navigator !== "undefined" && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
Expand Down Expand Up @@ -147,7 +148,7 @@ export class FastImageSequence {
if (src.tarURL !== undefined) {
return new ImageSourceTar(this, index, src);
} else {
return new ImageSource(this, index, src);
return new ImageSourceFetch(this, index, src);
}
});

Expand Down Expand Up @@ -204,6 +205,18 @@ export class FastImageSequence {
this.frame = (this.options.frames - 1) * value;
}

/**
* Get the first ImageSource from the sources array.
* @returns {ImageSource} - The first ImageSource object in the sources array.
*/
public get src() {
return this.sources[0] as ImageSource;
}

private get index(): number {
return this.wrapIndex(this.frame);
}

/**
* Returns a promise that resolves when the image sequence is ready to play.
*/
Expand All @@ -221,18 +234,6 @@ export class FastImageSequence {
});
}

/**
* Get the first ImageSource from the sources array.
* @returns {ImageSource} - The first ImageSource object in the sources array.
*/
public get src() {
return this.sources[0] as ImageSource;
}

private get index(): number {
return this.wrapIndex(this.frame);
}

/**
* Register a tick function to be called on every frame update.
*
Expand Down Expand Up @@ -331,7 +332,7 @@ export class FastImageSequence {
this.clearCanvas = true;
}

public setLoadingPriority() {
private setLoadingPriority() {
const priorityIndex = this.index;// this.wrapIndex(Math.min(this.spread / 2 - 2, (this.frame - this.prevFrame) * (dt * 60)) + this.frame);
this.frames.forEach((image) => {
image.priority = Math.abs(image.index + 0.25 - priorityIndex);
Expand Down
44 changes: 7 additions & 37 deletions src/lib/ImageSource.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {clamp, type FastImageSequence, isMobile} from "./FastImageSequence.js";
import ImageElement from "./ImageElement.js";
import {getImageFetchWorker, releaseImageFetchWorker} from "./ImageFetch.js";
import {loadImage} from "./DownloadFile.js";

export const INPUT_SRC = 0;
export const INPUT_TAR = 1;
Expand Down Expand Up @@ -70,14 +68,15 @@ export default class ImageSource {
}

public getImageURL(index: number): string | undefined {
return this.options.imageURL ? new URL(this.options.imageURL(index), window.location.href).href : undefined;
return undefined;
}

public async loadResources() {
if (!this.images[0]?.available) {
throw new Error(`No image available for index 0 in ImageSource${this.index} (${this.images[0]?.imageURL})`);
}

this.setMaxCachedImages(this.options.maxCachedImages);
this.initialized = true;
}

Expand Down Expand Up @@ -111,39 +110,14 @@ export default class ImageSource {

public async fetchImage(imageElement: ImageElement) {
return new Promise<ImageBitmap | HTMLImageElement>((resolve, reject) => {
if (imageElement.imageURL) {
imageElement.loading = true;

const loadingDone = (image: ImageBitmap | HTMLImageElement) => {
if (imageElement.loading) {
imageElement.image = image;
resolve(image);
}
};

const loadingError = (e: any) => {
imageElement.reset();
reject(e);
};

if (this.options.useWorker) {
const worker = getImageFetchWorker();
worker.load(this.index, imageElement.imageURL).then((imageBitmap) => {
loadingDone(imageBitmap);
releaseImageFetchWorker(worker);
}).catch(e => loadingError(e));
} else {
const imgElement = new Image();
loadImage(imgElement, imageElement.imageURL).then(() => {
loadingDone(imgElement);
}).catch(e => loadingError(e));
}
} else {
reject('Image url not set');
}
reject('Not implemented');
});
}

public destruct() {
this.images.forEach(image => image.reset());
}

private releaseImageWithLowestPriority() {
this.context.setLoadingPriority();
const loadedImages = this.images.filter(a => a.image !== undefined && !a.loading);
Expand All @@ -155,8 +129,4 @@ export default class ImageSource {
}
}
}

public destruct() {
this.images.forEach(image => image.reset());
}
}
45 changes: 45 additions & 0 deletions src/lib/ImageSourceFetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import ImageElement from "./ImageElement.js";
import {getImageFetchWorker, releaseImageFetchWorker} from "./ImageFetch.js";
import {loadImage} from "./DownloadFile.js";
import ImageSource from "./ImageSource.js";

export default class ImageSourceFetch extends ImageSource {
public override getImageURL(index: number): string | undefined {
return this.options.imageURL ? new URL(this.options.imageURL(index), window.location.href).href : undefined;
}

public override async fetchImage(imageElement: ImageElement) {
return new Promise<ImageBitmap | HTMLImageElement>((resolve, reject) => {
if (imageElement.imageURL) {
imageElement.loading = true;

const loadingDone = (image: ImageBitmap | HTMLImageElement) => {
if (imageElement.loading) {
imageElement.image = image;
resolve(image);
}
};

const loadingError = (e: any) => {
imageElement.reset();
reject(e);
};

if (this.options.useWorker) {
const worker = getImageFetchWorker();
worker.load(this.index, imageElement.imageURL).then((imageBitmap) => {
loadingDone(imageBitmap);
releaseImageFetchWorker(worker);
}).catch(e => loadingError(e));
} else {
const imgElement = new Image();
loadImage(imgElement, imageElement.imageURL).then(() => {
loadingDone(imgElement);
}).catch(e => loadingError(e));
}
} else {
reject('Image url not set');
}
});
}
}
1 change: 0 additions & 1 deletion src/lib/ImageSourceTar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default class ImageSourceTar extends ImageSource {
this.context.log('Tarball', this.tarball);

this.images.forEach(image => image.available = image.imageURL !== undefined && this.tarball?.getInfo(image.imageURL) !== undefined);
this.setMaxCachedImages(this.options.maxCachedImages);
}

return super.loadResources();
Expand Down

0 comments on commit 73487ab

Please sign in to comment.