Skip to content

Commit

Permalink
feat(actions): implement get/save colors
Browse files Browse the repository at this point in the history
Closes #59, #60
  • Loading branch information
christianliebel committed Jul 17, 2020
1 parent 598e099 commit 51ac6d1
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 34 deletions.
51 changes: 51 additions & 0 deletions actions/get-colors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { fileOpen } from '../web_modules/browser-nativefs.js';
import { updateContext } from '../helpers/update-context.js';

export class GetColorsAction {
async execute(drawingContext) {
const file = await fileOpen({ extensions: ['pal'] });
const buffer = await file.arrayBuffer();
const dataView = new DataView(buffer);
const textDecoder = new TextDecoder();

// RIFF header
const header = textDecoder.decode(buffer.slice(0, 4));
if (header !== 'RIFF') {
alert('Non-RIFF palettes are not supported.');
return;
}

// PAL form type
const formType = textDecoder.decode(buffer.slice(8, 12));
if (formType !== 'PAL ') {
alert('Only PAL form types are supported.');
return;
}

// Data chunk
const chunkType = textDecoder.decode(buffer.slice(12, 16));
if (chunkType !== 'data') {
alert('Expected a data chunk.');
return;
}

// LOGPALETTE
const palette = [];
const count = dataView.getUint16(22, true);
for (let i = 0; i < count; i++) {
const offset = 24 + i * 4;

// PALETTEENTRY
const r = dataView.getUint8(offset); // peRed
const g = dataView.getUint8(offset + 1); // peGreen
const b = dataView.getUint8(offset + 2); // peBlue
// peFlags skipped

palette.push(`rgb(${r} ${g} ${b})`);
}

palette.slice(0, 26)
.forEach((color, index) => drawingContext.palette[index] = color);
updateContext(drawingContext.element);
}
}
47 changes: 47 additions & 0 deletions actions/save-colors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { fileSave } from '../web_modules/browser-nativefs.js';

export class SaveColorsAction {
async execute({ palette }) {
const count = palette.length;
const chunkSize = 4 + count * 4;
const size = 24 + count * 4;
const buffer = new ArrayBuffer(size);
const uint8View = new Uint8Array(buffer);
const dataView = new DataView(buffer);
const textEncoder = new TextEncoder();

// RIFF header
uint8View.set(textEncoder.encode('RIFF'));
dataView.setUint32(4, size - 8, true);

// PAL form type
uint8View.set(textEncoder.encode('PAL '), 8);

// Data chunk
uint8View.set(textEncoder.encode('data'), 12); // ckID
dataView.setUint32(16, chunkSize, true); // ckSize

// LOGPALETTE
dataView.setUint16(20, 0x300, true); // palVersion
dataView.setUint16(22, count, true); // palNumEntries

const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
for (let i = 0; i < count; i++) {
context.fillStyle = palette[i];
context.fillRect(0, 0, 1, 1);
const [r, g, b] = context.getImageData(0, 0, 1, 1).data;

const offset = 24 + i * 4;
// PALETTEENTRY
dataView.setUint8(offset, r); // peRed
dataView.setUint8(offset + 1, g); // peGreen
dataView.setUint8(offset + 2, b); // peBlue
dataView.setUint8(offset + 3, 0); // peFlags
}

const blob = new Blob([buffer]);
await fileSave(blob, { fileName: 'untitled.pal' });
}
}

32 changes: 31 additions & 1 deletion elements/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,36 @@ class App extends LitElement {
primary: '#000000',
secondary: '#FFFFFF',
},
palette: [
'#000000', // black
'#808080', // gray
'#800000', // maroon
'#808000', // olive
'#008000', // green
'#008080', // teal
'#000080', // navy
'#800080', // purple
'#808040',
'#004040',
'#0080FF',
'#004080',
'#4000FF',
'#804000',
'#FFFFFF', // white
'#C0C0C0', // silver
'#FF0000', // red
'#FFFF00', // yellow
'#00FF00', // lime
'#00FFFF', // aqua
'#0000FF', // blue
'#FF00FF', // fuchsia
'#FFFF80',
'#00FF80',
'#80FFFF',
'#8080FF',
'#FF0080',
'#FF8040',
],
previewColor: null,
transparentBackground: false,
eraserSize: null,
Expand All @@ -123,7 +153,7 @@ class App extends LitElement {
statusBar: true,
colorBox: true,
toolBox: true,
}
},
};
this.addEventListener(
'set-help-text',
Expand Down
34 changes: 1 addition & 33 deletions elements/color-box.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ class ColorBox extends LitElement {
static get properties() {
return {
drawingContext: { type: Object },

palette: { attribute: false },
};
}

Expand All @@ -29,36 +27,6 @@ class ColorBox extends LitElement {

constructor() {
super();
this.palette = [
'#000000', // black
'#808080', // gray
'#800000', // maroon
'#808000', // olive
'#008000', // green
'#008080', // teal
'#000080', // navy
'#800080', // purple
'#808040',
'#004040',
'#0080FF',
'#004080',
'#4000FF',
'#804000',
'#FFFFFF', // white
'#C0C0C0', // silver
'#FF0000', // red
'#FFFF00', // yellow
'#00FF00', // lime
'#00FFFF', // aqua
'#0000FF', // blue
'#FF00FF', // fuchsia
'#FFFF80',
'#00FF80',
'#80FFFF',
'#8080FF',
'#FF0080',
'#FF8040',
];
}

render() {
Expand All @@ -68,7 +36,7 @@ class ColorBox extends LitElement {
secondaryColor="${this.drawingContext.colors.secondary}"
>
</paint-color-switcher>
${this.palette.map(
${this.drawingContext.palette.map(
(color) =>
html`
<paint-color-picker
Expand Down
5 changes: 5 additions & 0 deletions menus/options.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { SaveColorsAction } from '../actions/save-colors';
import { GetColorsAction } from '../actions/get-colors';

export const optionsMenu = {
caption: 'Options',
mnemonic: 'O',
Expand All @@ -12,11 +15,13 @@ export const optionsMenu = {
caption: 'Get Colors…',
mnemonic: 'G',
helpText: 'Uses a previously saved palette of colors.',
instance: new GetColorsAction(),
},
{
caption: 'Save Colors…',
mnemonic: 'S',
helpText: 'Saves the current palette of colors to a file.',
instance: new SaveColorsAction(),
},
{
caption: 'Draw Opaque',
Expand Down

0 comments on commit 51ac6d1

Please sign in to comment.