1 | {"version":3,"file":"ImageResource.js","sources":["../../../src/textures/resources/ImageResource.ts"],"sourcesContent":["import { ALPHA_MODES } from '@pixi/constants';\nimport { settings } from '@pixi/settings';\nimport { BaseImageResource } from './BaseImageResource';\n\nimport type { Renderer } from '../../Renderer';\nimport type { BaseTexture } from '../BaseTexture';\nimport type { GLTexture } from '../GLTexture';\n\nexport interface IImageResourceOptions\n{\n /** Start loading process automatically when constructed. */\n autoLoad?: boolean;\n\n /** Whether its required to create a bitmap before upload. */\n createBitmap?: boolean;\n\n /** Load image using cross origin. */\n crossorigin?: boolean | string;\n\n /** Premultiply image alpha in bitmap. */\n alphaMode?: ALPHA_MODES;\n}\n\n/**\n * Resource type for HTMLImageElement.\n * @memberof PIXI\n */\nexport class ImageResource extends BaseImageResource\n{\n /** URL of the image source */\n url: string;\n\n /**\n * If the image should be disposed after upload\n * @default false\n */\n preserveBitmap: boolean;\n\n /**\n * If capable, convert the image using createImageBitmap API.\n * @default PIXI.settings.CREATE_IMAGE_BITMAP\n */\n createBitmap: boolean;\n\n /**\n * Controls texture alphaMode field\n * Copies from options\n * Default is `null`, copies option from baseTexture\n * @readonly\n */\n alphaMode: ALPHA_MODES;\n\n /**\n * The ImageBitmap element created for a {@link HTMLImageElement}.\n * @default null\n */\n bitmap: ImageBitmap;\n\n /**\n * Promise when loading.\n * @default null\n */\n private _load: Promise<this>;\n\n /** When process is completed */\n private _process: Promise<this>;\n\n /**\n * @param source - image source or URL\n * @param options\n * @param {boolean} [options.autoLoad=true] - start loading process\n * @param {boolean} [options.createBitmap=PIXI.settings.CREATE_IMAGE_BITMAP] - whether its required to create\n * a bitmap before upload\n * @param {boolean} [options.crossorigin=true] - Load image using cross origin\n * @param {PIXI.ALPHA_MODES} [options.alphaMode=PIXI.ALPHA_MODES.UNPACK] - Premultiply image alpha in bitmap\n */\n constructor(source: HTMLImageElement | string, options?: IImageResourceOptions)\n {\n options = options || {};\n\n if (typeof source === 'string')\n {\n const imageElement = new Image();\n\n BaseImageResource.crossOrigin(imageElement, source, options.crossorigin);\n\n imageElement.src = source;\n source = imageElement;\n }\n\n super(source);\n\n // FireFox 68, and possibly other versions, seems like setting the HTMLImageElement#width and #height\n // to non-zero values before its loading completes if images are in a cache.\n // Because of this, need to set the `_width` and the `_height` to zero to avoid uploading incomplete images.\n // Please refer to the issue #5968 (https://github.com/pixijs/pixijs/issues/5968).\n if (!source.complete && !!this._width && !!this._height)\n {\n this._width = 0;\n this._height = 0;\n }\n\n this.url = source.src;\n\n this._process = null;\n\n this.preserveBitmap = false;\n this.createBitmap = (options.createBitmap ?? settings.CREATE_IMAGE_BITMAP) && !!globalThis.createImageBitmap;\n this.alphaMode = typeof options.alphaMode === 'number' ? options.alphaMode : null;\n this.bitmap = null;\n\n this._load = null;\n\n if (options.autoLoad !== false)\n {\n this.load();\n }\n }\n\n /**\n * Returns a promise when image will be loaded and processed.\n * @param createBitmap - whether process image into bitmap\n */\n load(createBitmap?: boolean): Promise<this>\n {\n if (this._load)\n {\n return this._load;\n }\n\n if (createBitmap !== undefined)\n {\n this.createBitmap = createBitmap;\n }\n\n this._load = new Promise((resolve, reject): void =>\n {\n const source = this.source as HTMLImageElement;\n\n this.url = source.src;\n\n const completed = (): void =>\n {\n if (this.destroyed)\n {\n return;\n }\n source.onload = null;\n source.onerror = null;\n\n this.update();\n this._load = null;\n\n if (this.createBitmap)\n {\n resolve(this.process());\n }\n else\n {\n resolve(this);\n }\n };\n\n if (source.complete && source.src)\n {\n completed();\n }\n else\n {\n source.onload = completed;\n source.onerror = (event): void =>\n {\n // Avoids Promise freezing when resource broken\n reject(event);\n this.onError.emit(event);\n };\n }\n });\n\n return this._load;\n }\n\n /**\n * Called when we need to convert image into BitmapImage.\n * Can be called multiple times, real promise is cached inside.\n * @returns - Cached promise to fill that bitmap\n */\n process(): Promise<this>\n {\n const source = this.source as HTMLImageElement;\n\n if (this._process !== null)\n {\n return this._process;\n }\n if (this.bitmap !== null || !globalThis.createImageBitmap)\n {\n return Promise.resolve(this);\n }\n\n const createImageBitmap = globalThis.createImageBitmap as any;\n const cors = !source.crossOrigin || source.crossOrigin === 'anonymous';\n\n this._process = fetch(source.src,\n {\n mode: cors ? 'cors' : 'no-cors'\n })\n .then((r) => r.blob())\n .then((blob) => createImageBitmap(blob,\n 0, 0, source.width, source.height,\n {\n premultiplyAlpha: this.alphaMode === null || this.alphaMode === ALPHA_MODES.UNPACK\n ? 'premultiply' : 'none',\n }))\n .then((bitmap: ImageBitmap) =>\n {\n if (this.destroyed)\n {\n return Promise.reject();\n }\n this.bitmap = bitmap;\n this.update();\n this._process = null;\n\n return Promise.resolve(this);\n });\n\n return this._process;\n }\n\n /**\n * Upload the image resource to GPU.\n * @param renderer - Renderer to upload to\n * @param baseTexture - BaseTexture for this resource\n * @param glTexture - GLTexture to use\n * @returns {boolean} true is success\n */\n override upload(renderer: Renderer, baseTexture: BaseTexture, glTexture: GLTexture): boolean\n {\n if (typeof this.alphaMode === 'number')\n {\n // bitmap stores unpack premultiply flag, we dont have to notify texImage2D about it\n\n baseTexture.alphaMode = this.alphaMode;\n }\n\n if (!this.createBitmap)\n {\n return super.upload(renderer, baseTexture, glTexture);\n }\n if (!this.bitmap)\n {\n // yeah, ignore the output\n this.process();\n if (!this.bitmap)\n {\n return false;\n }\n }\n\n super.upload(renderer, baseTexture, glTexture, this.bitmap);\n\n if (!this.preserveBitmap)\n {\n // checks if there are other renderers that possibly need this bitmap\n\n let flag = true;\n\n const glTextures = baseTexture._glTextures;\n\n for (const key in glTextures)\n {\n const otherTex = glTextures[key];\n\n if (otherTex !== glTexture && otherTex.dirtyId !== baseTexture.dirtyId)\n {\n flag = false;\n break;\n }\n }\n\n if (flag)\n {\n if (this.bitmap.close)\n {\n this.bitmap.close();\n }\n\n this.bitmap = null;\n }\n }\n\n return true;\n }\n\n /** Destroys this resource. */\n override dispose(): void\n {\n (this.source as HTMLImageElement).onload = null;\n (this.source as HTMLImageElement).onerror = null;\n\n super.dispose();\n\n if (this.bitmap)\n {\n this.bitmap.close();\n this.bitmap = null;\n }\n this._process = null;\n this._load = null;\n }\n\n /**\n * Used to auto-detect the type of resource.\n * @param {*} source - The source object\n * @returns {boolean} `true` if current environment support HTMLImageElement, and source is string or HTMLImageElement\n */\n static override test(source: unknown): source is string | HTMLImageElement\n {\n return typeof HTMLImageElement !== 'undefined' && (typeof source === 'string' || source instanceof HTMLImageElement);\n }\n}\n"],"names":["BaseImageResource","settings","ALPHA_MODES"],"mappings":"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"} |