"use strict"; var palette; function PixelEditor(parentDiv, fmt, palette, initialData, thumbnails) { var self = this; var width = fmt.w; var height = fmt.h; function createCanvas(parent) { var c = document.createElement('canvas'); c.width = width; c.height = height; if (fmt.xform) c.style.transform = fmt.xform; c.classList.add("pixels"); c.classList.add("pixelated"); //canvas.tabIndex = "-1"; // Make it focusable $(parentDiv).empty().append(c); return c; } function updateImage() { ctx.putImageData(pixdata, 0, 0); } function updateThumbnails() { if (!thumbnails) return; for (var i=0; i> 0) & 0xff) << 16; y |= ((x >> 8) & 0xff) << 8; y |= ((x >> 16) & 0xff) << 0; return y; } this.createPaletteButtons = function() { var span = $("#palette_group").empty(); for (var i=0; i'); var rgb = palette[i] & 0xffffff; var color = "#" + hex(revrgb(rgb), 6); btn.click(self.setCurrentColor.bind(this, i)); btn.attr('id', 'palcol_' + i); btn.css('backgroundColor', color).text(i.toString(16)); if ((rgb & 0x808080) != 0x808080) { btn.css('color', 'white'); } span.append(btn); } self.setCurrentColor(1); } function getPixelByOffset(ofs) { var oldrgba = pixints[ofs] & 0xffffff; for (var i=0; i= width || y < 0 || y >= height) return; var ofs = x+y*width; var oldrgba = pixints[ofs]; var rgba = palette[col]; if (oldrgba != rgba) { pixints[ofs] = rgba; updateImage(); } } this.getImageColors = function() { var pixcols = new Uint8Array(pixints.length); for (var i=0; i= 0) $("#palcol_" + curpalcol).removeClass('selected'); curpalcol = col; $("#palcol_" + col).addClass('selected'); } } self.setCurrentColor = setCurrentColor; var dragcol = 1; var dragging = false; var pxls = $(pixcanvas); pxls.mousedown(function(e) { var pos = getPositionFromEvent(e); dragcol = getPixel(pos.x, pos.y) == curpalcol ? 0 : curpalcol; setPixel(pos.x, pos.y, curpalcol); dragging = true; pixcanvas.setCapture(); }) .mousemove(function(e) { var pos = getPositionFromEvent(e); if (dragging) { setPixel(pos.x, pos.y, dragcol); } }) .mouseup(function(e) { var pos = getPositionFromEvent(e); setPixel(pos.x, pos.y, dragcol); dragging = false; updateThumbnails(); pixcanvas.releaseCapture(); }); } } ///////////////// var pixel_re = /([0#]?)([x$%])([0-9a-f]+)/gi; function parseHexBytes(s) { var arr = []; var m; while (m = pixel_re.exec(s)) { var n; if (m[2].startsWith('%')) n = parseInt(m[3],2); else if (m[2].startsWith('x') || m[2].startsWith('$')) n = parseInt(m[3],16); else n = parseInt(m[3]); arr.push(n); } return arr; } function replaceHexBytes(s, bytes) { var result = ""; var m; var li = 0; var i = 0; while (m = pixel_re.exec(s)) { result += s.slice(li, pixel_re.lastIndex - m[0].length); li = pixel_re.lastIndex; if (m[2].startsWith('%')) result += m[1] + "%" + bytes[i++].toString(2); else if (m[2].startsWith('x')) result += m[1] + "x" + hex(bytes[i++]); else if (m[2].startsWith('$')) result += m[1] + "$" + hex(bytes[i++]); else result += m[1] + bytes[i++].toString(); } result += s.slice(li); return result; } function remapBits(x, arr) { if (!arr) return x; var y = 0; for (var i=0; i>(8-shift-bpp) : byte>>shift) & mask) << (p*bpp); } imgdata.push(color); shift += bpp; if (shift >= 8) { ofs0 += 1; shift = 0; } } } images.push(imgdata); } return images; } function convertImagesToBytes(images, fmt) { var width = fmt.w; var height = fmt.h; var count = fmt.count || 1; var bpp = fmt.bpp || 1; var nplanes = fmt.np || 1; var bytesperline = fmt.sl || Math.ceil(fmt.w * bpp / 8); var mask = (1 << bpp)-1; var bytes = new Uint8Array(bytesperline * height * nplanes * count); for (var n=0; n> (p*bpp)) & mask; bytes[ofs + p*(fmt.pofs|0)] |= (fmt.brev ? (c << (8-shift-bpp)) : (c << shift)); } shift += bpp; if (shift >= 8) { ofs0 += 1; shift = 0; } } } } return bytes; } function convertPaletteBytes(arr,r0,r1,g0,g1,b0,b1) { var result = []; for (var i=0; i> r0) & ((1<> g0) & ((1<> b0) & ((1<= 0) palette = convertPaletteBytes(palbytes, 0, rr, rr, gg, rr+gg, bb); else palette = convertPaletteBytes(palbytes, rr+gg, bb, rr, gg, 0, rr); } else { // TODO: default palette? } palette = new Uint32Array(palette); } function pixelEditorCreateThumbnails(e) { // create thumbnail for all images $("#thumbnaildiv").empty(); var parentdiv; var count = e.data.fmt.count || 1; allthumbs = []; for (var i=0; i"); } allthumbs.push(createThumbnailForImage(parentdiv, i)); } } function pixelEditorReceiveMessage(e) { pixelEditorDecodeMessage(e); pixelEditorCreateThumbnails(e); // create initial editor createEditorForImage(0); } function createThumbnailForImage(parentdiv, i) { var span = $(''); var thumb = new PixelEditor(span, currentFormat, palette, allimages[i]); parentdiv.append(span); span.click(function() { createEditorForImage(i) }); return thumb; } function createEditorForImage(i) { currentPixelEditor = new PixelEditor(maineditor, currentFormat, palette, allimages[i], [allthumbs[i]]); currentPixelEditor.resize(); currentPixelEditor.makeEditable(); currentPixelEditor.createPaletteButtons(); } function postToParentWindow(data) { if (data.save) { var allimgs = []; for (var i=0; i= 48 && c <= 57) { currentPixelEditor.setCurrentColor(c-48); } else if (c >= 97 && c <= 102) { currentPixelEditor.setCurrentColor(c-97+10); } }