Skip to content

Commit

Permalink
Fix alpha channel detection when using in-process image handling.
Browse files Browse the repository at this point in the history
This fix solves an issue when the image worker is not being used, so Lightning processes images on the main thread. There is a simple check for `.png` to toggle whether or not the image has an alpha channel. This however gives an issue when a `.PNG` is used. Introduced a simple lowerCase cast to be able to work with both `.png` and `.PNG`.

Additionally added some (quick and dirty) vitest cases to validate the above changes.
Resolves: rdkcentral#493
  • Loading branch information
wouterlucas committed Jun 28, 2023
1 parent 16b7a28 commit ae36afa
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/platforms/browser/WebPlatform.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ export default class WebPlatform {

loadSrcTexture({ src, hasAlpha }, cb) {
let cancelCb = undefined;
let isPng = (src.indexOf(".png") >= 0) || src.substr(0, 21) == 'data:image/png;base64';
let isPng = (src.toLowerCase().indexOf(".png") >= 0) || src.substr(0, 21) == 'data:image/png;base64';
let isKtx = src.indexOf('.ktx') >= 0;
let isPvr = src.indexOf('.pvr') >= 0;
if (isKtx || isPvr) {
Expand Down
151 changes: 151 additions & 0 deletions src/platforms/browser/WebPlatform.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import { describe, it, expect } from 'vitest';
import WebPlatform from './WebPlatform.mjs';

// stub stage for now
const stage = {
getOption: () => {
return false;
}
}

// WebPlatform expects certain browser based globals to be present
// lets stub them and just run our functionality
global.document = {
addEventListener: (type, listener) => { return; },
removeEventListener: (type, listener) => { return; }
}

class ImageStub {
static loadBehaviour = 'success';

set crossOrigin(s) { this._crossOrigin = s; }
get crossOrigin() { return this._crossOrigin; }

set onload(o) { this._onload = o; }
set onerror(r) { this._onerror = r; }

set src(s) {
this._src = s;

setTimeout(() => {
if (ImageStub.loadBehaviour === 'success' && this._onload && typeof this._onload === 'function') {
return this._onload();
}

return this._onerror();
}, 20);
}

get src() { return this._src; }

removeAttribute(a) {
// idk about this
if (this[a] !== undefined)
delete this[a];
}

static setLoadBehaviour(t) {
ImageStub.loadBehaviour = t;
}
}

global.Image = ImageStub;

describe('WebPlatform', () => {
let webPlatform = null;

describe('init', () => {
it('WebPlatform should init properly', () => {
webPlatform = new WebPlatform(stage);

expect(webPlatform.init).toBeTypeOf('function');
expect(webPlatform.destroy).toBeTypeOf('function');
expect(webPlatform.loop).toBeTypeOf('function');
expect(webPlatform.loadSrcTexture).toBeTypeOf('function');
expect(webPlatform.createWebGLContext).toBeTypeOf('function');
});

it('should initialize', () => {
webPlatform.init(stage);

//we're expecting to not run with the image worker for this particular test
expect(webPlatform._imageWorker).toBeUndefined();
})
});

describe('loadSrcTexture', () => {
it('should allow for loading a png', () => new Promise(done => {
const opts = {
src: 'https://lightningjs.io/cool.png'
}

const cancelCb = webPlatform.loadSrcTexture(opts, (err, image) => {
expect(err).toBeFalsy();
expect(image).toBeDefined();
expect(image).toBeTypeOf('object');
expect(image.hasAlpha).toBeTruthy();
expect(image.renderInfo).toBeDefined();
expect(image.renderInfo.src).toBe(opts.src);
expect(image.renderInfo.compressed).toBeFalsy();
done();
});

expect(cancelCb).toBeTypeOf('function');
}));

it('should set hasAlpha to True with uppercase extension', () => new Promise(done => {
const opts = {
src: 'https://lightningjs.io/cool.PNG'
}

const cancelCb = webPlatform.loadSrcTexture(opts, (err, image) => {
expect(err).toBeFalsy();
expect(image).toBeDefined();
expect(image).toBeTypeOf('object');
expect(image.hasAlpha).toBeTruthy();
expect(image.renderInfo).toBeDefined();
expect(image.renderInfo.src).toBe(opts.src);
expect(image.renderInfo.compressed).toBeFalsy();
done();
});

expect(cancelCb).toBeTypeOf('function');
}));

it('should set hasAlpha with a png blob', () => new Promise(done => {
const opts = {
src: 'data:image/png;base64;1234567890ABCDEFcoolPNGdude'
}

const cancelCb = webPlatform.loadSrcTexture(opts, (err, image) => {
expect(err).toBeFalsy();
expect(image).toBeDefined();
expect(image).toBeTypeOf('object');
expect(image.hasAlpha).toBeTruthy();
expect(image.renderInfo).toBeDefined();
expect(image.renderInfo.src).toBe(opts.src);
expect(image.renderInfo.compressed).toBeFalsy();
done();
});

expect(cancelCb).toBeTypeOf('function');
}));

it('should handle a load error', () => new Promise(done => {
const opts = {
src: 'https://lightningjs.io/cool.PNG'
}

ImageStub.setLoadBehaviour('error');

const cancelCb = webPlatform.loadSrcTexture(opts, (err, image) => {
expect(err).toBeTruthy();
expect(image).toBeUndefined();
done();
});

expect(cancelCb).toBeTypeOf('function');
}));
});
});

0 comments on commit ae36afa

Please sign in to comment.