Przeglądaj źródła

improve print texture debug helpers

Alexander Rose 3 lat temu
rodzic
commit
54476ad85e

+ 7 - 4
src/mol-gl/compute/util.ts

@@ -6,11 +6,12 @@
 
 import { WebGLContext } from '../../mol-gl/webgl/context';
 import { Texture } from '../../mol-gl/webgl/texture';
-import { printTextureImage } from '../../mol-gl/renderable/util';
+import { PrintImageOptions, printTextureImage } from '../../mol-gl/renderable/util';
 import { defaults, ValueCell } from '../../mol-util';
 import { ValueSpec, AttributeSpec, UniformSpec, Values } from '../../mol-gl/renderable/schema';
 import { Vec2 } from '../../mol-math/linear-algebra';
 import { GLRenderingContext } from '../../mol-gl/webgl/compat';
+import { PixelData } from '../../mol-util/image';
 
 export const QuadPositions = new Float32Array([
     1.0,  1.0,  -1.0,  1.0,  -1.0, -1.0, // First triangle
@@ -41,7 +42,7 @@ function getArrayForTexture(gl: GLRenderingContext, texture: Texture, size: numb
     throw new Error('unknown/unsupported texture type');
 }
 
-export function readTexture(ctx: WebGLContext, texture: Texture, width?: number, height?: number) {
+export function readTexture(ctx: WebGLContext, texture: Texture, width?: number, height?: number): PixelData {
     const { gl, resources } = ctx;
     width = defaults(width, texture.getWidth());
     height = defaults(height, texture.getHeight());
@@ -55,6 +56,8 @@ export function readTexture(ctx: WebGLContext, texture: Texture, width?: number,
     return { array, width, height };
 }
 
-export function printTexture(ctx: WebGLContext, texture: Texture, scale: number) {
-    printTextureImage(readTexture(ctx, texture), scale);
+export function printTexture(ctx: WebGLContext, texture: Texture, options: Partial<PrintImageOptions> = {}) {
+    const pixelData = readTexture(ctx, texture);
+    PixelData.flipY(pixelData);
+    printTextureImage(pixelData, options);
 }

+ 39 - 13
src/mol-gl/renderable/util.ts

@@ -39,7 +39,15 @@ export function createTextureImage<T extends Uint8Array | Float32Array>(n: numbe
     return { array, width, height };
 }
 
-export function printTextureImage(textureImage: TextureImage<any>, scale = 1) {
+const DefaultPrintImageOptions = {
+    scale: 1,
+    pixelated: false,
+    id: 'molstar.debug.image'
+};
+export type PrintImageOptions = typeof DefaultPrintImageOptions
+
+export function printTextureImage(textureImage: TextureImage<any>, options: Partial<PrintImageOptions> = {}) {
+
     const { array, width, height } = textureImage;
     const itemSize = array.length / (width * height);
     const data = new Uint8ClampedArray(width * height * 4);
@@ -54,32 +62,50 @@ export function printTextureImage(textureImage: TextureImage<any>, scale = 1) {
     } else {
         console.warn(`itemSize '${itemSize}' not supported`);
     }
-    return printImageData(new ImageData(data, width, height), scale);
+    return printImageData(new ImageData(data, width, height), options);
 }
 
-export function printImageData(imageData: ImageData, scale = 1, pixelated = false) {
-    const canvas = document.createElement('canvas');
+let tmpCanvas: HTMLCanvasElement;
+let tmpCanvasCtx: CanvasRenderingContext2D;
+let tmpContainer: HTMLDivElement;
+
+export function printImageData(imageData: ImageData, options: Partial<PrintImageOptions> = {}) {
+    const o = { ...DefaultPrintImageOptions, ...options };
+    const canvas = tmpCanvas || document.createElement('canvas');
+    tmpCanvas = canvas;
     canvas.width = imageData.width;
     canvas.height = imageData.height;
-    const ctx = canvas.getContext('2d');
+    const ctx = tmpCanvasCtx || canvas.getContext('2d');
+    tmpCanvasCtx = ctx;
     if (!ctx) throw new Error('Could not create canvas 2d context');
     ctx.putImageData(imageData, 0, 0);
+
+    if (!tmpContainer) {
+        tmpContainer = document.createElement('div');
+        tmpContainer.style.position = 'absolute';
+        tmpContainer.style.bottom = '0px';
+        tmpContainer.style.right = '0px';
+        tmpContainer.style.border = 'solid orange';
+        tmpContainer.style.pointerEvents = 'none';
+        document.body.appendChild(tmpContainer);
+    }
+
     canvas.toBlob(imgBlob => {
-        const objectURL = window.URL.createObjectURL(imgBlob);
-        const img = document.createElement('img');
+        const objectURL = URL.createObjectURL(imgBlob);
+        const existingImg = document.getElementById(o.id) as HTMLImageElement;
+        const img = existingImg || document.createElement('img');
+        img.id = o.id;
         img.src = objectURL;
-        img.style.width = imageData.width * scale + 'px';
-        img.style.height = imageData.height * scale + 'px';
-        if (pixelated) {
+        img.style.width = imageData.width * o.scale + 'px';
+        img.style.height = imageData.height * o.scale + 'px';
+        if (o.pixelated) {
             // not supported in Firefox and IE
             img.style.imageRendering = 'pixelated';
         }
         img.style.position = 'relative';
-        img.style.top = '0px';
-        img.style.left = '0px';
         img.style.border = 'solid grey';
         img.style.pointerEvents = 'none';
-        document.body.appendChild(img);
+        if (!existingImg) tmpContainer.appendChild(img);
     }, 'image/png');
 }
 

+ 4 - 3
src/mol-util/image.ts

@@ -7,13 +7,13 @@
 export { PixelData };
 
 interface PixelData {
-    readonly array: Uint8Array
+    readonly array: Uint8Array | Float32Array
     readonly width: number
     readonly height: number
 }
 
 namespace PixelData {
-    export function create(array: Uint8Array, width: number, height: number): PixelData {
+    export function create(array: Uint8Array | Float32Array, width: number, height: number): PixelData {
         return { array, width, height };
     }
 
@@ -36,8 +36,9 @@ namespace PixelData {
     /** to undo pre-multiplied alpha */
     export function divideByAlpha(pixelData: PixelData): PixelData {
         const { array } = pixelData;
+        const factor = (array instanceof Uint8Array) ? 255 : 1;
         for (let i = 0, il = array.length; i < il; i += 4) {
-            const a = array[i + 3] / 255;
+            const a = array[i + 3] / factor;
             array[i] /= a;
             array[i + 1] /= a;
             array[i + 2] /= a;

+ 1 - 1
src/tests/browser/font-atlas.ts

@@ -33,7 +33,7 @@ function test() {
     fontAtlas.get(String.fromCharCode(0x212B));
     console.timeEnd('Angstrom Sign');
 
-    printTextureImage(fontAtlas.texture, 0.5);
+    printTextureImage(fontAtlas.texture, { scale: 0.5 });
     console.log(`${Object.keys(fontAtlas.mapped).length} chars prepared`);
 }