A suite to track Project Diva score statistics and ratings / D4DJ event data.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
projectdivar/server/node_modules/image-pixels/test/index.js

844 lines
21 KiB

'use strict'
var t = require('tape')
var fs = require('fs')
var path = require('path')
var getPixels = require('../')
var match = require('pixelmatch')
var toab = require('to-array-buffer')
var fixture = require('./fixture')
var ab2s = require('arraybuffer-to-string')
var x = require('object-assign')
var getNdPixels = require('get-pixels')
var isOnline = require('is-online')
var isBrowser = require('is-browser')
var save = require('save-file')
if (!isBrowser) {
var path = require('path')
var del = require('del')
}
if (!isBrowser) {
// var { JSDOM } = require('jsdom')
// var { window } = new JSDOM(`<!doctype html>`)
}
var clipFix = {
data: [
0,255,255,255, 255,255,255,255,
255,255,255,255, 255,255,255,255
],
width: 2,
height: 2
}
var pngFixData = toab(fixture.pngDataURL)
var pngFixURL = fixture.pngURL
const ASSERT_N = 19
const REQUEST_TIMEOUT = 3000
async function testSource(t, arg, o, fix=fixture) {
// direct
let to = setTimeout(function () {t.fail('Direct timeout')}, REQUEST_TIMEOUT)
let data = await getPixels(arg, o)
clearTimeout(to)
t.equal(data.width, fix.width)
t.equal(data.height, fix.height)
fix.data ?
t.equal(match(data.data, fix.data, null, fix.width, fix.height, {threshold: .006}), 0, 'Ok async pixels') :
t.ok(data.data[0], 'Ok async pixels')
let redata = await getPixels(data)
t.equal(redata, data, 'Repeat data')
// second time (cache)
to = setTimeout(function () {t.fail('Direct second timeout')}, REQUEST_TIMEOUT)
let data2 = await getPixels(arg, o)
clearTimeout(to)
t.deepEqual(data.data, data2.data)
t.equal(data2.width, fix.width)
t.equal(data2.height, fix.height)
fix.data ? t.equal(match(data2.data, fix.data, null, fix.width, fix.height, {threshold: .006}), 0, 'Ok async pixels twice') :
t.ok(data2.data[0], 'Ok async pixels twice')
let redata2 = await getPixels(data2)
t.equal(redata2, data2, 'Repeat data secondary')
// clip
to = setTimeout(function () {t.fail('Clip timeout')}, REQUEST_TIMEOUT)
let clip = await getPixels(arg, x({clip: [1,1,3,3]}, o))
clearTimeout(to)
t.equal(clip.width, 2)
t.equal(clip.height, 2)
fix.data ?
t.equal(match(clip.data, clipFix.data, null, 2, 2, {threshold: .006}), 0, 'Ok clip pixels') :
t.ok(clip.data[0], 'Ok clip pixels')
// alltogether
to = setTimeout(function () {t.fail('All timeout')}, REQUEST_TIMEOUT)
var list = await getPixels.all([
o,
x({clip: [1,1,3,3]}, o)
], {source: arg})
clearTimeout(to)
t.deepEqual(data.data, list[0].data, 'Ok all pixels data')
t.equal(list[0].width, fix.width)
t.equal(list[0].height, fix.height)
fix.data ? t.equal(match(list[0].data, fix.data, null, fix.width, fix.height, {threshold: .006}), 0, 'Ok all pixels') :
t.ok(list[0].data[0], 'Ok all pixels')
t.equal(list[1].width, 2)
t.equal(list[1].height, 2)
fix.data ?
t.equal(match(list[1].data, clipFix.data, null, 2, 2, {threshold: .006}), 0, 'Ok clip pixels') :
t.ok(list[1].data[0], 'Ok all clip pixels')
}
async function online () {
if (isOnline.call) {
isOnline = await isOnline()
}
return isOnline
}
// strings
t('absolute path', async t => {
t.plan(ASSERT_N)
await testSource(t, path.resolve('./test/test_pattern.png'))
t.end()
})
t('relative path', async t => {
t.plan(ASSERT_N)
await testSource(t, './test/test_pattern.png')
t.end()
})
t('some path', async t => {
t.plan(ASSERT_N)
await testSource(t, 'test/test_pattern.png')
t.end()
})
t('https', async t => {
if (await online()) {
t.plan(ASSERT_N)
await testSource(t, pngFixURL)
}
t.end()
})
t('http', async t => {
if (await online()) {
t.plan(ASSERT_N)
await testSource(t, pngFixURL.replace('https', 'http'))
}
t.end()
})
t('protocol-relative URL', async t => {
if (await online()) {
t.plan(ASSERT_N)
await testSource(t, pngFixURL.replace('https:', ''))
}
t.end()
})
t('data URL', async t => {
t.plan(2 * ASSERT_N)
await testSource(t, fixture.pngDataURL)
await testSource(t, fixture.jpgDataURL)
t.end()
})
t('base64', async t => {
t.plan(ASSERT_N)
await testSource(t, fixture.pngDataURL.replace(/^data:image\/(png|jpg);base64,/, ''))
t.end()
})
t('raw pixels base64', async t => {
t.plan(ASSERT_N)
await testSource(t, ab2s(fixture.data, 'base64'), {w:16, h:8})
t.end()
})
// DOMs
t(`<img>`, async t => {
//TODO: add node test
if (!isBrowser) return t.end()
t.plan(ASSERT_N)
let img = document.createElement('img')
img.src = './test/test_pattern.png'
await testSource(t, img)
t.end()
})
t(`<image>`, async t => {
if (!isBrowser) return t.end()
t.plan(ASSERT_N)
let el = document.createElement('div')
el.innerHTML = `<svg width="200" height="200"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image xlink:href="./test/test_pattern.png"/>
</svg>
`
let img = el.firstChild.firstChild
await testSource(t, img)
t.end()
})
t(`<video>`, async t => {
if (!isBrowser) return t.end()
t.plan(ASSERT_N)
let el = document.createElement('div')
el.innerHTML = `<video src="./test/stream_of_water.webm"></video>`
await testSource(t, el.firstChild, null, {
width: 480, height: 360
})
t.end()
})
t(`Video bad src`, async t => {
if (!isBrowser) return t.end()
t.plan(1)
let el = document.createElement('div')
el.innerHTML = `<video src="./test/xxx.webm"></video>`
try {
await getPixels(el.firstChild)
}
catch (e) {
t.ok(e)
}
t.end()
})
t(`Image`, async t => {
if (!isBrowser) return t.end()
t.plan(ASSERT_N)
let img = new Image
img.src = './test/test_pattern.png'
await testSource(t, img)
t.end()
})
t(`Image bad src`, async t => {
if (!isBrowser) return t.end()
t.plan(1)
let img = new Image()
img.src = 'xxx.png'
try {
await getPixels(img)
}
catch (e) {
t.ok(e)
}
t.end()
})
t(`ImageData`, async t => {
if (!isBrowser) return t.end()
t.plan(ASSERT_N)
var context = document.createElement('canvas').getContext('2d')
var idata = context.createImageData(fixture.width, fixture.height)
for (var i = 0; i < fixture.data.length; i++) {
idata.data[i] = fixture.data[i]
}
await testSource(t, idata)
t.end()
})
t(`ImageBitmap`, async t => {
if (!isBrowser) return t.end()
t.plan(ASSERT_N * 2)
var canvas = fixture.canvas2d
let bm = createImageBitmap(canvas)
await testSource(t, bm)
bm = await createImageBitmap(canvas)
await testSource(t, bm)
t.end()
})
t(`File, Blob`, async t => {
if (!isBrowser) return t.end()
t.plan(ASSERT_N * 2)
await testSource(t, new File([pngFixData], 'file.png'))
await testSource(t, new Blob([pngFixData]))
t.end()
})
t(`Canvas/Context2D`, async t => {
if (!isBrowser) return t.end()
t.plan(ASSERT_N * 2)
var canvas = fixture.canvas2d
await testSource(t, canvas)
var canvas = fixture.canvas2d
await testSource(t, canvas.getContext('2d'))
t.end()
})
t(`Canvas/WebGLContext`, async t => {
if (isBrowser) {
t.plan(ASSERT_N * 4)
await testSource(t, fixture.gl)
await testSource(t, fixture.canvasGl)
}
else {
t.plan(ASSERT_N * 3)
await testSource(t, fixture.gl)
}
await testSource(t, fixture.regl)
let c = fixture.gl.canvas
Object.defineProperty(fixture.gl, 'canvas', {
writable: true,
configurable: true,
value: null
})
fixture.gl.canvas = null
await testSource(t, fixture.gl)
fixture.gl.canvas = c
t.end()
})
// buffers
t(`Buffer`, async t => {
t.plan(ASSERT_N + 1)
var buf = new Buffer(fixture.data)
try {
if (getPixels.cache.get(fixture.data)) throw Error('cached')
await getPixels(new Buffer(fixture.data))
} catch (e) {
t.ok(e)
}
await testSource(t, buf, {width: fixture.width, height: fixture.height})
t.end()
})
t(`ArrayBuffer`, async t => {
t.plan(ASSERT_N + 1)
try {
if (getPixels.cache.get(fixture.data.buffer)) throw Error('cached')
await getPixels(fixture.data.buffer)
} catch (e) {
t.ok(e)
}
await testSource(t, fixture.data.buffer, {width: fixture.width, height: fixture.height})
t.end()
})
t(`Uint8Array`, async t => {
t.plan(ASSERT_N + 1)
try {
if (getPixels.cache.get(fixture.data)) throw Error('cached')
await getPixels(fixture.data)
} catch (e) {
t.ok(e)
}
await testSource(t, fixture.data, {width: fixture.width, height: fixture.height})
t.end()
})
t(`Uint8Array encoded`, async t => {
t.plan(ASSERT_N)
await testSource(t, new Uint8Array(pngFixData))
t.end()
})
t(`Uint8ClampedArray`, async t => {
t.plan(ASSERT_N + 1)
try {
if (getPixels.cache.get(fixture.data)) throw Error('cached')
await getPixels(new Uint8ClampedArray(fixture.data))
} catch (e) {
t.ok(e)
}
await testSource(t, new Uint8ClampedArray(fixture.data), {width: fixture.width, height: fixture.height})
t.end()
})
t(`Float32Array`, async t => {
t.plan(ASSERT_N + 1)
var arr = new Float32Array(fixture.data.length)
for (let i = 0; i < arr.length; i++) {
arr[i] = fixture.data[i] / 255
}
try {
await getPixels(arr)
} catch (e) {
t.ok(e)
}
await testSource(t, arr, {width: fixture.width, height: fixture.height})
t.end()
})
t(`Float64Array`, async t => {
t.plan(ASSERT_N + 1)
var arr = new Float64Array(fixture.data.length)
for (let i = 0; i < arr.length; i++) {
arr[i] = fixture.data[i] / 255
}
try {
await getPixels(arr)
} catch (e) {
t.ok(e)
}
await testSource(t, arr, {width: fixture.width, height: fixture.height})
t.end()
})
t(`Array`, async t => {
t.plan(ASSERT_N + 1)
var arr = Array.from(fixture.data)
try {
await getPixels(arr)
} catch (e) {
t.ok(e)
}
await testSource(t, arr, {width: fixture.width, height: fixture.height})
t.end()
})
t(`[[r,g,b,a], [r,g,b,a], ...]`, async t => {
t.plan(ASSERT_N + 1)
// [[r,g,b,a], [r,g,b,a], ...]
var arr = Array(fixture.data.length / 4)
for (let i = 0; i < arr.length; i++) {
arr[i] = [
fixture.data[4 * i + 0],
fixture.data[4 * i + 1],
fixture.data[4 * i + 2],
fixture.data[4 * i + 3]
]
}
try {
await getPixels(arr)
} catch (e) {
t.ok(e)
}
await testSource(t, arr, {width: fixture.width, height: fixture.height})
t.end()
})
t('[[r,g,b,a,r,g,b,a], [r,g,b,a,r,g,b,a], ...]', async t => {
t.plan(ASSERT_N + 1)
// [[r,g,b,a], [r,g,b,a], ...]
var arr = []
for (let y = 0; y < fixture.height; y++) {
var row = []
for (let i = 0; i < fixture.width; i++) {
row.push(fixture.data[y * fixture.width * 4 + i * 4])
row.push(fixture.data[y * fixture.width * 4 + i * 4 + 1])
row.push(fixture.data[y * fixture.width * 4 + i * 4 + 2])
row.push(fixture.data[y * fixture.width * 4 + i * 4 + 3])
}
arr.push(row)
}
try {
await getPixels(arr)
} catch (e) {
t.ok(e)
}
await testSource(t, arr, {width: fixture.width, height: fixture.height})
t.end()
})
t('[[[r,g,b,a], [r,g,b,a]], [[r,g,b,a], [r,g,b,a]], ...]', async t => {
t.plan(ASSERT_N + 1)
// [[r,g,b,a], [r,g,b,a], ...]
var arr = []
for (let y = 0; y < fixture.height; y++) {
var row = []
for (let i = 0; i < fixture.width; i++) {
row.push([
fixture.data[y * fixture.width * 4 + i * 4],
fixture.data[y * fixture.width * 4 + i * 4 + 1],
fixture.data[y * fixture.width * 4 + i * 4 + 2],
fixture.data[y * fixture.width * 4 + i * 4 + 3]
])
}
arr.push(row)
}
try {
await getPixels(arr)
} catch (e) {
t.ok(e)
}
await testSource(t, arr, {width: fixture.width, height: fixture.height})
t.end()
})
// cases
t(`options directly`, async t => {
t.plan(ASSERT_N)
await testSource(t, {source: fixture.pngDataURL})
t.end()
})
t(`ndarray`, async t => {
t.plan(ASSERT_N)
getNdPixels(fixture.pngDataURL, async (e, px) => {
await testSource(t, px)
t.end()
})
})
t(`multiple sources: list`, async t => {
if (!(await online())) return t.end()
t.plan(8)
// different sources list
let list = await getPixels.all([
fixture.data,
fixture.pngDataURL,
fixture.pngURL,
fixture.gl
], {width: fixture.width, height: fixture.height})
t.equal(list[0].data.length, 512)
t.equal(list[1].data.length, 512)
t.equal(list[2].data.length, 512)
t.equal(list[3].data.length, 512)
t.equal(match(list[0].data, fixture.data, null, fixture.width, fixture.height, {threshold: .006}), 0, 'Ok data pixels')
t.equal(match(list[1].data, fixture.data, null, fixture.width, fixture.height, {threshold: .006}), 0, 'Ok data pixels')
t.equal(match(list[2].data, fixture.data, null, fixture.width, fixture.height, {threshold: .006}), 0, 'Ok data pixels')
t.equal(match(list[3].data, fixture.data, null, fixture.width, fixture.height, {threshold: .006}), 0, 'Ok data pixels')
t.end()
})
t('multiple sources: dict', async t => {
if (!(await online())) return t.end()
t.plan(3)
// different source dict
let {a, b, c} = await getPixels.all({
a: fixture.data,
b: fixture.pngDataURL,
c: fixture.pngURL
}, {width: fixture.width, height: fixture.height})
t.deepEqual(fixture.data, a.data)
t.deepEqual(fixture.data, b.data)
t.deepEqual(fixture.data, c.data)
t.end()
})
t('multiple source error', async t => {
if (!(await online())) return t.end()
t.plan(2)
await getPixels.all([
fixture.data,
fixture.pngDataURL,
fixture.canvas
]).catch(e => {
t.ok(e)
})
await getPixels.all({
a: fixture.data,
b: fixture.pngDataURL,
c: fixture.canvas
}).catch(e => {
t.ok(e)
})
t.end()
})
t('<picture>', async t => {
if (!isBrowser) return t.end()
t.plan(ASSERT_N)
let el = document.createElement('div')
el.innerHTML = `<picture>
<source srcset="${fixture.jpgDataURL}">
<img src="${fixture.pngDataURL}">
</picture>`
await testSource(t, el.firstChild)
t.end()
})
t('bad string', async t => {
t.plan(1)
try {
await getPixels('')
} catch (e) {
t.ok(e)
}
t.end()
})
t('not existing url', async t => {
t.plan(1)
try {
await getPixels('./test/xxx.png')
} catch (e) {
t.ok(e)
}
t.end()
})
t('not an image url', async t => {
t.plan(1)
try {
await getPixels('./test/fixture.js')
} catch (e) {
t.ok(e)
}
t.end()
})
t.skip('#img-el', async t => {
})
t('changed URL contents', async t => {
if (isBrowser) return t.end()
var data1 = fixture.pngDataURL
var data2 = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAICAYAAADwdn+XAAAAMklEQVQoU2P8z8DwnwEEQCQjnAcWIgYwMvwHaQUTZAFGBob///+TqxvsaIq0jxoAijYA90Mg6YIzCEUAAAAASUVORK5CYII=`
// cached
await save(
toab(data1),
'./a.png'
)
var result1 = await getPixels('./a.png')
t.deepEqual(result1.data, fixture.data)
await save(
toab(data2),
'./a.png'
)
var result2 = await getPixels('./a.png')
t.deepEqual(result2.data, result1.data)
// uncached
await save(
toab(data1),
'./b.png'
)
var result1 = await getPixels('./b.png', {cache: false})
t.deepEqual(result1.data, fixture.data)
await save(
toab(data2),
'./b.png'
)
var result2 = await getPixels('./b.png')
t.notDeepEqual(result2.data, result1.data)
del(['./b.png', './a.png'])
t.end()
})
t.skip('URL timeout')
t.skip('bad URL data')
t.skip('malformed encoded buffer')
t.skip(`File, Blob with encoded data`, async t => {
t.plan(ASSERT_N * 2)
await testSource(t, new File([fixture.data], 'file.png'))
await testSource(t, new Blob([fixture.data]))
t.end()
})
t.skip('Stream')
t.skip('SourceBuffer')
t.skip('SourceBufferList')
t.skip(`MediaSource`, async t => {
t.plan(ASSERT_N)
// var mediaSource = new MediaSource()
// var video = new HTMLVideoElement()
// video.src = URL.createObjectURL(mediaSource)
// mediaSource.addEventListener('sourceopen', function () {
// mediaSource.addSourceBuffer(mimeCodec)
// })
// await testSource(t, new)
t.end()
})
t.skip(`OffscreenCanvas, bitmaprenderer`, async t => {
t.plan(ASSERT_N * 2)
// let offscreen = new OffscreenCanvas(fixture.width, fixture.height)
// let context = offscreen.getContext('webgl')
// ... some drawing for the first canvas using the gl context ...
// Commit rendering to the first canvas
// var bm = offscreen.transferToImageBitmap()
// one.transferImageBitmap(bm);
})
t.skip('object with float data array', async t => {
// FIXME: probably this is normal behaviour
let data = [0,0,0,1, 1,1,1,1, 1,1,1,1, 0,0,0,1]
let px = await getPixels({
data: data,
width: 2,
height: 2
})
t.deepEqual(px.data, [0,0,0,255, 255,255,255,255, 255,255,255,255, 0,0,0,255])
t.end()
})
t('do not cache arrays', async t => {
// FIXME: it does not cache array, but transparently returns input value, unless indicater otherwise. Should that return copy instead?
var data = fixture.data.slice()
var result1 = await getPixels({data, w: fixture.width, h: fixture.height})
data[10] = 255
var result2 = await getPixels({data, w: fixture.width, h: fixture.height})
t.notDeepEqual(result1.data, result2.data)
t.end()
})
t('error during processing', t => {
t.plan(1)
getPixels(/asd/).then(null, err => {
t.ok(err)
t.end()
})
})
t('tagged template', async t => {
let {data} = await getPixels`./test/test_pattern.png`
t.ok(data.length)
t.end()
})
// get-pixels cases
function test_image (t, pixels) {
t.equal(match(pixels.data, fixture.data, null, fixture.width, fixture.height, {threshold: 0}), 0)
// t.deepEqual(pixels.data, fixture.data)
}
t('get-pixels', async function(t) {
getPixels('test/lena.png', function(err, pixels) {
if(err) {
t.fail(err)
} else {
t.equals([pixels.width, pixels.height].join(','), '512,512')
}
t.end()
})
})
t('get-pixels-png', async function(t) {
getPixels('test/test_pattern.png', function(err, pixels) {
if(err) {
t.error(err, 'failed to parse png')
t.end()
return
}
test_image(t, pixels)
t.end()
})
})
t.skip('get-pixels-ppm', async function(t) {
getPixels(path.join(__dirname, 'test_pattern.ppm'), function(err, pixels) {
if(err) {
t.error(err, 'failed to parse ppm')
t.end()
return
}
test_image(t, pixels)
t.end()
})
})
t('get-pixels-gif', async function(t) {
getPixels('test/test_pattern.gif', function(err, pixels) {
if(err) {
t.error(err, 'failed to parse gif')
t.end()
return
}
test_image(t, pixels)
t.end()
})
})
t('get-pixels-bmp', async function(t) {
getPixels('test/test_pattern.bmp', function(err, pixels) {
if(err) {
t.error(err, 'failed to parse bmp')
t.end()
return
}
test_image(t, pixels)
t.end()
})
})
t('data url', async function(t) {
var url = 'data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7'
getPixels(url, function(err, data) {
if(err) {
t.error('failed to read data url')
t.end()
return
}
t.ok(true, 'data url opened without crashing')
t.end()
})
})
t('get-pixels-buffer', async function(t) {
var buffer = fs.readFileSync(__dirname + '/test_pattern.png')
getPixels(buffer, 'image/png', function(err, pixels) {
if(err) {
t.error(err, 'failed to parse buffer')
t.end()
return
}
test_image(t, pixels)
t.end()
})
})
t('get-url png img', async function(t) {
if (!(await online())) return t.end()
var url = 'https://raw.githubusercontent.com/dy/get-pixel-data/master/test/test_pattern.png';
getPixels(url, function(err, pixels){
if(err) {
t.error(err, 'failed to read web image data');
t.end();
return;
}
test_image(t, pixels);
t.end();
});
})
t('get-url gif img', async function(t) {
if (!(await online())) return t.end()
var url = 'https://raw.githubusercontent.com/dy/get-pixel-data/master/test/test_pattern.gif';
getPixels(url, function(err, pixels){
if(err) {
t.error(err, 'failed to read web image data');
t.end();
return;
}
test_image(t, pixels);
t.end();
});
})