public unsafe bool Bake(PipelineBakeContext context) { Console.WriteLine("Art.Bake: " + context.ContentPath); float umin = 0; float vmin = 0; float umax = 1; float vmax = 1; var path = context.Depends["source"]; var imageBuffer = ImageLoading.LoadImage(path); //TODO: we can only handle certain input formats here (no compressed formats) //but we can output any format (after we crop it) int width = imageBuffer.Width; int height = imageBuffer.Height; int physwidth = width; int physheight = height; int ox = 0, oy = 0; //NOTE: EVERYTHING BELOW IS EXPERIMENTAL. ITS A TOTAL MESS //TODO - apply art-specific operations (cropping, etc.) //TODO - make controllable //TODO - handle errors var conversionResult = imageBuffer.ConvertToAlphaProcessableFormat(false); bool doTrim = true; if (conversionResult.ConversionResult == ConversionResult.Error_InputFormatHasNoAlpha) { doTrim = false; } if (doTrim) { //accept the converted image imageBuffer = conversionResult.ResultImage; var alphaTrimResult = imageBuffer.AlphaTrim(); imageBuffer = alphaTrimResult.ResultImage; ox = alphaTrimResult.x; oy = alphaTrimResult.y; physwidth = alphaTrimResult.Width; physheight = alphaTrimResult.Height; } bool doPadPow2 = true; if (!imageBuffer.IsAlphaProcessableFormat()) { doPadPow2 = false; } if (doPadPow2) { int widthRound = PipelineMath.TextureUptoPow2(physwidth); int heightRound = PipelineMath.TextureUptoPow2(physheight); if (widthRound != physwidth || heightRound != physheight) { imageBuffer = imageBuffer.ExpandDownRight(widthRound, heightRound); } } var fmtAttribute = context.Attributes.FirstOrDefault(a => a is TextureFormatAttribute); if (fmtAttribute != null) { var toFormat = ((TextureFormatAttribute)fmtAttribute).Format; ImageConversionContext imageContext = new ImageConversionContext(); imageContext.From = imageBuffer; imageContext.NewAlpha = 0xFF; imageContext.ToFormat = toFormat; ImageLoading.Convert(imageContext); imageBuffer = imageContext.Output; } umax = (ox + physwidth) / imageBuffer.Width; vmax = (oy + physheight) / imageBuffer.Height; //the texture goes first... var textureBakingContext = new PipelineConnector_TextureBaking() { Image = imageBuffer, Writer = context.BakedWriter }; context.PipelineConnector.BakeTexture(textureBakingContext); //..then art-specific stuff context.BakedWriter.Write(width); context.BakedWriter.Write(height); context.BakedWriter.Write(ox); context.BakedWriter.Write(oy); context.BakedWriter.Write(umin); context.BakedWriter.Write(vmin); context.BakedWriter.Write(umax); context.BakedWriter.Write(vmax); return(true); }
public static void Convert(ImageConversionContext context) { if (context.From.Format == context.ToFormat) { return; } var ret = new ImageBuffer(); ret.Format = context.ToFormat; int width = ret.Width = context.From.Width; int height = ret.Height = context.From.Height; //reminder: we should intermediate-convert where reasonable to a standard format (i.e. RGBA8) so that we have fewer permutations to code //(needs to be done in a better way than this) //we can end up with permutations for the basic formats anyway. it will be more rare stuff that's obviously ridiculous to do without the intermediate stage if (context.From.Format == TextureFormat.BGRA8 && context.ToFormat == TextureFormat.RGB8) { var intermediateContext = new ImageConversionContext(); intermediateContext.From = context.From; intermediateContext.ToFormat = TextureFormat.RGBA8; Convert(intermediateContext); context.From = intermediateContext.Output; } var src = context.From.Data; if (context.From.Format == TextureFormat.R8 && context.ToFormat == TextureFormat.RGBA8) { context.Output = ret; byte[] dst = ret.Data = new byte[width * height * 4]; uint[] palette = context.From.Palette; for (int didx = 0, sidx = 0, y = 0; y < height; y++) { for (int x = 0; x < width; x++) { uint c = palette[src[sidx++]]; dst[didx++] = (byte)(c >> 0); dst[didx++] = (byte)(c >> 8); dst[didx++] = (byte)(c >> 16); dst[didx++] = (byte)(c >> 24); } } } if (context.From.Format == TextureFormat.BGRA8 && context.ToFormat == TextureFormat.RGBA8) { context.Output = ret; byte[] dst = ret.Data = new byte[width * height * 4]; for (int didx = 0, sidx = 0, y = 0; y < height; y++) { for (int x = 0; x < width; x++) { byte b = (byte)(src[sidx++]); byte g = (byte)(src[sidx++]); byte r = (byte)(src[sidx++]); byte a = (byte)(src[sidx++]); dst[didx++] = r; dst[didx++] = g; dst[didx++] = b; dst[didx++] = a; } } } if (context.From.Format == TextureFormat.BGR8 && context.ToFormat == TextureFormat.RGB8) { context.Output = ret; byte[] dst = ret.Data = new byte[width * height * 3]; for (int didx = 0, sidx = 0, y = 0; y < height; y++) { for (int x = 0; x < width; x++) { byte b = (byte)(src[sidx++]); byte g = (byte)(src[sidx++]); byte r = (byte)(src[sidx++]); dst[didx++] = r; dst[didx++] = g; dst[didx++] = b; } } } if (context.From.Format == TextureFormat.BGR8 && context.ToFormat == TextureFormat.RGBA8) { context.Output = ret; byte a = context.NewAlpha; byte[] dst = ret.Data = new byte[width * height * 4]; for (int didx = 0, sidx = 0, y = 0; y < height; y++) { for (int x = 0; x < width; x++) { byte b = (byte)(src[sidx++]); byte g = (byte)(src[sidx++]); byte r = (byte)(src[sidx++]); dst[didx++] = r; dst[didx++] = g; dst[didx++] = b; dst[didx++] = a; } } } if (context.From.Format == TextureFormat.RGBA8 && context.ToFormat == TextureFormat.RGB8) { context.Output = ret; byte[] dst = ret.Data = new byte[width * height * 3]; for (int didx = 0, sidx = 0, y = 0; y < height; y++) { for (int x = 0; x < width; x++) { byte r = (byte)(src[sidx++]); byte g = (byte)(src[sidx++]); byte b = (byte)(src[sidx++]); sidx++; dst[didx++] = r; dst[didx++] = g; dst[didx++] = b; } } } } //Convert()