Fix for .jpg textures not working

This commit is contained in:
Lucas Dower 2023-03-01 20:35:32 +00:00
parent 3fe2e6a7c4
commit 2d639b043e
No known key found for this signature in database
GPG Key ID: B3EE6B8499593605
4 changed files with 33 additions and 21 deletions

View File

@ -4,7 +4,7 @@ import { Bounds } from './bounds';
import { RGBA, RGBAColours, RGBAUtil } from './colour';
import { degreesToRadians } from './math';
import { StatusHandler } from './status';
import { Texture, TextureConverter, TImageFiletype, TTransparencyOptions } from './texture';
import { Texture, TextureConverter, TImageFiletype, TImageRawWrap, TTransparencyOptions } from './texture';
import { Triangle, UVTriangle } from './triangle';
import { getRandomID, UV } from './util';
import { AppError, ASSERT } from './util/error_util';
@ -39,10 +39,7 @@ export type SolidMaterial = BaseMaterial & {
}
export type TexturedMaterial = BaseMaterial & {
type: MaterialType.textured,
diffuse?: {
raw: string,
filetype: TImageFiletype
},
diffuse?: TImageRawWrap,
interpolation: TTexelInterpolation,
extension: TTexelExtension,
transparency: TTransparencyOptions,

View File

@ -1,6 +1,8 @@
import * as jpeg from 'jpeg-js';
import { PNG } from 'pngjs';
import { RGBA, RGBAColours, RGBAUtil } from './colour';
import { AppConfig } from './config';
import { clamp } from './math';
import { TOptional, UV } from './util';
import { ASSERT } from './util/error_util';
@ -37,7 +39,7 @@ export enum EImageChannel {
}
/* eslint-enable */
export type TImageFiletype = 'png';
export type TImageFiletype = 'png' | 'jpg';
export type TImageRawWrap = {
raw: string,
@ -71,6 +73,15 @@ export class Texture {
return PNG.sync.read(Buffer.from(png, 'base64'));
}
}
if (params?.filetype === 'jpg') {
const jpg = params.raw.split(',')[1];
if (jpg !== undefined) {
return jpeg.decode(Buffer.from(jpg, 'base64'), {
maxMemoryUsageInMB: AppConfig.Get.MAXIMUM_IMAGE_MEM_ALLOC,
formatAsRGBA: true,
});
}
}
}
private _correctTexcoord(a: number) {

View File

@ -1,3 +1,4 @@
import { TImageFiletype, TImageRawWrap } from '../../texture';
import { getRandomID } from '../../util';
import { ASSERT } from '../../util/error_util';
import { UIUtil } from '../../util/ui_util';
@ -5,13 +6,13 @@ import { AppIcons } from '../icons';
import { ConfigUIElement } from './config_element';
import { ToolbarItemElement } from './toolbar_item';
export class ImageElement extends ConfigUIElement<Promise<string>, HTMLImageElement> {
export class ImageElement extends ConfigUIElement<Promise<TImageRawWrap>, HTMLImageElement> {
private _switchElement: ToolbarItemElement;
private _imageId: string;
public constructor(source?: string) {
super(Promise.resolve(source ?? ''));
public constructor(param?: TImageRawWrap) {
super(Promise.resolve(param ?? { raw: '', filetype: 'png' }));
this._switchElement = new ToolbarItemElement({ id: 'sw', iconSVG: AppIcons.UPLOAD })
.setSmall()
@ -51,12 +52,13 @@ export class ImageElement extends ConfigUIElement<Promise<string>, HTMLImageElem
if (files?.length === 1) {
const file = files.item(0);
ASSERT(file !== null);
ASSERT(file.type === 'image/jpeg' || file.type === 'image/png', 'Unexpected image type');
this._setValue(new Promise((res, rej) => {
const fileReader = new FileReader();
fileReader.onload = function () {
if (typeof fileReader.result === 'string') {
res(fileReader.result);
res({ filetype: file.type === 'image/jpeg' ? 'jpg' : 'png', raw: fileReader.result });
} else {
rej(Error());
}
@ -73,12 +75,12 @@ export class ImageElement extends ConfigUIElement<Promise<string>, HTMLImageElem
protected override _onValueChanged(): void {
const inputElement = UIUtil.getElementById(this._imageId) as HTMLImageElement;
this.getValue()
.then((source) => {
if (source === '') {
.then((res) => {
if (res.raw === '') {
throw Error();
}
this._switchElement.setActive(false);
inputElement.src = source;
inputElement.src = res.raw;
inputElement.style.display = 'unset';
})
.catch((err) => {

View File

@ -1,3 +1,5 @@
import path from 'path';
import { MaterialType, TexturedMaterial } from '../../mesh';
import { EImageChannel, TTransparencyTypes } from '../../texture';
import { getRandomID } from '../../util';
@ -45,7 +47,7 @@ export class TexturedMaterialElement extends ConfigUIElement<TexturedMaterial, H
.setSmall()
.setDefaultValue(material.transparency.type);
this._imageElement = new ImageElement(material.diffuse?.raw);
this._imageElement = new ImageElement(material.diffuse);
this._typeElement = new MaterialTypeElement(MaterialType.textured);
@ -60,7 +62,7 @@ export class TexturedMaterialElement extends ConfigUIElement<TexturedMaterial, H
.setSmall();
break;
case 'UseAlphaMap':
this._alphaMapElement = new ImageElement(material.transparency.alpha?.raw);
this._alphaMapElement = new ImageElement(material.transparency.alpha);
this._alphaChannelElement = new ComboBoxElement<EImageChannel>()
.addItem({ payload: EImageChannel.R, displayText: 'Red' })
.addItem({ payload: EImageChannel.G, displayText: 'Green' })
@ -85,10 +87,10 @@ export class TexturedMaterialElement extends ConfigUIElement<TexturedMaterial, H
this._imageElement.addValueChangedListener((newPath) => {
const material = this.getValue();
// TODO Unimplemented, promise should be resolved where it is used
newPath.then((source) => {
newPath.then((res) => {
material.diffuse = {
filetype: 'png', // TODO Unimplemented other filetypes
raw: source,
filetype: res.filetype, // TODO Unimplemented other filetypes
raw: res.raw,
};
});
});
@ -116,11 +118,11 @@ export class TexturedMaterialElement extends ConfigUIElement<TexturedMaterial, H
this._alphaMapElement?.addValueChangedListener((newPath) => {
const material = this.getValue();
// TODO Unimplemented, promise should be resolved where it is used
newPath.then((source) => {
newPath.then((res) => {
ASSERT(material.transparency.type === 'UseAlphaMap');
material.transparency.alpha = {
filetype: 'png', // TODO Unimplemented other filetypes
raw: source,
filetype: res.filetype, // TODO Unimplemented other filetypes
raw: res.raw,
};
});
});