"use strict"; 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 commit() { if (!thumbnails) return; for (var i=0; i w) pixcanvas.style.height = Math.floor(h)+"px"; else pixcanvas.style.height = Math.floor(h/2)+"px"; // TODO } this.resize = fitCanvas; var pixcanvas = createCanvas(); var ctx = pixcanvas.getContext('2d'); var pixdata = ctx.createImageData(width, height); var pixints = new Uint32Array(pixdata.data.buffer); 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; commit(); pixcanvas.releaseCapture(); }); } this.rotate = function(deg) { console.log("rotate " + deg); var s1 = Math.sin(deg * Math.PI / 180); var c1 = Math.cos(deg * Math.PI / 180); var p = self.getImageColors(); var i = 0; for (var y=0; y>(8-shift-bpp) : byte>>shift) & mask) << (p*bpp); } imgdata.push(color); shift += bpp; if (shift >= 8) { ofs0 += 1; shift = 0; } } } images.push(new Uint8Array(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 pofs = fmt.pofs || bytesperline*height*count; var bytes = new Uint8Array(bytesperline*height*count*nplanes); for (var n=0; n> (p*bpp)) & mask; bytes[ofs + p*pofs] |= (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) { var rr = Math.floor(Math.abs(pal/100) % 10); var gg = Math.floor(Math.abs(pal/10) % 10); var bb = Math.floor(Math.abs(pal) % 10); // TODO: n if (currentPaletteFmt.pal >= 0) palette = convertPaletteBytes(palbytes, 0, rr, rr, gg, rr+gg, bb); else palette = convertPaletteBytes(palbytes, rr+gg, bb, rr, gg, 0, rr); } else { var paltable = PREDEF_PALETTES[pal]; if (paltable) { palette = palbytes.map(function(i) { return paltable[i]; }); } else { alert("No palette named " + pal); } } if (currentPaletteFmt.n) { paletteSets = []; 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); } else { switch (e.keyCode) { case 33: // PgUp currentPixelEditor.rotate(-90); break; case 34: // PgDn currentPixelEditor.rotate(90); break; case 35: // PgUp currentPixelEditor.rotate(-45); break; case 36: // PgDn currentPixelEditor.rotate(45); break; default: console.log(e); break; } } } var PREDEF_PALETTES = { 'nes':[ 0xFF7C7C7C ,0xFF0000FC ,0xFF0000BC ,0xFF4428BC ,0xFF940084 ,0xFFA80020 ,0xFFA81000 ,0xFF881400 ,0xFF503000 ,0xFF007800 ,0xFF006800 ,0xFF005800 ,0xFF004058 ,0xFF000000 ,0xFF000000 ,0xFF000000 ,0xFFBCBCBC ,0xFF0078F8 ,0xFF0058F8 ,0xFF6844FC ,0xFFD800CC ,0xFFE40058 ,0xFFF83800 ,0xFFE45C10 ,0xFFAC7C00 ,0xFF00B800 ,0xFF00A800 ,0xFF00A844 ,0xFF008888 ,0xFF000000 ,0xFF000000 ,0xFF000000 ,0xFFF8F8F8 ,0xFF3CBCFC ,0xFF6888FC ,0xFF9878F8 ,0xFFF878F8 ,0xFFF85898 ,0xFFF87858 ,0xFFFCA044 ,0xFFF8B800 ,0xFFB8F818 ,0xFF58D854 ,0xFF58F898 ,0xFF00E8D8 ,0xFF787878 ,0xFF000000 ,0xFF000000 ,0xFFFCFCFC ,0xFFA4E4FC ,0xFFB8B8F8 ,0xFFD8B8F8 ,0xFFF8B8F8 ,0xFFF8A4C0 ,0xFFF0D0B0 ,0xFFFCE0A8 ,0xFFF8D878 ,0xFFD8F878 ,0xFFB8F8B8 ,0xFFB8F8D8 ,0xFF00FCFC ,0xFFF8D8F8 ,0xFF000000 ,0xFF000000 ] };