processImage( image, format, flipY ) {

    		const writer = this;
    		const cache = writer.cache;
    		const json = writer.json;
    		const options = writer.options;
    		const pending = writer.pending;

    		if ( ! cache.images.has( image ) ) cache.images.set( image, {} );

    		const cachedImages = cache.images.get( image );
    		const mimeType = format === RGBAFormat ? 'image/png' : 'image/jpeg';
    		const key = mimeType + ':flipY/' + flipY.toString();

    		if ( cachedImages[ key ] !== undefined ) return cachedImages[ key ];

    		if ( ! json.images ) json.images = [];

    		const imageDef = { mimeType: mimeType };

    		if ( options.embedImages ) {

    			const canvas = cachedCanvas = cachedCanvas || document.createElement( 'canvas' );

    			canvas.width = Math.min( image.width, options.maxTextureSize );
    			canvas.height = Math.min( image.height, options.maxTextureSize );

    			const ctx = canvas.getContext( '2d' );

    			if ( flipY === true ) {

    				ctx.translate( 0, canvas.height );
    				ctx.scale( 1, - 1 );

    			}

    			if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
    				( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
    				( typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas ) ||
    				( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {

    				ctx.drawImage( image, 0, 0, canvas.width, canvas.height );

    			} else {

    				if ( format !== RGBAFormat && format !== RGBFormat ) {

    					console.error( 'GLTFExporter: Only RGB and RGBA formats are supported.' );

    				}

    				if ( image.width > options.maxTextureSize || image.height > options.maxTextureSize ) {

    					console.warn( 'GLTFExporter: Image size is bigger than maxTextureSize', image );

    				}

    				const data = new Uint8ClampedArray( image.height * image.width * 4 );

    				if ( format === RGBAFormat ) {

    					for ( let i = 0; i < data.length; i += 4 ) {

    						data[ i + 0 ] = image.data[ i + 0 ];
    						data[ i + 1 ] = image.data[ i + 1 ];
    						data[ i + 2 ] = image.data[ i + 2 ];
    						data[ i + 3 ] = image.data[ i + 3 ];

    					}

    				} else {

    					for ( let i = 0, j = 0; i < data.length; i += 4, j += 3 ) {

    						data[ i + 0 ] = image.data[ j + 0 ];
    						data[ i + 1 ] = image.data[ j + 1 ];
    						data[ i + 2 ] = image.data[ j + 2 ];
    						data[ i + 3 ] = 255;

    					}

    				}

    				ctx.putImageData( new ImageData( data, image.width, image.height ), 0, 0 );

    			}

    			if ( options.binary === true ) {

    				pending.push( new Promise( function ( resolve ) {

    					canvas.toBlob( function ( blob ) {

    						writer.processBufferViewImage( blob ).then( function ( bufferViewIndex ) {

    							imageDef.bufferView = bufferViewIndex;
    							resolve();

    						} );

    					}, mimeType );

    				} ) );

    			} else {

    				imageDef.uri = canvas.toDataURL( mimeType );

    			}

    		} else {

    			imageDef.uri = image.src;

    		}

    		const index = json.images.push( imageDef ) - 1;
    		cachedImages[ key ] = index;
    		return index;

    	}
Process image
@param  {Image} image to process
@param  {Integer} format of the image (e.g. RGBFormat, RGBAFormat etc)
@param  {Boolean} flipY before writing out the image
@return {Integer}     Index of the processed texture in the "images" array