Создать изображение в чистом JS без холста ? - PullRequest
5 голосов
/ 30 сентября 2019

Как сгенерировать картинку в чистом JavaScript (без внешней библиотеки) из массива пикселей без холста? Я пытаюсь сгенерировать изображение в форме URI, но безуспешно (формат изображения s нелегко быстро понять и реализовать)

1 Ответ

6 голосов
/ 30 сентября 2019

BMP dataURI

Вы можете сгенерировать BMP (битовую карту) dataURI, используя функцию ниже. RAW BMP с 24 битами - 16x16 RGB преобразуется в 2397 байт dataURI (ширина изображения должна делиться на 4).

/**
 * Generate dataURI raw BMP image
 *
 * @param width - image width (num of pixels)
 * @param pixels - 1D array of RGBA pixels (pixel = 4 numbers in
 *                 range 0-255; staring from left bottom corner)
 * @return dataURI string
 */
function genBMPUri(width, pixels) {
  let LE= n=> (n + 2**32).toString(16).match(/\B../g).reverse().join``;
  let wh= LE(width).slice(0,4) + LE(pixels.length/width/3).slice(0,4);
  let size= LE(26+pixels.length);

  let head=`424d${size}000000001a0000000C000000${wh}01001800`;
  
  return "data:image/bmp," + [
           ...head.match(/../g), 
           ...pixels.map(x=> x.toString(16).padStart(2,'0'))
         ].map(x=>'%'+x).join``;
}


// TEST

// 16x16 pixels - 1D Array of pixels (start from bottom-left corner) 
// where one pixel has 3 color component (each 0-255) RGB 
// (but during rendering browser ignore alpha channel - BMP not support alpha)
imgagePixels=[0,0,0,8,90,114,0,0,0,0,0,0,8,31,205,8,31,205,8,31,205,8,31,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,8,90,114,8,90,114,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,8,90,114,8,90,114,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,0,0,0,0,0,0,0,0,0,42,129,252,0,0,0,8,90,114,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,90,114,8,90,114,42,129,252,42,129,252,42,129,252,0,0,0,8,31,205,8,31,205,8,90,114,8,31,205,8,31,205,42,129,252,8,31,205,8,31,205,42,129,252,8,31,205,8,90,114,8,90,114,42,129,252,42,129,252,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,0,0,0,0,0,0,8,90,114,0,0,0,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,31,205,8,90,114,8,90,114,8,90,114,8,31,205,0,0,0,0,0,0,8,90,114,0,0,0,0,0,0,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,31,205,8,90,114,8,90,114,8,90,114,8,31,205,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,129,252,42,129,252,42,129,252,42,129,252,42,129,252,42,129,252,42,129,252,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,8,90,114,42,129,252,42,129,252,42,129,252,42,129,252,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,42,129,252,8,90,114,8,90,114,42,129,252,42,129,252,42,129,252,8,90,114,42,129,252,42,129,252,42,129,252,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,42,129,252,8,90,114,42,129,252,42,129,252,42,129,252,8,90,114,42,129,252,42,129,252,8,90,114,8,90,114,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,8,90,114,8,90,114,42,129,252,42,129,252,8,90,114,42,129,252,0,0,0,8,90,114,8,90,114,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,42,129,252,42,129,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,0,0,0,0,0,0,42,129,252,42,129,252,42,129,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,129,252,42,129,252,42,129,252];

uri = genBMPUri(16, imgagePixels);
msg.innerHTML+= uri;
pic.src= uri;
img{image-rendering: pixelated;width:128px;height:128px}
pre{word-break: break-all;white-space: pre-wrap;}
image
Copy below dataURI to browser url top bar or src attrib in img tag

2464 бит 16x16 RGB с кодировкой Base64 преобразуется в 1118 байтов (~ в 2 раза меньше, чем RAW)

/**
 * Generate dataURI base64 BMP image
 *
 * @param width - image width (num of pixels)
 * @param pixels - 1D array of RGB pixels (pixel = 3 numbers in
 *                 range 0-255; staring from left bottom corner)
 * @return dataURI string
 */
function genBMPUri(width, pixels) {
  let LE= n=> (n + 2**32).toString(16).match(/\B../g).reverse().join``;
  let wh= LE(width).slice(0,4) + LE(pixels.length/width/3).slice(0,4);
  let size= LE(26+pixels.length);

  let head=`424d${size}000000001b0000000C000000${wh}0100180000`;
  
  return "data:image/bmp;base64,"
         + btoa(String.fromCharCode(...head.match(/../g).map(x=> +`0x${x}`))) 
         + btoa(pixels.map(p=>String.fromCharCode(p)).join``);
}


// TEST

// 16x16 pixels - 1D Array of pixels (start from bottom-left corner) 
// where one pixel has 3 color component (each 0-255) RGB 
imgagePixels=[0,0,0,8,90,114,0,0,0,0,0,0,8,31,205,8,31,205,8,31,205,8,31,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,8,90,114,8,90,114,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,8,90,114,8,90,114,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,0,0,0,0,0,0,0,0,0,42,129,252,0,0,0,8,90,114,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,90,114,8,90,114,42,129,252,42,129,252,42,129,252,0,0,0,8,31,205,8,31,205,8,90,114,8,31,205,8,31,205,42,129,252,8,31,205,8,31,205,42,129,252,8,31,205,8,90,114,8,90,114,42,129,252,42,129,252,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,0,0,0,0,0,0,8,90,114,0,0,0,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,31,205,8,90,114,8,90,114,8,90,114,8,31,205,0,0,0,0,0,0,8,90,114,0,0,0,0,0,0,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,8,31,205,8,90,114,8,90,114,8,90,114,8,31,205,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,129,252,42,129,252,42,129,252,42,129,252,42,129,252,42,129,252,42,129,252,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,8,90,114,42,129,252,42,129,252,42,129,252,42,129,252,8,90,114,8,90,114,8,90,114,8,90,114,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,42,129,252,8,90,114,8,90,114,42,129,252,42,129,252,42,129,252,8,90,114,42,129,252,42,129,252,42,129,252,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,42,129,252,8,90,114,42,129,252,42,129,252,42,129,252,8,90,114,42,129,252,42,129,252,8,90,114,8,90,114,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,90,114,8,90,114,8,90,114,42,129,252,42,129,252,8,90,114,42,129,252,0,0,0,8,90,114,8,90,114,8,90,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,42,129,252,42,129,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,31,205,8,31,205,8,31,205,8,31,205,8,31,205,0,0,0,0,0,0,42,129,252,42,129,252,42,129,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,129,252,42,129,252,42,129,252];

uri = genBMPUri(16, imgagePixels);
msg.innerHTML+= uri;
pic.src= uri;
img{image-rendering: pixelated;width:128px;height:128px}
pre{word-break: break-all;white-space: pre-wrap;}
image
Copy below dataURI to browser url top bar or src attrib in img tag

RAW Прозрачный BMP 32-битный RGBA 16x16 (3453 байта)

/**
 * Generate dataURI raw BMP image
 *
 * @param width - image width (num of pixels)
 * @param pixels - 1D array of RGBA pixels (pixel = 4 numbers in
 *                 range 0-255; staring from left bottom corner)
 * @return dataURI string
 */
function genBMPUri(width, pixels) {
  let LE= n=> (n + 2**32).toString(16).match(/\B../g).reverse().join``;
  let wh= LE(width) + LE(pixels.length/width/4);
  let size= LE(108+pixels.length);
  let r= n=>'0'.repeat(n);
  
  let head = `424d${size}ZZ7AZ006CZ00${wh}01002Z3${r(50)}FFZFFZFFZZZFF${r(104)}`

  return "data:image/bmp," + [
            ...head.replace(/Z/g,'0000').match(/../g), 
            ...pixels.map(x=> x.toString(16).padStart(2,'0'))
         ].map(x=>'%'+x).join``;
}


// TEST
// 16x16 pixels - 1D Array of pixels (start from bottom-left corner) 
// where one pixel has 4 color component (each 0-255) RGBA 
// (but during rendering browser ignore alpha channel - BMP not support alpha)
image=[0,0,0,0,8,90,114,16,0,0,0,32,0,0,0,48,8,31,205,64,8,31,205,80,8,31,205,96,8,31,205,112,0,0,0,128,0,0,0,144,0,0,0,160,0,0,0,176,0,0,0,192,0,0,0,208,0,0,0,224,0,0,0,240,0,0,0,0,8,90,114,16,8,90,114,32,8,90,114,48,8,31,205,64,8,31,205,80,8,31,205,96,8,31,205,112,8,31,205,128,8,31,205,144,8,31,205,160,0,0,0,176,0,0,0,192,0,0,0,208,0,0,0,224,0,0,0,240,0,0,0,0,0,0,0,16,8,90,114,32,8,90,114,48,8,90,114,64,8,31,205,80,8,31,205,96,8,31,205,112,8,31,205,128,8,31,205,144,8,31,205,160,8,31,205,176,8,31,205,192,8,31,205,208,0,0,0,224,0,0,0,240,0,0,0,0,42,129,252,16,0,0,0,32,8,90,114,48,8,31,205,64,8,31,205,80,8,31,205,96,8,31,205,112,8,31,205,128,8,31,205,144,8,31,205,160,8,31,205,176,8,31,205,192,8,31,205,208,8,90,114,224,8,90,114,240,42,129,252,0,42,129,252,16,42,129,252,32,0,0,0,48,8,31,205,64,8,31,205,80,8,90,114,96,8,31,205,112,8,31,205,128,42,129,252,144,8,31,205,160,8,31,205,176,42,129,252,192,8,31,205,208,8,90,114,224,8,90,114,240,42,129,252,0,42,129,252,16,8,90,114,32,8,90,114,48,8,90,114,64,8,90,114,80,8,90,114,96,8,90,114,112,8,31,205,128,8,31,205,144,8,31,205,160,8,31,205,176,8,31,205,192,0,0,0,208,0,0,0,224,8,90,114,240,0,0,0,0,8,90,114,16,8,90,114,32,8,90,114,48,8,90,114,64,8,90,114,80,8,90,114,96,8,90,114,112,8,31,205,128,8,90,114,144,8,90,114,160,8,90,114,176,8,31,205,192,0,0,0,208,0,0,0,224,8,90,114,240,0,0,0,0,0,0,0,16,8,90,114,32,8,90,114,48,8,90,114,64,8,90,114,80,8,90,114,96,8,31,205,112,8,90,114,128,8,90,114,144,8,90,114,
160,8,31,205,176,8,90,114,192,0,0,0,208,0,0,0,224,0,0,0,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,80,42,129,252,96,42,129,252,112,42,129,252,128,42,129,252,144,42,129,252,160,42,129,252,176,42,129,252,192,8,90,114,208,0,0,0,224,0,0,0,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,8,90,114,64,8,90,114,80,42,129,252,96,42,129,252,112,42,129,252,128,42,129,252,144,8,90,114,160,8,90,114,176,8,90,114,192,8,90,114,208,8,90,114,224,0,0,0,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,8,90,114,64,42,129,252,80,8,90,114,96,8,90,114,112,42,129,252,128,42,129,252,144,42,129,252,160,8,90,114,176,42,129,252,192,42,129,252,208,42,129,252,224,8,90,114,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,8,90,114,64,42,129,252,80,8,90,114,96,42,129,252,112,42,129,252,128,42,129,252,144,8,90,114,160,42,129,252,176,42,129,252,192,8,90,114,208,8,90,114,224,8,90,114,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,0,0,0,64,8,90,114,80,8,90,114,96,8,90,114,112,42,129,252,128,42,129,252,144,8,90,114,160,42,129,252,176,0,0,0,192,8,90,114,208,8,90,114,224,8,90,114,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,0,0,0,64,8,31,205,80,8,31,205,96,8,31,205,112,8,31,205,128,8,31,205,144,8,31,205,160,8,31,205,176,8,31,205,192,8,31,205,208,42,129,252,224,42,129,252,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,80,8,31,205,96,8,31,205,112,8,31,205,128,8,31,205,144,8,31,205,160,0,0,0,176,0,0,0,192,42,129,252,208,42,129,252,224,42,129,252,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,80,0,0,0,96,0,0,0,112,0,0,0,128,0,0,0,144,0,0,0,160,0,0,0,176,0,0,0,192,42,129,252,208,42,129,252,224,42,129,252,240]
uri = genBMPUri(16, image);
msg.innerHTML+= uri;
pic.src= uri;
img{position:fixed;image-rendering: pixelated;width:128px;height:128px}
pre{word-break: break-all;white-space: pre-wrap;}
image
    

Base64 Прозрачный BMP 32-битный RGBA 16x16 (1554 байта - ~ в 2 раза меньше, чем RAW)

/**
 * Generate dataURI raw BMP image
 *
 * @param width - image width (num of pixels)
 * @param pixels - 1D array of RGBA pixels (pixel = 4 numbers in
 *                 range 0-255; staring from left bottom corner)
 * @return dataURI string
 */
function genBMPUri(width, pixels) {
  let LE= n=> (n + 2**32).toString(16).match(/\B../g).reverse().join``;
  let wh= LE(width) + LE(pixels.length/width/4);
  let size= LE(109+pixels.length);
  let r= n=>'0'.repeat(n);
  
  let head = `424d${size}ZZ7BZ006CZ00${wh}01002Z3${r(50)}FFZFFZFFZZZFF${r(106)}`

  return "data:image/bmp;base64,"
    + btoa(String.fromCharCode(...head.replace(/Z/g,'0000').match(/../g).map(x=> +`0x${x}`))) 
    + btoa(pixels.map(p=>String.fromCharCode(p)).join``);
}


// TEST
// 16x16 pixels - 1D Array of pixels (start from bottom-left corner) 
// where one pixel has 4 color component (each 0-255) RGBA 
// (but during rendering browser ignore alpha channel - BMP not support alpha)
image=[0,0,0,0,8,90,114,16,0,0,0,32,0,0,0,48,8,31,205,64,8,31,205,80,8,31,205,96,8,31,205,112,0,0,0,128,0,0,0,144,0,0,0,160,0,0,0,176,0,0,0,192,0,0,0,208,0,0,0,224,0,0,0,240,0,0,0,0,8,90,114,16,8,90,114,32,8,90,114,48,8,31,205,64,8,31,205,80,8,31,205,96,8,31,205,112,8,31,205,128,8,31,205,144,8,31,205,160,0,0,0,176,0,0,0,192,0,0,0,208,0,0,0,224,0,0,0,240,0,0,0,0,0,0,0,16,8,90,114,32,8,90,114,48,8,90,114,64,8,31,205,80,8,31,205,96,8,31,205,112,8,31,205,128,8,31,205,144,8,31,205,160,8,31,205,176,8,31,205,192,8,31,205,208,0,0,0,224,0,0,0,240,0,0,0,0,42,129,252,16,0,0,0,32,8,90,114,48,8,31,205,64,8,31,205,80,8,31,205,96,8,31,205,112,8,31,205,128,8,31,205,144,8,31,205,160,8,31,205,176,8,31,205,192,8,31,205,208,8,90,114,224,8,90,114,240,42,129,252,0,42,129,252,16,42,129,252,32,0,0,0,48,8,31,205,64,8,31,205,80,8,90,114,96,8,31,205,112,8,31,205,128,42,129,252,144,8,31,205,160,8,31,205,176,42,129,252,192,8,31,205,208,8,90,114,224,8,90,114,240,42,129,252,0,42,129,252,16,8,90,114,32,8,90,114,48,8,90,114,64,8,90,114,80,8,90,114,96,8,90,114,112,8,31,205,128,8,31,205,144,8,31,205,160,8,31,205,176,8,31,205,192,0,0,0,208,0,0,0,224,8,90,114,240,0,0,0,0,8,90,114,16,8,90,114,32,8,90,114,48,8,90,114,64,8,90,114,80,8,90,114,96,8,90,114,112,8,31,205,128,8,90,114,144,8,90,114,160,8,90,114,176,8,31,205,192,0,0,0,208,0,0,0,224,8,90,114,240,0,0,0,0,0,0,0,16,8,90,114,32,8,90,114,48,8,90,114,64,8,90,114,80,8,90,114,96,8,31,205,112,8,90,114,128,8,90,114,144,8,90,114,
160,8,31,205,176,8,90,114,192,0,0,0,208,0,0,0,224,0,0,0,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,80,42,129,252,96,42,129,252,112,42,129,252,128,42,129,252,144,42,129,252,160,42,129,252,176,42,129,252,192,8,90,114,208,0,0,0,224,0,0,0,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,8,90,114,64,8,90,114,80,42,129,252,96,42,129,252,112,42,129,252,128,42,129,252,144,8,90,114,160,8,90,114,176,8,90,114,192,8,90,114,208,8,90,114,224,0,0,0,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,8,90,114,64,42,129,252,80,8,90,114,96,8,90,114,112,42,129,252,128,42,129,252,144,42,129,252,160,8,90,114,176,42,129,252,192,42,129,252,208,42,129,252,224,8,90,114,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,8,90,114,64,42,129,252,80,8,90,114,96,42,129,252,112,42,129,252,128,42,129,252,144,8,90,114,160,42,129,252,176,42,129,252,192,8,90,114,208,8,90,114,224,8,90,114,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,0,0,0,64,8,90,114,80,8,90,114,96,8,90,114,112,42,129,252,128,42,129,252,144,8,90,114,160,42,129,252,176,0,0,0,192,8,90,114,208,8,90,114,224,8,90,114,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,0,0,0,64,8,31,205,80,8,31,205,96,8,31,205,112,8,31,205,128,8,31,205,144,8,31,205,160,8,31,205,176,8,31,205,192,8,31,205,208,42,129,252,224,42,129,252,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,80,8,31,205,96,8,31,205,112,8,31,205,128,8,31,205,144,8,31,205,160,0,0,0,176,0,0,0,192,42,129,252,208,42,129,252,224,42,129,252,240,0,0,0,0,0,0,0,16,0,0,0,32,0,0,0,48,0,0,0,64,0,0,0,80,0,0,0,96,0,0,0,112,0,0,0,128,0,0,0,144,0,0,0,160,0,0,0,176,0,0,0,192,42,129,252,208,42,129,252,224,42,129,252,240]
uri = genBMPUri(16, image);
msg.innerHTML+= uri;
pic.src= uri;
img{position:fixed;image-rendering: pixelated;width:128px;height:128px}
pre{word-break: break-all;white-space: pre-wrap;}
image
    

БОНУС

  • Нельзя использовать нотацию String.fromCharCode(...array) с большими массивами (например, 256* 256 * 4) это вызовет исключение (вам нужно выполнить преобразование по одному, как в фрагменте base64 выше).
  • Подробности для BMP-заголовка примера изображения (+ little endian процедура, которая произошла от здесь )

                          // hex values, offsets and sizes in little endian
head = [                  // header (before 16x16 RGBA(32bit) pixels  = 1024 bytes raw pixels data)
  "42", "4d",             // "BM" bitmap signature
  "1a", "04", "00", "00", // 0x41a = 1050dec = 16*16*4+26 bytes, total size of header and pixels 
  "00", "00", "00", "00", // reserved
  "1a", "00", "00", "00", // 0x1a=26 bytes, header size (pixels raw data start offset)
  "0C", "00", "00", "00", // 0x0C=12 bytes, Size of DIB header (type signature) - here:  BITMAPCOREHEADER
  "10", "00",             // 0x10=16 pixel, width  INT (little endian)
  "10", "00",             // 0x10=16 pixel, height INT (little endian)
  "01", "00",             // reserved
  "18", "00",             // bit per pixel 0x18=24 (1,4,8,16=0x10,24=0x18,32=0x20)
];

// Conversion to little endian example (padding to 32bit)
// 0x45678 -> 0x00045678 -> 0x78560400
LE = (0x45678 + 2**32).toString(16).match(/\B../g).reverse().join``;
console.log(LE);
  • детали прозрачного заголовка BMP

bmpHeaderHex = [
"42", "4d", 				 // "BM"
"6c","04","00","00", // 0x46c=1132 size of file in bytes
"00","00","00","00", // reserved
"7a","00","00","00", // 0x7a=122 bitmap raw data start offset (can be changed)
//DIB header
"6c","00","00","00", // 0x6C=108 header size/sign BITMAPV4HEADER
"10","00","00","00", // 0x10=16 pixel width  INT
"10","00","00","00", // 0x10=16 pixel height  INT
"01","00",	         // reserved
"20","00",	         // 0x20=32 bit per pixel

"03","00","00","00", // BI_BITFIELDS, no pixel array compression used
"00","00","00","00", // Size of the raw bitmap data (including padding)
"00","00","00","00", // width ppm
"00","00","00","00", // height ppm
"00","00","00","00", // colors in palette
"00","00","00","00", // important colors

"00","00","FF","00", // red channel bit mask
"00","FF","00","00", // green channel bit mask
"FF","00","00","00", // blue channel bit mask
"00","00","00","FF", // alpha channel bit mask
"20","6E","69","57", // little-endian 'Win '

"00","00","00","00", // unused 
"00","00","00","00", // unused 
"00","00","00","00", // unused 
"00","00","00","00", // unused 
"00","00","00","00", // unused 
"00","00","00","00", // unused 
"00","00","00","00", // unused 
"00","00","00","00", // unused 
"00","00","00","00", // unused 

"00","00","00","00", // 0 Red Gamma
"00","00","00","00", // 0 Green Gamma
"00","00","00","00", // 0 Blue Gamma
];
  • пример кода-фрактала с гольфом (после генерации ~ 5s вы можете щелкнуть по изображению rmb, скопировать его адрес и вставить в адресную строку браузера)

c=512;for(p=i='';j=x=y=0,++i<=c*c;p+=9*c+9*j)while(x*x+y*y<4&&++j-c)[x,y]=[x*x-y*y+i%c/128-2,2*x*y+i/c/128-2]
document.write(`<img src=data:image/bmp;base64,Qk0bAAwAAAAAABsAAAAMAAAAAAIAAgEAGAAA${p}>`)
...