3dlut-base-cube-maker.html 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <!doctype html>
  2. <html>
  3. <meta charset="utf-8">
  4. <head>
  5. <title>3DLUT Base Cube Maker</title>
  6. <style>
  7. canvas {
  8. min-width: 512px;
  9. min-height: 64px;
  10. image-rendering: pixelated;
  11. }
  12. #cube {
  13. max-width: calc(100% - 20px);
  14. overflow: auto;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <h1>Color Cube Image Maker</h1>
  20. <div>size:<input id="size" type="number" value="8" min="2" max="64"/></div>
  21. <p><button type="button">Save...</button></p>
  22. <div id="cube"><canvas></canvas></div>
  23. <div>( note: actual image size is
  24. <span id="width"></span>x<span id="height"></span> )</div>
  25. </p>
  26. </body>
  27. <script type="module">
  28. const ctx = document.querySelector( 'canvas' ).getContext( '2d' );
  29. function drawColorCubeImage( ctx, size ) {
  30. const canvas = ctx.canvas;
  31. canvas.width = size * size;
  32. canvas.height = size;
  33. for ( let zz = 0; zz < size; ++ zz ) {
  34. for ( let yy = 0; yy < size; ++ yy ) {
  35. for ( let xx = 0; xx < size; ++ xx ) {
  36. const r = Math.floor( xx / ( size - 1 ) * 255 );
  37. const g = Math.floor( yy / ( size - 1 ) * 255 );
  38. const b = Math.floor( zz / ( size - 1 ) * 255 );
  39. ctx.fillStyle = `rgb(${r},${g},${b})`;
  40. ctx.fillRect( zz * size + xx, yy, 1, 1 );
  41. }
  42. }
  43. }
  44. document.querySelector( '#width' ).textContent = canvas.width;
  45. document.querySelector( '#height' ).textContent = canvas.height;
  46. }
  47. drawColorCubeImage( ctx, 8 );
  48. function handleSizeChange( event ) {
  49. const elem = event.target;
  50. elem.style.background = '';
  51. try {
  52. const size = parseInt( elem.value );
  53. if ( size >= 2 && size <= 64 ) {
  54. drawColorCubeImage( ctx, size );
  55. }
  56. } catch ( e ) {
  57. elem.style.background = 'red';
  58. }
  59. }
  60. const sizeElem = document.querySelector( '#size' );
  61. sizeElem.addEventListener( 'change', handleSizeChange, true );
  62. const saveData = ( function () {
  63. const a = document.createElement( 'a' );
  64. document.body.appendChild( a );
  65. a.style.display = 'none';
  66. return function saveData( blob, fileName ) {
  67. const url = window.URL.createObjectURL( blob );
  68. a.href = url;
  69. a.download = fileName;
  70. a.click();
  71. };
  72. }() );
  73. document.querySelector( 'button' ).addEventListener( 'click', () => {
  74. ctx.canvas.toBlob( ( blob ) => {
  75. saveData( blob, `identity-lut-s${ctx.canvas.height}.png` );
  76. } );
  77. } );
  78. </script>
  79. </html>