# HG changeset patch # User Laurens Holst # Date 1587996396 -7200 # Mon Apr 27 16:06:36 2020 +0200 # Node ID 8d6ecfdee53b0813230776c84aa0532040759800 # Parent 0b536eb44e9475f0b62c8ced82a9c6917117230d images: Introduce gamma function to convert colours more precisely. diff --git a/res/resources.json b/res/resources.json --- a/res/resources.json +++ b/res/resources.json @@ -1,6 +1,7 @@ { "screenMode": 5, "frameRate": 59.922743404312307, + "gamma": 2.42, "tilemaps": [ { "name": "FieldMap", diff --git a/tools/images.js b/tools/images.js --- a/tools/images.js +++ b/tools/images.js @@ -153,9 +153,13 @@ } class PNGLoader { - constructor(path) { + constructor(path, gamma) { checkTypes(arguments, "string"); this.path = path; + this.valueMapping3Bit = new Array(256); + for (let i = 0; i < 256; i++) { + this.valueMapping3Bit[i] = Math.round(Math.pow(i / 255, gamma / 2.2) * 7); + } } async loadImage() { @@ -178,7 +182,7 @@ toPalette(palette8bit) { checkTypes(arguments, Array); const palette = new Palette(); - const palette3bit = palette8bit.map(c => Math.round(c / 255 * 7)); + const palette3bit = palette8bit.map(c => this.valueMapping3Bit[c]); for (let i = 0; i < palette3bit.length / 3; i++) { const r = palette3bit[i * 3] || 0; const g = palette3bit[i * 3 + 1] || 0; diff --git a/tools/resources.js b/tools/resources.js --- a/tools/resources.js +++ b/tools/resources.js @@ -21,10 +21,11 @@ } class Resources { - constructor(screenMode, frameRate) { - checkTypes(arguments, "number", "number"); + constructor(screenMode, frameRate, gamma) { + checkTypes(arguments, "number", "number", "number"); this.screenMode = screenMode; this.frameRate = frameRate; + this.gamma = gamma; this.tileMaps = []; this.images = []; this.sprites = []; @@ -86,24 +87,25 @@ const resources = new Resources( json.screenMode, - json.frameRate + json.frameRate, + json.gamma ); const tileMaps = Promise.all(json.tilemaps.map(async jsonTileMap => { const tileMapPath = path.resolve(path.dirname(this.path), jsonTileMap.path); - return new Tmx(jsonTileMap.name, tileMapPath).parse(); + return new Tmx(jsonTileMap.name, tileMapPath).parse(resources.gamma); })); const images = Promise.all(json.images.map(async jsonImage => { const imagePath = path.resolve(path.dirname(this.path), jsonImage.path); - const image = await new PNGLoader(imagePath).loadImage(); + const image = await new PNGLoader(imagePath, resources.gamma).loadImage(); image.name = jsonImage.name; return image; })); const sprites = Promise.all(json.sprites.map(async jsonSprite => { const spritePath = path.resolve(path.dirname(this.path), jsonSprite.path); - return new AsepriteSheet(jsonSprite.name, spritePath).parse(); + return new AsepriteSheet(jsonSprite.name, spritePath).parse(resources.gamma); })); const audio = Promise.all(json.audio.map(async jsonTrack => { diff --git a/tools/sprites.js b/tools/sprites.js --- a/tools/sprites.js +++ b/tools/sprites.js @@ -103,18 +103,19 @@ this.path = path; } - async parse() { + async parse(gamma) { + checkTypes(arguments, "number"); const json = JSON.parse(await fs.promises.readFile(this.path)); - const sprite = await this.parseSprite(json.meta, this.name); + const sprite = await this.parseSprite(json.meta, gamma); this.parseFrames(json.frames, sprite); return sprite; } - async parseSprite(jsonMeta, name) { - checkTypes(arguments, Object, "string"); + async parseSprite(jsonMeta, gamma) { + checkTypes(arguments, Object, "number"); const imagepath = path.resolve(path.dirname(this.path), jsonMeta.image); - const image = await new PNGLoader(imagepath).loadImage(); - return new Sprite(name, image); + const image = await new PNGLoader(imagepath, gamma).loadImage(); + return new Sprite(this.name, image); } parseFrames(jsonFrames, sprite) { diff --git a/tools/tilemaps.js b/tools/tilemaps.js --- a/tools/tilemaps.js +++ b/tools/tilemaps.js @@ -128,14 +128,15 @@ this.path = path; } - async parse() { + async parse(gamma) { + checkTypes(arguments, "number"); const xml = await xml2js.parseStringPromise(await fs.promises.readFile(this.path)); - return this.parseMap(xml.map); + return this.parseMap(xml.map, gamma); } - async parseMap(mapXml) { - checkTypes(arguments, Object); - const tileSet = await this.parseSet(mapXml.tileset[0]); + async parseMap(mapXml, gamma) { + checkTypes(arguments, Object, "number"); + const tileSet = await this.parseSet(mapXml.tileset[0], gamma); const tileMap = new TileMap(this.name, ~~mapXml.$.width, ~~mapXml.$.height, tileSet); const indices = mapXml.layer[0].data[0]._.replace(/\s/g, "").split(",").map(i => ~~i - 1); for (const index of indices) { @@ -144,10 +145,10 @@ return tileMap; } - async parseSet(setXml) { - checkTypes(arguments, Object); + async parseSet(setXml, gamma) { + checkTypes(arguments, Object, "number"); const imagepath = path.resolve(path.dirname(this.path), setXml.image[0].$.source); - const image = await new PNGLoader(imagepath).loadImage(); + const image = await new PNGLoader(imagepath, gamma).loadImage(); const tileSet = new TileSet(setXml.$.name, ~~setXml.$.tilewidth, ~~setXml.$.tileheight, image.palette); const tileImages = image.toTiles(tileSet.width, tileSet.height); for (let i = 0; i < tileImages.length; i++) {