headless-plugin-context.ts 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /**
  2. * Copyright (c) 2023 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Adam Midlik <midlik@gmail.com>
  5. */
  6. import fs from 'fs';
  7. import { type PNG } from 'pngjs'; // Only import type here, the actual import must be provided by the caller
  8. import { type BufferRet as JpegBufferRet } from 'jpeg-js'; // Only import type here, the actual import must be provided by the caller
  9. import { Canvas3D } from '../mol-canvas3d/canvas3d';
  10. import { PostprocessingProps } from '../mol-canvas3d/passes/postprocessing';
  11. import { PluginContext } from './context';
  12. import { PluginSpec } from './spec';
  13. import { HeadlessScreenshotHelper, HeadlessScreenshotHelperOptions, ExternalModules, RawImageData } from './util/headless-screenshot';
  14. /** PluginContext that can be used in Node.js (without DOM) */
  15. export class HeadlessPluginContext extends PluginContext {
  16. renderer: HeadlessScreenshotHelper;
  17. /** External modules (`gl` and optionally `pngjs` and `jpeg-js`) must be provided to the constructor (this is to avoid Mol* being dependent on these packages which are only used here) */
  18. constructor(externalModules: ExternalModules, spec: PluginSpec, canvasSize: { width: number, height: number } = { width: 640, height: 480 }, rendererOptions?: HeadlessScreenshotHelperOptions) {
  19. super(spec);
  20. this.renderer = new HeadlessScreenshotHelper(externalModules, canvasSize, undefined, rendererOptions);
  21. (this.canvas3d as Canvas3D) = this.renderer.canvas3d;
  22. }
  23. /** Render the current plugin state and save to a PNG or JPEG file */
  24. async saveImage(outPath: string, imageSize?: { width: number, height: number }, props?: Partial<PostprocessingProps>, format?: 'png' | 'jpeg', jpegQuality = 90) {
  25. this.canvas3d!.commit(true);
  26. return await this.renderer.saveImage(outPath, imageSize, props, format, jpegQuality);
  27. }
  28. /** Render the current plugin state and return as raw image data */
  29. async getImageRaw(imageSize?: { width: number, height: number }, props?: Partial<PostprocessingProps>): Promise<RawImageData> {
  30. this.canvas3d!.commit(true);
  31. return await this.renderer.getImageRaw(imageSize, props);
  32. }
  33. /** Render the current plugin state and return as a PNG object */
  34. async getImagePng(imageSize?: { width: number, height: number }, props?: Partial<PostprocessingProps>): Promise<PNG> {
  35. this.canvas3d!.commit(true);
  36. return await this.renderer.getImagePng(imageSize, props);
  37. }
  38. /** Render the current plugin state and return as a JPEG object */
  39. async getImageJpeg(imageSize?: { width: number, height: number }, props?: Partial<PostprocessingProps>, jpegQuality: number = 90): Promise<JpegBufferRet> {
  40. this.canvas3d!.commit(true);
  41. return await this.renderer.getImageJpeg(imageSize, props);
  42. }
  43. /** Get the current plugin state */
  44. async getStateSnapshot() {
  45. this.canvas3d!.commit(true);
  46. return await this.managers.snapshot.getStateSnapshot({ params: {} });
  47. }
  48. /** Save the current plugin state to a MOLJ file */
  49. async saveStateSnapshot(outPath: string) {
  50. const snapshot = this.getStateSnapshot();
  51. const snapshot_json = JSON.stringify(snapshot, null, 2);
  52. await new Promise<void>(resolve => {
  53. fs.writeFile(outPath, snapshot_json, () => resolve());
  54. });
  55. }
  56. }