<commit_before>// image/loader - image loading frontend
// Part of Stardazed
// (c) 2015-2017 by <NAME> - @zenmumbler
// https://github.com/stardazed/stardazed

namespace sd.image {

	export function loadImage(url: URL, extension?: string): Promise<PixelDataProvider>;
	export function loadImage(buffer: ArrayBufferView, extension: string): Promise<PixelDataProvider>;
	export function loadImage(source: URL | ArrayBufferView, extension?: string): Promise<PixelDataProvider> {
		return (source instanceof URL) ? loadImageFromURL(source) : loadImageFromBufferView(source, extension!);
	}

	// ----

	let nativeTGASupport: boolean | null = null;

	function checkNativeTGASupport(): Promise<boolean> {
		if (nativeTGASupport === null) {
			return new Promise((resolve, _) => {
				const img = new Image();
				img.onload = () => { nativeTGASupport = true; resolve(true); };
				img.onerror = () => { nativeTGASupport = false; resolve(false); };
				img.src = "data:image/tga;base64,AAACAAAAAAAAAAAAAQABABgA////";
			});
		}

		return Promise.resolve(nativeTGASupport);
	}

	function loadImageFromURL(url: URL, extension?: string): Promise<PixelDataProvider> {
		if (! extension) {
			extension = io.fileExtensionOfURL(url);
		}
		if (! extension) {
			return Promise.reject(`Cannot determine file type of '${url}'`);
		}

		if (extension === "dds") {
			return io.loadFile<ArrayBuffer>(url.href, { responseType: io.FileLoadType.ArrayBuffer })
				.then(buf => {
					return new DDSDataProvider(new Uint8ClampedArray(buf));
				});
		}

		if (extension === "tga") {
			return checkNativeTGASupport().then(supported => {
				if (supported) {
					return loadBuiltInImageFromURL(url);
				}
				return io.loadFile<ArrayBuffer>(url.href, { responseType: io.FileLoadType.ArrayBuffer })
					.then<PixelDataProvider>(buf => {
						return new TGADataProvider(new Uint8ClampedArray(buf));
					});
			});
		}

		return loadBuiltInImageFromURL(url);
	}


	function loadImageFromBufferView(view: ArrayBufferView, extension: string): Promise<PixelDataProvider> {
		if (extension === "tga") {
			return checkNativeTGASupport().then(supported => {
				if (supported) {
					return loadBuiltInImageFromBufferView(view, extension);
				}
				else {
					return new TGADataProvider(view);
				}
			});
		}

		if (extension === "dds") {
			return Promise.resolve(new DDSDataProvider(view));
		}

		return loadBuiltInImageFromBufferView(view, extension);
	}


	//  ___      _ _ _       _
	// | _ )_  _(_) | |_ ___(_)_ _
	// | _ \ || | | |  _|___| | ' \
	// |___/\_,_|_|_|\__|   |_|_||_|
	//

	class HTMLImageDataProvider implements PixelDataProvider {
		readonly colourSpace: ColourSpace;
		readonly pixelFormat: PixelFormat;
		readonly dim: PixelDimensions;
		readonly mipMapCount = 1;

		constructor(private image_: HTMLImageElement, extension?: string) {
			if (! extension) {
				const realSrc = image_.currentSrc || image_.src;
				extension = io.fileExtensionOfURL(realSrc);
			}

			this.colourSpace = (["jpg", "png"].indexOf(extension) > -1) ? ColourSpace.sRGB : ColourSpace.Linear;
			this.pixelFormat = (this.colourSpace === ColourSpace.sRGB) ? PixelFormat.SRGB8_Alpha8 : PixelFormat.RGBA8;
			this.dim = makePixelDimensions(image_.width, image_.height);
		}

		pixelBufferForLevel(level: number): PixelBuffer | undefined {
			if (level !== 0) {
				return undefined;
			}

			return {
				colourSpace: this.colourSpace,
				pixelFormat: this.pixelFormat,
				dim: { ...this.dim },
				data: this.image_
			};
		}
	}

	function loadBuiltInImageFromURL(url: URL) {
		return new Promise<PixelDataProvider>((resolve, reject) => {
			const image = new Image();
			image.onload = () => {
				resolve(new HTMLImageDataProvider(image));
			};
			image.onerror = () => {
				reject(`${url.href} doesn't exist or is not supported`);
			};

			// When requesting cross-domain media, always try the CORS route
			// GL will not allow tainted data to be loaded so if it fails, we can't use the image anyway
			if (url.origin !== location.origin) {
				image.crossOrigin = "anonymous";
			}
			image.src = url.href;
		});
	}


	function loadBuiltInImageFromBufferView(view: ArrayBufferView, extension: string) {
		return new Promise<PixelDataProvider>((resolve, reject) => {
			const blob = new Blob([view], { type: extension });

			io.BlobReader.readAsDataURL(blob).then(
				dataURL => {
					const image = new Image();
					image.onload = () => {
						resolve(new HTMLImageDataProvider(image));
					};
					image.onerror = () => {<commit_msg>ref(asset): make ColourSpace explicit when loading images<commit_after>// image/loader - image loading frontend
// Part of Stardazed
// (c) 2015-2017 by <NAME> - @zenmumbler
// https://github.com/stardazed/stardazed

namespace sd.image {

	export function loadImage(url: URL, colourSpace: ColourSpace, extension?: string): Promise<PixelDataProvider>;
	export function loadImage(buffer: ArrayBufferView, colourSpace: ColourSpace, extension: string): Promise<PixelDataProvider>;
	export function loadImage(source: URL | ArrayBufferView, colourSpace: ColourSpace, extension?: string): Promise<PixelDataProvider> {
		return (source instanceof URL) ? loadImageFromURL(source, colourSpace, extension) : loadImageFromBufferView(source, colourSpace, extension!);
	}

	// ----

	let nativeTGASupport: boolean | null = null;

	function checkNativeTGASupport(): Promise<boolean> {
		if (nativeTGASupport === null) {
			return new Promise((resolve, _) => {
				const img = new Image();
				img.onload = () => { nativeTGASupport = true; resolve(true); };
				img.onerror = () => { nativeTGASupport = false; resolve(false); };
				img.src = "data:image/tga;base64,AAACAAAAAAAAAAAAAQABABgA////";
			});
		}

		return Promise.resolve(nativeTGASupport);
	}

	function loadImageFromURL(url: URL, colourSpace: ColourSpace, extension?: string): Promise<PixelDataProvider> {
		if (! extension) {
			extension = io.fileExtensionOfURL(url);
		}
		if (! extension) {
			return Promise.reject(`Cannot determine file type of '${url}'`);
		}

		if (extension === "dds") {
			return io.loadFile<ArrayBuffer>(url.href, { responseType: io.FileLoadType.ArrayBuffer })
				.then(buf => {
					return new DDSDataProvider(new Uint8ClampedArray(buf));
				});
		}

		if (extension === "tga") {
			return checkNativeTGASupport().then(supported => {
				if (supported) {
					return loadBuiltInImageFromURL(url, colourSpace);
				}
				return io.loadFile<ArrayBuffer>(url.href, { responseType: io.FileLoadType.ArrayBuffer })
					.then<PixelDataProvider>(buf => {
						return new TGADataProvider(new Uint8ClampedArray(buf));
					});
			});
		}

		return loadBuiltInImageFromURL(url, colourSpace);
	}


	function loadImageFromBufferView(view: ArrayBufferView, colourSpace: ColourSpace, extension: string): Promise<PixelDataProvider> {
		if (extension === "tga") {
			return checkNativeTGASupport().then(supported => {
				if (supported) {
					return loadBuiltInImageFromBufferView(view, colourSpace, extension);
				}
				else {
					return new TGADataProvider(view);
				}
			});
		}

		if (extension === "dds") {
			return Promise.resolve(new DDSDataProvider(view));
		}

		return loadBuiltInImageFromBufferView(view, colourSpace, extension);
	}


	//  ___      _ _ _       _
	// | _ )_  _(_) | |_ ___(_)_ _
	// | _ \ || | | |  _|___| | ' \
	// |___/\_,_|_|_|\__|   |_|_||_|
	//

	class HTMLImageDataProvider implements PixelDataProvider {
		readonly colourSpace: ColourSpace;
		readonly pixelFormat: PixelFormat;
		readonly dim: PixelDimensions;
		readonly mipMapCount = 1;

		constructor(private image_: HTMLImageElement, colourSpace: ColourSpace, extension?: string) {
			if (! extension) {
				const realSrc = image_.currentSrc || image_.src;
				extension = io.fileExtensionOfURL(realSrc);
			}

			this.colourSpace = colourSpace;
			this.pixelFormat = (this.colourSpace === ColourSpace.sRGB) ? PixelFormat.SRGB8_Alpha8 : PixelFormat.RGBA8;
			this.dim = makePixelDimensions(image_.width, image_.height);
		}

		pixelBufferForLevel(level: number): PixelBuffer | undefined {
			if (level !== 0) {
				return undefined;
			}

			return {
				colourSpace: this.colourSpace,
				pixelFormat: this.pixelFormat,
				dim: { ...this.dim },
				data: this.image_
			};
		}
	}

	function loadBuiltInImageFromURL(url: URL, colourSpace: ColourSpace) {
		return new Promise<PixelDataProvider>((resolve, reject) => {
			const image = new Image();
			image.onload = () => {
				resolve(new HTMLImageDataProvider(image, colourSpace));
			};
			image.onerror = () => {
				reject(`${url.href} doesn't exist or is not supported`);
			};

			// When requesting cross-domain media, always try the CORS route
			// GL will not allow tainted data to be loaded so if it fails, we can't use the image anyway
			if (url.origin !== location.origin) {
				image.crossOrigin = "anonymous";
			}
			image.src = url.href;
		});
	}


	function loadBuiltInImageFromBufferView(view: ArrayBufferView, colourSpace: ColourSpace, extension: string) {
		return new Promise<PixelDataProvider>((resolve, reject) => {
			const blob = new Blob([view], { type: extension });

			io.BlobReader.readAsDataURL(blob).then(
				dataURL => {
					const image = new Image();
					image.onload = () => {
						resolve(new HTMLImageDataProvider(image, colourSpace));
					};
					image.onerror = () => {
{'fraction_non_alphanumeric': 0.13692768506632436, 'fraction_numerical': 0.003744116388532306, 'mean_word_length': 3.821557503867973, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 56, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4077513', 'n_tokens_mistral': 3422, 'n_tokens_neox': 2881, 'n_words': 623}