public static void TexImage2D(Stream data, out int width, out int height) { data.Position = 0; var nsData = NSData.FromStream(data); var image = UIImage.LoadFromData(nsData); if (image == null) { throw new Exception("could not load image data"); } width = (int)image.CGImage.Width; height = (int)image.CGImage.Height; var colorSpace = CGColorSpace.CreateDeviceRGB(); var imageData = new byte[height * width * 4]; var context = new CGBitmapContext(imageData, width, height, 8, 4 * width, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); colorSpace.Dispose(); context.ClearRect(new CGRect(0, 0, width, height)); context.DrawImage(new CGRect(0, 0, width, height), image.CGImage); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, imageData); context.Dispose(); }
void LoadBitmapData (int texId) { NSData texData = NSData.FromFile (NSBundle.MainBundle.PathForResource ("texture1", "png")); UIImage image = UIImage.LoadFromData (texData); if (image == null) return; int width = image.CGImage.Width; int height = image.CGImage.Height; CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB (); byte[] imageData = new byte[height * width * 4]; CGContext context = new CGBitmapContext (imageData, width, height, 8, 4 * width, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); context.TranslateCTM (0, height); context.ScaleCTM (1, -1); colorSpace.Dispose (); context.ClearRect (new RectangleF (0, 0, width, height)); context.DrawImage (new RectangleF (0, 0, width, height), image.CGImage); GL.TexImage2D (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, imageData); context.Dispose (); }
internal static CGBitmapContext CreateBitmap(int width, int height) //, PixelFormat format) { int bitsPerComponent, bytesPerRow; CGColorSpace colorSpace; CGBitmapFlags bitmapInfo; // bool premultiplied = false; int bitsPerPixel = 0; // Don't forget to set the Image width and height for size. imageSize.Width = width; imageSize.Height = height; colorSpace = CGColorSpace.CreateDeviceRGB(); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.PremultipliedLast; bytesPerRow = width * bitsPerPixel / bitsPerComponent; int size = bytesPerRow * height; bitmapBlock = Marshal.AllocHGlobal(size); var bitmapContext = new CGBitmapContext(bitmapBlock, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo); // This works for now but we need to look into initializing the memory area itself bitmapContext.ClearRect(new RectangleF(0, 0, width, height)); return(bitmapContext); }
private void LoadTextureFromImage(Texture t, CGImage image) { IntPtr pixelData = IntPtr.Zero; CGBitmapContext bitmap = null; try { pixelData = Marshal.AllocHGlobal((int)image.Width * (int)image.Height * 4); bitmap = new CGBitmapContext(pixelData, image.Width, image.Height, 8, 4 * image.Width, CGColorSpace.CreateDeviceRGB(), CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); bitmap.ClearRect(new CGRect(0, 0, image.Width, image.Height)); bitmap.DrawImage(new CGRect(0, 0, image.Width, image.Height), image); LoadTextureInternal(t, bitmap); } catch (Exception) { t.Failed = true; return; } finally { if (bitmap != null) { bitmap.Dispose(); } if (pixelData != IntPtr.Zero) { Marshal.FreeHGlobal(pixelData); } } }
void LoadBitmapData(int texId) { NSData texData = NSData.FromFile(NSBundle.MainBundle.PathForResource("texture1", "png")); UIImage image = UIImage.LoadFromData(texData); if (image == null) { return; } int width = image.CGImage.Width; int height = image.CGImage.Height; CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB(); byte[] imageData = new byte[height * width * 4]; CGContext context = new CGBitmapContext(imageData, width, height, 8, 4 * width, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); context.TranslateCTM(0, height); context.ScaleCTM(1, -1); colorSpace.Dispose(); context.ClearRect(new RectangleF(0, 0, width, height)); context.DrawImage(new RectangleF(0, 0, width, height), image.CGImage); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, imageData); context.Dispose(); }
//https://github.com/xamarin/mobile-samples/blob/master/TexturedCubeES30/TexturedCubeiOS/EAGLView.cs public void LoadTexture(int?textureToBind) { if (textureToBind != null) { _graphics.BindTexture2D(textureToBind.Value); } var width = _cgImage.Width; var height = _cgImage.Height; using (CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB()) { byte[] imageData = new byte[height * width * 4]; CGContext context = new CGBitmapContext(imageData, width, height, 8, 4 * width, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); using (context) { context.TranslateCTM(0, height); context.ScaleCTM(1, -1); context.ClearRect(new CGRect(0, 0, width, height)); context.DrawImage(new CGRect(0, 0, width, height), _cgImage); unsafe { fixed(byte *p = imageData) { IntPtr ptr = (IntPtr)p; _graphics.TexImage2D(Width, Height, ptr); } } } } }
/// <summary> /// Initializes a new instance of the <see cref="iOSSurfaceSource"/> class. /// </summary> /// <param name="stream">The <see cref="Stream"/> that contains the surface data.</param> public iOSSurfaceSource(Stream stream) { Contract.Require(stream, nameof(stream)); using (var data = NSData.FromStream(stream)) { using (var img = UIImage.LoadFromData(data)) { this.width = (Int32)img.Size.Width; this.height = (Int32)img.Size.Height; this.stride = (Int32)img.CGImage.BytesPerRow; this.bmpData = Marshal.AllocHGlobal(stride * height); using (var colorSpace = CGColorSpace.CreateDeviceRGB()) { using (var bmp = new CGBitmapContext(bmpData, width, height, 8, stride, colorSpace, CGImageAlphaInfo.PremultipliedLast)) { bmp.ClearRect(new CGRect(0, 0, width, height)); bmp.DrawImage(new CGRect(0, 0, width, height), img.CGImage); } } } } ReversePremultiplication(); }
protected void LoadTexture(UIImage inImage) { var pixelsWide = inImage.CGImage.Width; var pixelsHigh = inImage.CGImage.Height; var bitmapBytesPerRow = pixelsWide * 4; var bitmapByteCount = bitmapBytesPerRow * pixelsHigh; var bitmapData = Marshal.AllocHGlobal(bitmapByteCount); if (bitmapData == IntPtr.Zero) { throw new Exception("Memory not allocated."); } var context = new CGBitmapContext(bitmapData, pixelsWide, pixelsHigh, 8, bitmapBytesPerRow, inImage.CGImage.ColorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); if (context == null) { throw new Exception("Context not created"); } var imageSize = inImage.Size; var rect = new RectangleF(0.0f, 0.0f, imageSize.Width, imageSize.Height); context.ClearRect(rect); context.DrawImage(rect, inImage.CGImage); var data = context.Data; GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)imageSize.Width, (int)imageSize.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, data); Marshal.FreeHGlobal(data); }
public Bitmap(int width, int height, PixelFormat format) { int bitsPerComponent, bytesPerRow; CGColorSpace colorSpace; CGBitmapFlags bitmapInfo; bool premultiplied = false; int bitsPerPixel = 0; // Don't forget to set the Image width and height for size. imageSize.Width = width; imageSize.Height = height; switch (format) { case PixelFormat.Format32bppPArgb: premultiplied = true; colorSpace = CGColorSpace.CreateDeviceRGB(); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.PremultipliedFirst; break; case PixelFormat.Format32bppArgb: colorSpace = CGColorSpace.CreateDeviceRGB(); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.PremultipliedFirst; break; case PixelFormat.Format32bppRgb: colorSpace = CGColorSpace.CreateDeviceRGB(); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.None; break; default: throw new Exception("Format not supported: " + format); } bytesPerRow = width * bitsPerPixel / bitsPerComponent; int size = bytesPerRow * height; bitmapBlock = Marshal.AllocHGlobal(size); var bitmap = new CGBitmapContext(bitmapBlock, width, height, bitsPerComponent, bytesPerRow, colorSpace, CGImageAlphaInfo.PremultipliedLast); // This works for now but we need to look into initializing the memory area itself // TODO: Look at what we should do if the image does not have alpha channel bitmap.ClearRect(new RectangleF(0, 0, width, height)); var provider = new CGDataProvider(bitmapBlock, size, true); NativeCGImage = new CGImage(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpace, bitmapInfo, provider, null, false, CGColorRenderingIntent.Default); }
// CGImage public static void ToSKPixmap(this CGImage cgImage, SKPixmap pixmap) { using (var colorSpace = CGColorSpace.CreateDeviceRGB()) using (var context = new CGBitmapContext(pixmap.GetPixels(), pixmap.Width, pixmap.Height, 8, pixmap.RowBytes, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big)) { CGRect rect = new CGRect(0, 0, cgImage.Width, cgImage.Height); context.ClearRect(rect); context.DrawImage(rect, cgImage); } }
private Texture(String filename) { #if __ANDROID__ AssetManager assets = GameActivity.Instance.Assets; Bitmap bitmap = null; using (Stream stream = assets.Open(filename)) { bitmap = BitmapFactory.DecodeStream(stream); Width = bitmap.Width; Height = bitmap.Height; } GL.GenTextures(1, out _GLID); GL.BindTexture(All.Texture2D, _GLID); GL.TexParameter(All.Texture2D, All.TextureWrapS, (Int32)All.Repeat); GL.TexParameter(All.Texture2D, All.TextureWrapT, (Int32)All.Repeat); GL.TexParameter(All.Texture2D, All.TextureMinFilter, (Int32)All.Linear); GL.TexParameter(All.Texture2D, All.TextureMagFilter, (Int32)All.Linear); GLUtils.TexImage2D((Int32)All.Texture2D, 0, bitmap, 0); GL.GenerateMipmap(All.Texture2D); GL.BindTexture(All.Texture2D, 0); bitmap.Recycle(); #elif __IOS__ UIImage image = UIImage.FromFile(filename); nint cgWidth = image.CGImage.Width; nint cgHeight = image.CGImage.Height; Width = (Int32)cgWidth; Height = (Int32)cgHeight; CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB(); Byte[] data = new Byte[Width * Height * 4]; CGContext context = new CGBitmapContext(data, cgWidth, cgHeight, 8, 4 * Width, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrderDefault); colorSpace.Dispose(); context.ClearRect(new CGRect(0, 0, cgWidth, cgHeight)); context.DrawImage(new CGRect(0, 0, cgWidth, cgHeight), image.CGImage); GL.GenTextures(1, out _GLID); GL.BindTexture(TextureTarget.Texture2D, _GLID); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (Int32)All.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (Int32)All.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (Int32)TextureMinFilter.LinearMipmapLinear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (Int32)TextureMagFilter.Linear); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, data); context.Dispose(); GL.GenerateMipmap(TextureTarget.Texture2D); GL.BindTexture(TextureTarget.Texture2D, 0); #endif LoadedTextures.Add(filename, this); _Filename = filename; }
private bool createFontTexture(string file) { GL.Enable(EnableCap.Blend); GL.Enable(EnableCap.Texture2D); GL.GenTextures(1, out texture); GL.BindTexture(TextureTarget.Texture2D, texture); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge); string extension = Path.GetExtension(file); string fileName = Path.GetFileNameWithoutExtension(file); string directoryName = Path.GetDirectoryName(file); string path = NSBundle.MainBundle.PathForResource(fileName, extension, directoryName); NSData texData = NSData.FromFile(path); UIImage image = UIImage.LoadFromData(texData); if (image == null) { return(false); } textureWidth = image.CGImage.Width; textureHeight = image.CGImage.Height; GL.Uniform2(texsizeUniform, (float)textureWidth, (float)textureHeight); byte [] imageData = new byte[textureWidth * textureHeight * 1]; using (CGColorSpace colorSpace = CGColorSpace.CreateDeviceGray()) using (CGContext context = new CGBitmapContext(imageData, textureWidth, textureHeight, 8, 1 * textureWidth, colorSpace, CGImageAlphaInfo.None)) { context.TranslateCTM(0, textureHeight); context.ScaleCTM(1, -1); context.ClearRect(new CGRect(0, 0, textureWidth, textureHeight)); context.DrawImage(new CGRect(0, 0, textureWidth, textureHeight), image.CGImage); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); GL.PixelStore(PixelStoreParameter.PackAlignment, 1); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Luminance, (int)textureWidth, (int)textureHeight, 0, PixelFormat.Luminance, PixelType.UnsignedByte, imageData); } return(true); }
public GLTexture(string inFilename) { GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.Blend); filename = inFilename; GL.Hint(HintTarget.GenerateMipmapHint, HintMode.Nicest); GL.GenTextures(1, out texture); GL.BindTexture(TextureTarget.Texture2D, texture); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest); //TODO Remove the Substring method if you don't support iOS versions prior to iOS 6. string extension = Path.GetExtension(filename).Substring(1); string baseFilename = Path.GetFileNameWithoutExtension(filename); string path = NSBundle.MainBundle.PathForResource(baseFilename, extension); NSData texData = NSData.FromFile(path); UIImage image = UIImage.LoadFromData(texData); if (image == null) { return; } nint width = image.CGImage.Width; nint height = image.CGImage.Height; CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB(); byte [] imageData = new byte[height * width * 4]; CGContext context = new CGBitmapContext(imageData, width, height, 8, 4 * width, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); context.TranslateCTM(0, height); context.ScaleCTM(1, -1); colorSpace.Dispose(); context.ClearRect(new CGRect(0, 0, width, height)); context.DrawImage(new CGRect(0, 0, width, height), image.CGImage); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)width, (int)height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, imageData); context.Dispose(); }
/// <summary> /// Constructs a new instance. /// </summary> /// <param name="width">The width of the backing store in pixels.</param> /// <param name="height">The height of the backing store in pixels.</param> /// <param name="renderer">GWEN renderer.</param> public TextRenderer(int width, int height, OpenTK renderer) { if (width <= 0) throw new ArgumentOutOfRangeException("width"); if (height <= 0) throw new ArgumentOutOfRangeException("height"); m_PixelData = Marshal.AllocHGlobal(width * height * 4); m_Bitmap = new CGBitmapContext(m_PixelData, (nint)width, (nint)height, 8, 4 * (nint)width, CGColorSpace.CreateDeviceRGB(), CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); m_Bitmap.SetTextDrawingMode(CGTextDrawingMode.Fill); m_Bitmap.SetFillColor(new CGColor(1.0f, 1.0f, 1.0f, 1.0f)); m_Bitmap.ClearRect(new CGRect(0, 0, (nint)width, (nint)height)); m_Texture = new Texture(renderer) { Width = width, Height = height }; }
public static byte[] LoadImage(string fileName, bool premultiplied, out int width, out int height) { premultiplied = false; UIImage image = UIImage.FromBundle(fileName); width = (int)image.CGImage.Width; height = (int)image.CGImage.Height; byte[] bitmap = new byte[width * height * 4]; using (var colorSpace = CGColorSpace.CreateDeviceRGB()) { IntPtr rawData = Marshal.AllocHGlobal(width * height * 4); using (var cgContext = new CGBitmapContext(rawData, width, height, 8, 4 * width, colorSpace, CGBitmapFlags.ByteOrder32Big | CGBitmapFlags.PremultipliedLast)) { // clear the context (avoid garbage) cgContext.ClearRect(new CGRect(0, 0, width, height)); cgContext.DrawImage(new CGRect(0, 0, width, height), image.CGImage); Marshal.Copy(rawData, bitmap, 0, bitmap.Length); } Marshal.FreeHGlobal(rawData); } if (!premultiplied) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int position = (y * width * 4) + (x * 4); byte r = bitmap[position]; byte g = bitmap[position + 1]; byte b = bitmap[position + 2]; byte a = bitmap[position + 3]; bitmap[position] = (byte)(r * (255f / a)); bitmap[position + 1] = (byte)(g * (255f / a)); bitmap[position + 2] = (byte)(b * (255f / a)); } } } return(bitmap); }
public GLTexture (string inFilename) { GL.Enable (EnableCap.Texture2D); GL.Enable (EnableCap.Blend); filename = inFilename; GL.Hint (HintTarget.GenerateMipmapHint, HintMode.Nicest); GL.GenTextures (1, out texture); GL.BindTexture (TextureTarget.Texture2D, texture); GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) All.Repeat); GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) All.Repeat); GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) All.Linear); GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) All.Linear); GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) All.Nearest); GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) All.Nearest); //TODO Remove the Substring method if you don't support iOS versions prior to iOS 6. string extension = Path.GetExtension (filename).Substring(1); string baseFilename = Path.GetFileNameWithoutExtension (filename); string path = NSBundle.MainBundle.PathForResource (baseFilename, extension); NSData texData = NSData.FromFile (path); UIImage image = UIImage.LoadFromData (texData); if (image == null) return; nint width = image.CGImage.Width; nint height = image.CGImage.Height; CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB (); byte [] imageData = new byte[height * width * 4]; CGContext context = new CGBitmapContext (imageData, width, height, 8, 4 * width, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); context.TranslateCTM (0, height); context.ScaleCTM (1, -1); colorSpace.Dispose (); context.ClearRect (new CGRect (0, 0, width, height)); context.DrawImage (new CGRect (0, 0, width, height), image.CGImage); GL.TexImage2D (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)width, (int)height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, imageData); context.Dispose (); }
public void Draw(SkiaSharp.SKCanvas canvas) { var info = this.info; var viewBounds = Bounds; var scale = (float)UIKit.UIScreen.MainScreen.Scale; using (var image = new SkiaSharp.SKBitmap(info, info.RowBytes)) { using (var pixels = image.PeekPixels()) using (var colorSpace = CGColorSpace.CreateDeviceRGB()) using (var ctx = new CGBitmapContext(pixels.GetPixels(), info.Width, info.Height, 8, info.RowBytes, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big)) { ctx.ClearRect(viewBounds); ctx.TranslateCTM(0, info.Height); ctx.ScaleCTM(scale, -scale); Layer.RenderInContext(ctx); } canvas.DrawBitmap(image, SkiaSharp.SKPoint.Empty); } }
public static void TexImage2D(Stream data, out int width, out int height) { data.Position = 0; var nsData = NSData.FromStream(data); var image = UIImage.LoadFromData(nsData); if (image == null) throw new Exception ("could not load image data"); width = (int)image.CGImage.Width; height = (int)image.CGImage.Height; var colorSpace = CGColorSpace.CreateDeviceRGB(); var imageData = new byte[height * width * 4]; var context = new CGBitmapContext (imageData, width, height, 8, 4 * width, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); colorSpace.Dispose(); context.ClearRect(new CGRect(0, 0, width, height)); context.DrawImage(new CGRect(0, 0, width, height), image.CGImage); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, imageData); context.Dispose(); }
public ESTexture2D(UIImage uiImage, All filter) { CGImage image = uiImage.CGImage; if (uiImage == null) { throw new ArgumentNullException("uiImage"); } // TODO: could use this to implement lower-bandwidth textures //bool hasAlpha = (image.AlphaInfo == CGImageAlphaInfo.First || image.AlphaInfo == CGImageAlphaInfo.Last // || image.AlphaInfo == CGImageAlphaInfo.PremultipliedFirst || image.AlphaInfo == CGImageAlphaInfo.PremultipliedLast); // Image dimentions: logicalSize = new Point((int)uiImage.Size.Width, (int)uiImage.Size.Height); pixelWidth = uiImage.CGImage.Width; pixelHeight = uiImage.CGImage.Height; // Round up the target texture width and height to powers of two: potWidth = pixelWidth; potHeight = pixelHeight; if ((potWidth & (potWidth - 1)) != 0) { int w = 1; while (w < potWidth) { w *= 2; } potWidth = w; } if ((potHeight & (potHeight - 1)) != 0) { int h = 1; while (h < potHeight) { h *= 2; } potHeight = h; } // Scale down textures that are too large... CGAffineTransform transform = CGAffineTransform.MakeIdentity(); while ((potWidth > 1024) || (potHeight > 1024)) { potWidth /= 2; // Note: no precision loss - it's a power of two potHeight /= 2; pixelWidth /= 2; // Note: precision loss - assume possibility of dropping a pixel at each step is ok pixelHeight /= 2; transform.Multiply(CGAffineTransform.MakeScale(0.5f, 0.5f)); } RecalculateRatio(); lock (textureLoadBufferLockObject) { CreateTextureLoadBuffer(); unsafe { fixed(byte *data = textureLoadBuffer) { var colorSpace = CGColorSpace.CreateDeviceRGB(); var context = new CGBitmapContext(new IntPtr(data), potWidth, potHeight, 8, 4 * potWidth, colorSpace, CGImageAlphaInfo.PremultipliedLast); context.ClearRect(new RectangleF(0, 0, potWidth, potHeight)); context.TranslateCTM(0, potHeight - pixelHeight); // TODO: this does not play nice with the precision-loss above (keeping half-pixel to the edge) if (!transform.IsIdentity) { context.ConcatCTM(transform); } context.DrawImage(new RectangleF(0, 0, image.Width, image.Height), image); SetupTexture(new IntPtr(data), filter); context.Dispose(); colorSpace.Dispose(); } } } }
// see http://deathbyalgorithm.blogspot.fr/2013/05/opentk-textures.html public static int LoadTexture(string name, int quality, bool repeat, bool flip_y) { string prefix; #if __IOS__ prefix = "OpenGLDemo.iOS."; #endif #if __ANDROID__ prefix = "OpenGLDemo.Droid."; #endif var assembly = typeof(App2).GetTypeInfo().Assembly; // foreach (var res in assembly.GetManifestResourceNames()) // System.Diagnostics.Debug.WriteLine("found resource: " + res); Stream stream = assembly.GetManifestResourceStream(prefix + name + ".png"); byte[] imageData; using (MemoryStream ms = new MemoryStream()) { stream.CopyTo(ms); imageData = ms.ToArray(); } #if __ANDROID__ Bitmap b = BitmapFactory.DecodeByteArray(imageData, 0, imageData.Length); #elif __IOS__ UIImage image = ImageFromByteArray(imageData); int width = (int)image.CGImage.Width; int height = (int)image.CGImage.Height; CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB(); byte[] imageData2 = new byte[height * width * 4]; CGContext context = new CGBitmapContext(imageData2, width, height, 8, 4 * width, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); colorSpace.Dispose(); context.ClearRect(new RectangleF(0, 0, width, height)); context.DrawImage(new RectangleF(0, 0, width, height), image.CGImage); #endif int [] textures = new int[1]; //Generate a new texture target in gl GL.GenTextures(1, textures); //Will bind the texture newly/empty created with GL.GenTexture //All gl texture methods targeting Texture2D will relate to this texture GL.BindTexture(TextureTarget.Texture2D, textures[0]); //The reason why your texture will show up glColor without setting these parameters is actually //TextureMinFilters fault as its default is NearestMipmapLinear but we have not established mipmapping //We are only using one texture at the moment since mipmapping is a collection of textures pre filtered //I'm assuming it stops after not having a collection to check. switch (quality) { case 1: //High quality GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); break; //case 0: default: //Low quality GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Nearest); break; } if (repeat) { //This will repeat the texture past its bounds set by TexImage2D GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Repeat); } else { //This will clamp the texture to the edge, so manipulation will result in skewing //It can also be useful for getting rid of repeating texture bits at the borders GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge); } #if __ANDROID__ GLUtils.TexImage2D((int)All.Texture2D, 0, b, 0); b.Recycle(); #elif __IOS__ GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, imageData2); #endif GL.BindTexture(TextureTarget.Texture2D, 0); return(textures[0]); }
private void InitWithCGImage(CGImage image) { int width, height; CGBitmapContext bitmap = null; bool hasAlpha; CGImageAlphaInfo alphaInfo; CGColorSpace colorSpace; int bitsPerComponent, bytesPerRow; CGBitmapFlags bitmapInfo; int bitsPerPixel = 0; if (image == null) { throw new ArgumentException(" image is invalid! "); } alphaInfo = image.AlphaInfo; hasAlpha = ((alphaInfo == CGImageAlphaInfo.PremultipliedLast) || (alphaInfo == CGImageAlphaInfo.PremultipliedFirst) || (alphaInfo == CGImageAlphaInfo.Last) || (alphaInfo == CGImageAlphaInfo.First) ? true : false); imageSize.Width = (int)image.Width; imageSize.Height = (int)image.Height; width = (int)image.Width; height = (int)image.Height; // Not sure yet if we need to keep the original image information // before we change it internally. TODO look at what windows does // and follow that. bitmapInfo = image.BitmapInfo; bitsPerComponent = (int)image.BitsPerComponent; bitsPerPixel = (int)image.BitsPerPixel; bytesPerRow = width * bitsPerPixel / bitsPerComponent; int size = bytesPerRow * height; colorSpace = image.ColorSpace; // Right now internally we represent the images all the same // I left the call here just in case we find that this is not // possible. Read the comments for non alpha images. if (colorSpace != null) { if (hasAlpha) { colorSpace = CGColorSpace.CreateDeviceRGB(); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.PremultipliedLast; } else { // even for images without alpha we will internally // represent them as RGB with alpha. There were problems // if we do not do it this way and creating a bitmap context. // The images were not drawing correctly and tearing. Also // creating a Graphics to draw on was a nightmare. This // should probably be looked into or maybe it is ok and we // can continue representing internally with this representation colorSpace = CGColorSpace.CreateDeviceRGB(); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.NoneSkipLast; } } else { colorSpace = CGColorSpace.CreateDeviceRGB(); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.NoneSkipLast; } bytesPerRow = width * bitsPerPixel / bitsPerComponent; size = bytesPerRow * height; var bitmapBlock = Marshal.AllocHGlobal(size); bitmap = new CGBitmapContext(bitmapBlock, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo); bitmap.ClearRect(new CGRect(0, 0, width, height)); bitmap.DrawImage(new CGRect(0, 0, image.Width, image.Height), image); this.bitmapBlock = bitmapBlock; this.dataProvider = new CGDataProvider(bitmapBlock, size, true); NativeCGImage = new CGImage(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpace, bitmapInfo, dataProvider, null, true, image.RenderingIntent); colorSpace.Dispose(); cachedContext = bitmap; }
static Texture2D FromUIImage(UIImage uiImage, string name) { All filter = All.Linear; CGImage image = uiImage.CGImage; if(uiImage == null) throw new ArgumentNullException("uiImage"); // TODO: could use this to implement lower-bandwidth textures //bool hasAlpha = (image.AlphaInfo == CGImageAlphaInfo.First || image.AlphaInfo == CGImageAlphaInfo.Last // || image.AlphaInfo == CGImageAlphaInfo.PremultipliedFirst || image.AlphaInfo == CGImageAlphaInfo.PremultipliedLast); // Image dimentions: Point logicalSize = new Point((int)uiImage.Size.Width, (int)uiImage.Size.Height); int pixelWidth = uiImage.CGImage.Width; int pixelHeight = uiImage.CGImage.Height; // Round up the target texture width and height to powers of two: int potWidth = pixelWidth; int potHeight = pixelHeight; if(( potWidth & ( potWidth-1)) != 0) { int w = 1; while(w < potWidth) { w *= 2; } potWidth = w; } if((potHeight & (potHeight-1)) != 0) { int h = 1; while(h < potHeight) { h *= 2; } potHeight = h; } // Scale down textures that are too large... CGAffineTransform transform = CGAffineTransform.MakeIdentity(); while((potWidth > 1024) || (potHeight > 1024)) { potWidth /= 2; // Note: no precision loss - it's a power of two potHeight /= 2; pixelWidth /= 2; // Note: precision loss - assume possibility of dropping a pixel at each step is ok pixelHeight /= 2; transform.Multiply(CGAffineTransform.MakeScale(0.5f, 0.5f)); } lock(textureLoadBufferLockObject) { CreateTextureLoadBuffer(); unsafe { fixed(byte* data = textureLoadBuffer) { using(var colorSpace = CGColorSpace.CreateDeviceRGB()) using(var context = new CGBitmapContext(new IntPtr(data), potWidth, potHeight, 8, 4 * potWidth, colorSpace, CGImageAlphaInfo.PremultipliedLast)) { context.ClearRect(new RectangleF(0, 0, potWidth, potHeight)); context.TranslateCTM(0, potHeight - pixelHeight); // TODO: this does not play nice with the precision-loss above (keeping half-pixel to the edge) if(!transform.IsIdentity) context.ConcatCTM(transform); context.DrawImage(new RectangleF(0, 0, image.Width, image.Height), image); uint textureId = 0; /*textureId = new uint[1]; textureId[0]= 0; GL.GenTextures(1,textureId);*/ GL.GenTextures(1, ref textureId); GL.BindTexture(All.Texture2D, textureId); GL.TexParameter(All.Texture2D, All.TextureMinFilter, (int)filter); GL.TexParameter(All.Texture2D, All.TextureMagFilter, (int)filter); GL.TexImage2D(All.Texture2D, 0, (int)All.Rgba, (int)potWidth, (int)potHeight, 0, All.Rgba, All.UnsignedByte, new IntPtr(data)); return new Texture2D(logicalSize.X, logicalSize.Y, pixelWidth, pixelHeight, potWidth, potHeight, textureId, name); } } } } }
private void InitWithCGImage(CGImage image, All filter) { int width,height,i; CGContext context = null; IntPtr data; CGColorSpace colorSpace; IntPtr tempData; bool hasAlpha; CGImageAlphaInfo info; CGAffineTransform transform; Size imageSize; SurfaceFormat pixelFormat; bool sizeToFit = false; if(image == null) { throw new ArgumentException(" uimage is invalid! " ); } info = image.AlphaInfo; hasAlpha = ((info == CGImageAlphaInfo.PremultipliedLast) || (info == CGImageAlphaInfo.PremultipliedFirst) || (info == CGImageAlphaInfo.Last) || (info == CGImageAlphaInfo.First) ? true : false); if (image.ColorSpace != null) { pixelFormat = SurfaceFormat.Color; } else { pixelFormat = SurfaceFormat.Alpha8; } imageSize = new Size(image.Width,image.Height); transform = CGAffineTransform.MakeIdentity(); width = imageSize.Width; if((width != 1) && ((width & (width - 1))!=0)) { i = 1; while((sizeToFit ? 2 * i : i) < width) i *= 2; width = i; } height = imageSize.Height; if((height != 1) && ((height & (height - 1))!=0)) { i = 1; while((sizeToFit ? 2 * i : i) < height) i *= 2; height = i; } // TODO: kMaxTextureSize = 1024 while((width > 1024) || (height > 1024)) { width /= 2; height /= 2; transform = CGAffineTransform.MakeScale(0.5f,0.5f); imageSize.Width /= 2; imageSize.Height /= 2; } switch(pixelFormat) { case SurfaceFormat.Color: colorSpace = CGColorSpace.CreateDeviceRGB(); data = Marshal.AllocHGlobal(height * width * 4); context = new CGBitmapContext(data, width, height, 8, 4 * width, colorSpace,CGImageAlphaInfo.PremultipliedLast); colorSpace.Dispose(); break; case SurfaceFormat.Alpha8: data = Marshal.AllocHGlobal(height * width); context = new CGBitmapContext(data, width, height, 8, width, null, CGImageAlphaInfo.Only); break; default: throw new NotSupportedException("Invalid pixel format"); } context.ClearRect(new RectangleF(0,0,width,height)); context.TranslateCTM(0, height - imageSize.Height); if (!transform.IsIdentity) { context.ConcatCTM(transform); } context.DrawImage(new RectangleF(0, 0, image.Width, image.Height), image); //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" /* if(pixelFormat == SurfaceFormat.Rgb32) { tempData = Marshal.AllocHGlobal(height * width * 2); int d32; short d16; int inPixel32Count=0,outPixel16Count=0; for(i = 0; i < width * height; ++i, inPixel32Count+=sizeof(int)) { d32 = Marshal.ReadInt32(data,inPixel32Count); short R = (short)((((d32 >> 0) & 0xFF) >> 3) << 11); short G = (short)((((d32 >> 8) & 0xFF) >> 2) << 5); short B = (short)((((d32 >> 16) & 0xFF) >> 3) << 0); d16 = (short) (R | G | B); Marshal.WriteInt16(tempData,outPixel16Count,d16); outPixel16Count += sizeof(short); } Marshal.FreeHGlobal(data); data = tempData; } */ InitWithData(data,pixelFormat,width,height,imageSize, filter); context.Dispose(); Marshal.FreeHGlobal (data); }
private void InitWithCGImage(CGImage image, All filter) { int width, height, i; CGContext context = null; IntPtr data; CGColorSpace colorSpace; IntPtr tempData; bool hasAlpha; CGImageAlphaInfo info; CGAffineTransform transform; Size imageSize; SurfaceFormat pixelFormat; bool sizeToFit = false; if (image == null) { throw new ArgumentException(" NSImage is invalid! "); } info = image.AlphaInfo; hasAlpha = ((info == CGImageAlphaInfo.PremultipliedLast) || (info == CGImageAlphaInfo.PremultipliedFirst) || (info == CGImageAlphaInfo.Last) || (info == CGImageAlphaInfo.First) ? true : false); if (image.ColorSpace != null) { if (hasAlpha) { pixelFormat = SurfaceFormat.Rgba32; } else { pixelFormat = SurfaceFormat.Rgb32; } } else { pixelFormat = SurfaceFormat.Alpha8; } imageSize = new Size(image.Width, image.Height); transform = CGAffineTransform.MakeIdentity(); width = imageSize.Width; if ((width != 1) && ((width & (width - 1)) != 0)) { i = 1; while ((sizeToFit ? 2 * i : i) < width) { i *= 2; } width = i; } height = imageSize.Height; if ((height != 1) && ((height & (height - 1)) != 0)) { i = 1; while ((sizeToFit ? 2 * i : i) < height) { i *= 2; } height = i; } // TODO: kMaxTextureSize = 1024 while ((width > 1024) || (height > 1024)) { width /= 2; height /= 2; transform = CGAffineTransform.MakeScale(0.5f, 0.5f); imageSize.Width /= 2; imageSize.Height /= 2; } switch (pixelFormat) { case SurfaceFormat.Rgba32: colorSpace = CGColorSpace.CreateDeviceRGB(); data = Marshal.AllocHGlobal(height * width * 4); context = new CGBitmapContext(data, width, height, 8, 4 * width, colorSpace, CGImageAlphaInfo.PremultipliedLast); colorSpace.Dispose(); break; case SurfaceFormat.Rgb32: colorSpace = CGColorSpace.CreateDeviceRGB(); data = Marshal.AllocHGlobal(height * width * 4); context = new CGBitmapContext(data, width, height, 8, 4 * width, colorSpace, CGImageAlphaInfo.NoneSkipLast); colorSpace.Dispose(); break; case SurfaceFormat.Alpha8: data = Marshal.AllocHGlobal(height * width); context = new CGBitmapContext(data, width, height, 8, width, null, CGImageAlphaInfo.Only); break; default: throw new NotSupportedException("Invalid pixel format"); } context.ClearRect(new RectangleF(0, 0, width, height)); context.TranslateCTM(0, height - imageSize.Height); if (!transform.IsIdentity) { context.ConcatCTM(transform); } context.DrawImage(new RectangleF(0, 0, image.Width, image.Height), image); //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" if (pixelFormat == SurfaceFormat.Rgb32) { tempData = Marshal.AllocHGlobal(height * width * 2); int d32; short d16; int inPixel32Count = 0, outPixel16Count = 0; for (i = 0; i < width * height; ++i, inPixel32Count += sizeof(int)) { d32 = Marshal.ReadInt32(data, inPixel32Count); short R = (short)((((d32 >> 0) & 0xFF) >> 3) << 11); short G = (short)((((d32 >> 8) & 0xFF) >> 2) << 5); short B = (short)((((d32 >> 16) & 0xFF) >> 3) << 0); d16 = (short)(R | G | B); Marshal.WriteInt16(tempData, outPixel16Count, d16); outPixel16Count += sizeof(short); } Marshal.FreeHGlobal(data); data = tempData; } InitWithData(data, pixelFormat, width, height, imageSize, filter); context.Dispose(); Marshal.FreeHGlobal(data); }
public void GetData <T>(T[] data) { // TODO Causese AV on Device, but not simulator GetData<T>(0, null, data, 0, Width * Height); if (data == null) { throw new ArgumentException("data cannot be null"); } int sz = 0; byte[] pixel = new byte[4]; int pos; IntPtr pixelOffset; // Get the Color values if ((typeof(T) == typeof(Color))) { // Load up texture into memory UIImage uiImage = UIImage.FromBundle(this.Name); if (uiImage == null) { throw new ContentLoadException("Error loading file via UIImage: " + Name); } CGImage image = uiImage.CGImage; if (image == null) { throw new ContentLoadException("Error with CGIamge: " + Name); } int width, height, i; CGContext context = null; IntPtr imageData; CGColorSpace colorSpace; IntPtr tempData; bool hasAlpha; CGImageAlphaInfo info; CGAffineTransform transform; Size imageSize; SurfaceFormat pixelFormat; bool sizeToFit = false; info = image.AlphaInfo; hasAlpha = ((info == CGImageAlphaInfo.PremultipliedLast) || (info == CGImageAlphaInfo.PremultipliedFirst) || (info == CGImageAlphaInfo.Last) || (info == CGImageAlphaInfo.First) ? true : false); if (image.ColorSpace != null) { if (hasAlpha) { pixelFormat = SurfaceFormat.Rgba32; } else { pixelFormat = SurfaceFormat.Rgb32; } } else { pixelFormat = SurfaceFormat.Alpha8; } imageSize = new Size(image.Width, image.Height); transform = CGAffineTransform.MakeIdentity(); width = imageSize.Width; if ((width != 1) && ((width & (width - 1)) != 0)) { i = 1; while ((sizeToFit ? 2 * i : i) < width) { i *= 2; } width = i; } height = imageSize.Height; if ((height != 1) && ((height & (height - 1)) != 0)) { i = 1; while ((sizeToFit ? 2 * i : i) < height) { i *= 2; } height = i; } // TODO: kMaxTextureSize = 1024 while ((width > 1024) || (height > 1024)) { width /= 2; height /= 2; transform = CGAffineTransform.MakeScale(0.5f, 0.5f); imageSize.Width /= 2; imageSize.Height /= 2; } switch (pixelFormat) { case SurfaceFormat.Rgba32: colorSpace = CGColorSpace.CreateDeviceRGB(); imageData = Marshal.AllocHGlobal(height * width * 4); context = new CGBitmapContext(imageData, width, height, 8, 4 * width, colorSpace, CGImageAlphaInfo.PremultipliedLast); colorSpace.Dispose(); break; case SurfaceFormat.Rgb32: colorSpace = CGColorSpace.CreateDeviceRGB(); imageData = Marshal.AllocHGlobal(height * width * 4); context = new CGBitmapContext(imageData, width, height, 8, 4 * width, colorSpace, CGImageAlphaInfo.NoneSkipLast); colorSpace.Dispose(); break; case SurfaceFormat.Alpha8: imageData = Marshal.AllocHGlobal(height * width); context = new CGBitmapContext(imageData, width, height, 8, width, null, CGImageAlphaInfo.Only); break; default: throw new NotSupportedException("Invalid pixel format"); } context.ClearRect(new RectangleF(0, 0, width, height)); context.TranslateCTM(0, height - imageSize.Height); if (!transform.IsIdentity) { context.ConcatCTM(transform); } context.DrawImage(new RectangleF(0, 0, image.Width, image.Height), image); //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" if (pixelFormat == SurfaceFormat.Rgb32) { tempData = Marshal.AllocHGlobal(height * width * 2); int d32; short d16; int inPixel32Count = 0, outPixel16Count = 0; for (i = 0; i < width * height; ++i, inPixel32Count += sizeof(int)) { d32 = Marshal.ReadInt32(imageData, inPixel32Count); short R = (short)((((d32 >> 0) & 0xFF) >> 3) << 11); short G = (short)((((d32 >> 8) & 0xFF) >> 2) << 5); short B = (short)((((d32 >> 16) & 0xFF) >> 3) << 0); d16 = (short)(R | G | B); Marshal.WriteInt16(tempData, outPixel16Count, d16); outPixel16Count += sizeof(short); } Marshal.FreeHGlobal(imageData); imageData = tempData; } // Loop through and extract the data for (int y = 0; y < imageSize.Height; y++) { for (int x = 0; x < imageSize.Width; x++) { var result = new Color(0, 0, 0, 0); switch (pixelFormat) { case SurfaceFormat.Rgba32: //kTexture2DPixelFormat_RGBA8888 case SurfaceFormat.Dxt3: sz = 4; pos = ((y * imageSize.Width) + x) * sz; pixelOffset = new IntPtr(imageData.ToInt64() + pos); Marshal.Copy(pixelOffset, pixel, 0, 4); result.R = pixel[0]; result.G = pixel[1]; result.B = pixel[2]; result.A = pixel[3]; break; case SurfaceFormat.Bgra4444: //kTexture2DPixelFormat_RGBA4444 sz = 2; pos = ((y * imageSize.Width) + x) * sz; pixelOffset = new IntPtr(imageData.ToInt64() + pos); Marshal.Copy(pixelOffset, pixel, 0, 4); result.R = pixel[0]; result.G = pixel[1]; result.B = pixel[2]; result.A = pixel[3]; break; case SurfaceFormat.Bgra5551: //kTexture2DPixelFormat_RGB5A1 sz = 2; pos = ((y * imageSize.Width) + x) * sz; pixelOffset = new IntPtr(imageData.ToInt64() + pos); Marshal.Copy(pixelOffset, pixel, 0, 4); result.R = pixel[0]; result.G = pixel[1]; result.B = pixel[2]; result.A = pixel[3]; break; case SurfaceFormat.Rgb32: // kTexture2DPixelFormat_RGB565 sz = 2; pos = ((y * imageSize.Width) + x) * sz; pixelOffset = new IntPtr(imageData.ToInt64() + pos); Marshal.Copy(pixelOffset, pixel, 0, 4); result.R = pixel[0]; result.G = pixel[1]; result.B = pixel[2]; result.A = 255; break; case SurfaceFormat.Alpha8: // kTexture2DPixelFormat_A8 sz = 1; pos = ((y * imageSize.Width) + x) * sz; pixelOffset = new IntPtr(imageData.ToInt64() + pos); Marshal.Copy(pixelOffset, pixel, 0, 4); result.A = pixel[0]; break; default: throw new NotSupportedException("Texture format"); } data[((y * imageSize.Width) + x)] = (T)(object)result; } } context.Dispose(); Marshal.FreeHGlobal(imageData); } }
private void InitWithCGImage(CGImage image) { int width, height; CGBitmapContext bitmap = null; bool hasAlpha; CGImageAlphaInfo alphaInfo; CGColorSpace colorSpace; int bitsPerComponent, bytesPerRow; CGBitmapFlags bitmapInfo; bool premultiplied = false; int bitsPerPixel = 0; if (image == null) { throw new ArgumentException (" image is invalid! " ); } alphaInfo = image.AlphaInfo; hasAlpha = ((alphaInfo == CGImageAlphaInfo.PremultipliedLast) || (alphaInfo == CGImageAlphaInfo.PremultipliedFirst) || (alphaInfo == CGImageAlphaInfo.Last) || (alphaInfo == CGImageAlphaInfo.First) ? true : false); imageSize.Width = (int)image.Width; imageSize.Height = (int)image.Height; width = (int)image.Width; height = (int)image.Height; // Not sure yet if we need to keep the original image information // before we change it internally. TODO look at what windows does // and follow that. bitmapInfo = image.BitmapInfo; bitsPerComponent = (int)image.BitsPerComponent; bitsPerPixel = (int)image.BitsPerPixel; bytesPerRow = width * bitsPerPixel/bitsPerComponent; int size = bytesPerRow * height; colorSpace = image.ColorSpace; // Right now internally we represent the images all the same // I left the call here just in case we find that this is not // possible. Read the comments for non alpha images. if(colorSpace != null) { if( hasAlpha ) { premultiplied = true; colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.PremultipliedLast; } else { // even for images without alpha we will internally // represent them as RGB with alpha. There were problems // if we do not do it this way and creating a bitmap context. // The images were not drawing correctly and tearing. Also // creating a Graphics to draw on was a nightmare. This // should probably be looked into or maybe it is ok and we // can continue representing internally with this representation premultiplied = true; colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.NoneSkipLast; } } else { premultiplied = true; colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.NoneSkipLast; } bytesPerRow = width * bitsPerPixel/bitsPerComponent; size = bytesPerRow * height; bitmapBlock = Marshal.AllocHGlobal (size); bitmap = new CGBitmapContext (bitmapBlock, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo); bitmap.ClearRect (new CGRect (0,0,width,height)); // We need to flip the Y axis to go from right handed to lefted handed coordinate system var transform = new CGAffineTransform(1, 0, 0, -1, 0, image.Height); bitmap.ConcatCTM(transform); bitmap.DrawImage (new CGRect (0, 0, image.Width, image.Height), image); var provider = new CGDataProvider (bitmapBlock, size, true); NativeCGImage = new CGImage (width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpace, bitmapInfo, provider, null, true, image.RenderingIntent); colorSpace.Dispose(); bitmap.Dispose(); }
public void GetData <T>(int level, Rectangle?rect, T[] data, int startIndex, int elementCount) { if (data == null) { throw new ArgumentException("data cannot be null"); } if (data.Length < startIndex + elementCount) { throw new ArgumentException("The data passed has a length of " + data.Length + " but " + elementCount + " pixels have been requested."); } Rectangle r; if (rect != null) { r = rect.Value; } else { r = new Rectangle(0, 0, Width, Height); } int sz = 0; byte[] pixel = new byte[4]; int pos; IntPtr pixelOffset; // Get the Color values if ((typeof(T) == typeof(Color))) { // Load up texture into memory UIImage uiImage = UIImage.FromBundle(this.Name); if (uiImage == null) { throw new ContentLoadException("Error loading file via UIImage: " + Name); } CGImage image = uiImage.CGImage; if (image == null) { throw new ContentLoadException("Error with CGIamge: " + Name); } int width, height, i; CGContext context = null; IntPtr imageData; CGColorSpace colorSpace; IntPtr tempData; bool hasAlpha; CGImageAlphaInfo info; CGAffineTransform transform; Size imageSize; SurfaceFormat pixelFormat; bool sizeToFit = false; info = image.AlphaInfo; hasAlpha = ((info == CGImageAlphaInfo.PremultipliedLast) || (info == CGImageAlphaInfo.PremultipliedFirst) || (info == CGImageAlphaInfo.Last) || (info == CGImageAlphaInfo.First) ? true : false); if (image.ColorSpace != null) { pixelFormat = SurfaceFormat.Color; } else { pixelFormat = SurfaceFormat.Alpha8; } imageSize = new Size(image.Width, image.Height); transform = CGAffineTransform.MakeIdentity(); width = imageSize.Width; if ((width != 1) && ((width & (width - 1)) != 0)) { i = 1; while ((sizeToFit ? 2 * i : i) < width) { i *= 2; } width = i; } height = imageSize.Height; if ((height != 1) && ((height & (height - 1)) != 0)) { i = 1; while ((sizeToFit ? 2 * i : i) < height) { i *= 2; } height = i; } // TODO: kMaxTextureSize = 1024 while ((width > 1024) || (height > 1024)) { width /= 2; height /= 2; transform = CGAffineTransform.MakeScale(0.5f, 0.5f); imageSize.Width /= 2; imageSize.Height /= 2; } switch (pixelFormat) { case SurfaceFormat.Color: colorSpace = CGColorSpace.CreateDeviceRGB(); imageData = Marshal.AllocHGlobal(height * width * 4); context = new CGBitmapContext(imageData, width, height, 8, 4 * width, colorSpace, CGImageAlphaInfo.PremultipliedLast); colorSpace.Dispose(); break; case SurfaceFormat.Alpha8: imageData = Marshal.AllocHGlobal(height * width); context = new CGBitmapContext(imageData, width, height, 8, width, null, CGImageAlphaInfo.Only); break; default: throw new NotSupportedException("Invalid pixel format"); } context.ClearRect(new RectangleF(0, 0, width, height)); context.TranslateCTM(0, height - imageSize.Height); if (!transform.IsIdentity) { context.ConcatCTM(transform); } context.DrawImage(new RectangleF(0, 0, image.Width, image.Height), image); //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" /* * if(pixelFormat == SurfaceFormat.Rgb32) { * tempData = Marshal.AllocHGlobal(height * width * 2); * * int d32; * short d16; * int inPixel32Count=0,outPixel16Count=0; * for(i = 0; i < width * height; ++i, inPixel32Count+=sizeof(int)) * { * d32 = Marshal.ReadInt32(imageData,inPixel32Count); * short R = (short)((((d32 >> 0) & 0xFF) >> 3) << 11); * short G = (short)((((d32 >> 8) & 0xFF) >> 2) << 5); * short B = (short)((((d32 >> 16) & 0xFF) >> 3) << 0); * d16 = (short) (R | G | B); * Marshal.WriteInt16(tempData,outPixel16Count,d16); * outPixel16Count += sizeof(short); * } * Marshal.FreeHGlobal(imageData); * imageData = tempData; * } */ int count = 0; // Loop through and extract the data for (int y = r.Top; y < r.Bottom; y++) { for (int x = r.Left; x < r.Right; x++) { var result = new Color(0, 0, 0, 0); switch (this.Format) { case SurfaceFormat.Color /*kTexture2DPixelFormat_RGBA8888*/: case SurfaceFormat.Dxt3: sz = 4; pos = ((y * imageSize.Width) + x) * sz; pixelOffset = new IntPtr(imageData.ToInt64() + pos); Marshal.Copy(pixelOffset, pixel, 0, 4); result.R = pixel[0]; result.G = pixel[1]; result.B = pixel[2]; result.A = pixel[3]; break; case SurfaceFormat.Bgra4444 /*kTexture2DPixelFormat_RGBA4444*/: sz = 2; pos = ((y * imageSize.Width) + x) * sz; pixelOffset = new IntPtr(imageData.ToInt64() + pos); Marshal.Copy(pixelOffset, pixel, 0, 4); result.R = pixel[0]; result.G = pixel[1]; result.B = pixel[2]; result.A = pixel[3]; break; case SurfaceFormat.Bgra5551 /*kTexture2DPixelFormat_RGB5A1*/: sz = 2; pos = ((y * imageSize.Width) + x) * sz; pixelOffset = new IntPtr(imageData.ToInt64() + pos); Marshal.Copy(pixelOffset, pixel, 0, 4); result.R = pixel[0]; result.G = pixel[1]; result.B = pixel[2]; result.A = pixel[3]; break; case SurfaceFormat.Alpha8 /*kTexture2DPixelFormat_A8*/: sz = 1; pos = ((y * imageSize.Width) + x) * sz; pixelOffset = new IntPtr(imageData.ToInt64() + pos); Marshal.Copy(pixelOffset, pixel, 0, 4); result.A = pixel[0]; break; default: throw new NotSupportedException("Texture format"); } data[((y * imageSize.Width) + x)] = (T)(object)result; count++; if (count >= elementCount) { return; } } } context.Dispose(); Marshal.FreeHGlobal(imageData); } else { throw new NotImplementedException(); } }
public bool Finalize(IMTLDevice device) { if (MetalTexture != null) { return(true); } UIImage image = UIImage.FromFile(path); if (image == null) { return(false); } using (CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB()) { if (colorSpace == null) { return(false); } Width = image.CGImage.Width; Height = image.CGImage.Height; nuint width = (nuint)Width; nuint height = (nuint)Height; nuint rowBytes = width * 4; var context = new CGBitmapContext(IntPtr.Zero, (int)width, (int)height, 8, (int)rowBytes, colorSpace, CGImageAlphaInfo.PremultipliedLast); if (context == null) { return(false); } var bounds = new CGRect(0f, 0f, width, height); context.ClearRect(bounds); // Vertical Reflect if (flip) { context.TranslateCTM(width, height); context.ScaleCTM(-1f, -1f); } context.DrawImage(bounds, image.CGImage); MTLTextureDescriptor texDesc = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, width, height, false); if (texDesc == null) { return(false); } MetalTexture = device.CreateTexture(texDesc); if (MetalTexture == null) { context.Dispose(); return(false); } IntPtr pixels = context.Data; if (pixels != IntPtr.Zero) { var region = new MTLRegion(); region.Origin.X = 0; region.Origin.Y = 0; region.Size.Width = (nint)width; region.Size.Height = (nint)height; MetalTexture.ReplaceRegion(region, 0, pixels, rowBytes); } context.Dispose(); } return(true); }
public Bitmap(int width, int height, PixelFormat format) { imageTransform = new CGAffineTransform(1, 0, 0, -1, 0, height); int bitsPerComponent, bytesPerRow; CGColorSpace colorSpace; CGBitmapFlags bitmapInfo; bool premultiplied = false; int bitsPerPixel = 0; pixelFormat = format; // Don't forget to set the Image width and height for size. imageSize.Width = width; imageSize.Height = height; switch (format){ case PixelFormat.Format32bppPArgb: case PixelFormat.DontCare: premultiplied = true; colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.PremultipliedFirst; break; case PixelFormat.Format32bppArgb: colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.PremultipliedFirst; break; case PixelFormat.Format32bppRgb: colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.NoneSkipLast; break; case PixelFormat.Format24bppRgb: colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = CGBitmapFlags.NoneSkipLast; break; default: throw new Exception ("Format not supported: " + format); } bytesPerRow = width * bitsPerPixel/bitsPerComponent; int size = bytesPerRow * height; bitmapBlock = Marshal.AllocHGlobal (size); var bitmap = new CGBitmapContext (bitmapBlock, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo); // This works for now but we need to look into initializing the memory area itself // TODO: Look at what we should do if the image does not have alpha channel bitmap.ClearRect (new CGRect (0,0,width,height)); var provider = new CGDataProvider (bitmapBlock, size, true); NativeCGImage = new CGImage (width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpace, bitmapInfo, provider, null, false, CGColorRenderingIntent.Default); dpiWidth = dpiHeight = ConversionHelpers.MS_DPI; physicalDimension.Width = width; physicalDimension.Height = height; // The physical size may be off on certain implementations. For instance the dpiWidth and dpiHeight // are read using integers in core graphics but in windows it is a float. // For example: // coregraphics dpiWidth = 24 as integer // windows dpiWidth = 24.999935 as float // this gives a few pixels difference when calculating the physical size. // 256 * 96 / 24 = 1024 // 256 * 96 / 24.999935 = 983.04 // // https://bugzilla.xamarin.com/show_bug.cgi?id=14365 // PR: https://github.com/mono/maccore/pull/57 // physicalSize = new SizeF (physicalDimension.Width, physicalDimension.Height); physicalSize.Width *= ConversionHelpers.MS_DPI / dpiWidth; physicalSize.Height *= ConversionHelpers.MS_DPI / dpiHeight; rawFormat = ImageFormat.MemoryBmp; pixelFormat = format; }
public bool Finalize (IMTLDevice device) { if (MetalTexture != null) return true; UIImage image = UIImage.FromFile (path); if (image == null) return false; using (CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB ()) { if (colorSpace == null) return false; Width = image.CGImage.Width; Height = image.CGImage.Height; nuint width = (nuint)Width; nuint height = (nuint)Height; nuint rowBytes = width * 4; var context = new CGBitmapContext (IntPtr.Zero, (int)width, (int)height, 8, (int)rowBytes, colorSpace, CGImageAlphaInfo.PremultipliedLast); if (context == null) return false; var bounds = new CGRect (0f, 0f, width, height); context.ClearRect (bounds); // Vertical Reflect if (flip) { context.TranslateCTM (width, height); context.ScaleCTM (-1f, -1f); } context.DrawImage (bounds, image.CGImage); MTLTextureDescriptor texDesc = MTLTextureDescriptor.CreateTexture2DDescriptor (MTLPixelFormat.RGBA8Unorm, width, height, false); if (texDesc == null) return false; MetalTexture = device.CreateTexture (texDesc); if (MetalTexture == null) { context.Dispose (); return false; } IntPtr pixels = context.Data; if (pixels != IntPtr.Zero) { var region = new MTLRegion (); region.Origin.X = 0; region.Origin.Y = 0; region.Size.Width = (nint)width; region.Size.Height = (nint)height; MetalTexture.ReplaceRegion (region, 0, pixels, rowBytes); } context.Dispose (); } return true; }
// see http://deathbyalgorithm.blogspot.fr/2013/05/opentk-textures.html public static int LoadTexture(string name, int quality, bool repeat, bool flip_y) { string prefix; #if __IOS__ prefix = "OpenGLDemo.iOS."; #endif #if __ANDROID__ prefix = "OpenGLDemo.Droid."; #endif var assembly = typeof(App2).GetTypeInfo ().Assembly; // foreach (var res in assembly.GetManifestResourceNames()) // System.Diagnostics.Debug.WriteLine("found resource: " + res); Stream stream = assembly.GetManifestResourceStream (prefix + name + ".png"); byte[] imageData; using (MemoryStream ms = new MemoryStream()) { stream.CopyTo(ms); imageData = ms.ToArray(); } #if __ANDROID__ Bitmap b = BitmapFactory.DecodeByteArray (imageData, 0, imageData.Length); #elif __IOS__ UIImage image = ImageFromByteArray (imageData); int width = (int)image.CGImage.Width; int height = (int)image.CGImage.Height; CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB (); byte[] imageData2 = new byte[height * width * 4]; CGContext context = new CGBitmapContext (imageData2, width, height, 8, 4 * width, colorSpace, CGBitmapFlags.PremultipliedLast | CGBitmapFlags.ByteOrder32Big); colorSpace.Dispose (); context.ClearRect (new RectangleF (0, 0, width, height)); context.DrawImage (new RectangleF (0, 0, width, height), image.CGImage); #endif int [] textures = new int[1]; //Generate a new texture target in gl GL.GenTextures(1, textures); //Will bind the texture newly/empty created with GL.GenTexture //All gl texture methods targeting Texture2D will relate to this texture GL.BindTexture(TextureTarget.Texture2D, textures[0]); //The reason why your texture will show up glColor without setting these parameters is actually //TextureMinFilters fault as its default is NearestMipmapLinear but we have not established mipmapping //We are only using one texture at the moment since mipmapping is a collection of textures pre filtered //I'm assuming it stops after not having a collection to check. switch (quality) { case 1://High quality GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) All.Linear); break; //case 0: default://Low quality GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) All.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) All.Nearest); break; } if (repeat) { //This will repeat the texture past its bounds set by TexImage2D GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) All.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) All.Repeat); } else { //This will clamp the texture to the edge, so manipulation will result in skewing //It can also be useful for getting rid of repeating texture bits at the borders GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) All.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) All.ClampToEdge); } #if __ANDROID__ GLUtils.TexImage2D ((int) All.Texture2D, 0, b, 0); b.Recycle(); #elif __IOS__ GL.TexImage2D (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, imageData2); #endif GL.BindTexture(TextureTarget.Texture2D, 0); return textures[0]; }
private void InitWithCGImage(CGImage image, All filter) { int width, height, i; CGContext context = null; IntPtr data; CGColorSpace colorSpace; IntPtr tempData; bool hasAlpha; CGImageAlphaInfo info; CGAffineTransform transform; Size imageSize; SurfaceFormat pixelFormat; //bool sizeToFit = false; if (image == null) { throw new ArgumentException(" NSImage is invalid! "); } info = image.AlphaInfo; hasAlpha = ((info == CGImageAlphaInfo.PremultipliedLast) || (info == CGImageAlphaInfo.PremultipliedFirst) || (info == CGImageAlphaInfo.Last) || (info == CGImageAlphaInfo.First) ? true : false); if (image.ColorSpace != null) { if (hasAlpha) { pixelFormat = SurfaceFormat.Color; } else { pixelFormat = SurfaceFormat.Color; } } else { pixelFormat = SurfaceFormat.Alpha8; } imageSize = new Size(image.Width, image.Height); transform = CGAffineTransform.MakeIdentity(); width = imageSize.Width; // Take out the width and height adjustments for power of 2 // If not then GetData and SetData is messed up. // The Mac opengl version supports non power of 2 textures // so we do not have to make them so // if ((width != 1) && ((width & (width - 1)) != 0)) { // i = 1; // while ((sizeToFit ? 2 * i : i) < width) // i *= 2; // width = i; // } height = imageSize.Height; // The Mac opengl version supports non power of 2 textures // so we do not have to make them so // if ((height != 1) && ((height & (height - 1)) != 0)) { // i = 1; // while ((sizeToFit ? 2 * i : i) < height) // i *= 2; // height = i; // } // TODO: kMaxTextureSize = 1024 // while ((width > 1024) || (height > 1024)) { // width /= 2; // height /= 2; // transform = CGAffineTransform.MakeScale (0.5f, 0.5f); // imageSize.Width /= 2; // imageSize.Height /= 2; // } // I am going to take the following out right now to see how it reacts. It seems to be causing // a few problems for people. We may need to come up with another way to solve these issues as // one size is not fitting all. // float size = Math.Max(width,height); // if(size > 1024) // { // float ratio = 1024 / size; // width = (int)(width * ratio); // height = (int)(height * ratio); // transform = CGAffineTransform.MakeScale(ratio, ratio); // imageSize.Width = (int)(imageSize.Width * ratio); // imageSize.Height = (int)(imageSize.Height * ratio);; // } switch (pixelFormat) { case SurfaceFormat.Color: colorSpace = CGColorSpace.CreateDeviceRGB(); data = Marshal.AllocHGlobal(height * width * 4); context = new CGBitmapContext(data, width, height, 8, 4 * width, colorSpace, CGImageAlphaInfo.PremultipliedLast); colorSpace.Dispose(); break; case SurfaceFormat.Alpha8: data = Marshal.AllocHGlobal(height * width); context = new CGBitmapContext(data, width, height, 8, width, null, CGImageAlphaInfo.Only); break; default: throw new NotSupportedException("Invalid pixel format"); } context.ClearRect(new RectangleF(0, 0, width, height)); context.TranslateCTM(0, height - imageSize.Height); if (!transform.IsIdentity) { context.ConcatCTM(transform); } context.DrawImage(new RectangleF(0, 0, image.Width, image.Height), image); //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" /* * if(pixelFormat == SurfaceFormat.Rgb32) { * tempData = Marshal.AllocHGlobal(height * width * 2); * * int d32; * short d16; * int inPixel32Count=0,outPixel16Count=0; * for(i = 0; i < width * height; ++i, inPixel32Count+=sizeof(int)) * { * d32 = Marshal.ReadInt32(data,inPixel32Count); * short R = (short)((((d32 >> 0) & 0xFF) >> 3) << 11); * short G = (short)((((d32 >> 8) & 0xFF) >> 2) << 5); * short B = (short)((((d32 >> 16) & 0xFF) >> 3) << 0); * d16 = (short) (R | G | B); * Marshal.WriteInt16(tempData,outPixel16Count,d16); * outPixel16Count += sizeof(short); * } * Marshal.FreeHGlobal(data); * data = tempData; * } */ InitWithData(data, pixelFormat, width, height, imageSize, filter); context.Dispose(); Marshal.FreeHGlobal(data); }
public ESTexture2D(UIImage uiImage, All filter) { CGImage image = uiImage.CGImage; if(uiImage == null) throw new ArgumentNullException("uiImage"); // TODO: could use this to implement lower-bandwidth textures //bool hasAlpha = (image.AlphaInfo == CGImageAlphaInfo.First || image.AlphaInfo == CGImageAlphaInfo.Last // || image.AlphaInfo == CGImageAlphaInfo.PremultipliedFirst || image.AlphaInfo == CGImageAlphaInfo.PremultipliedLast); // Image dimentions: logicalSize = new Point((int)uiImage.Size.Width, (int)uiImage.Size.Height); pixelWidth = uiImage.CGImage.Width; pixelHeight = uiImage.CGImage.Height; // Round up the target texture width and height to powers of two: potWidth = pixelWidth; potHeight = pixelHeight; if(( potWidth & ( potWidth-1)) != 0) { int w = 1; while(w < potWidth) { w *= 2; } potWidth = w; } if((potHeight & (potHeight-1)) != 0) { int h = 1; while(h < potHeight) { h *= 2; } potHeight = h; } // Scale down textures that are too large... CGAffineTransform transform = CGAffineTransform.MakeIdentity(); while((potWidth > 1024) || (potHeight > 1024)) { potWidth /= 2; // Note: no precision loss - it's a power of two potHeight /= 2; pixelWidth /= 2; // Note: precision loss - assume possibility of dropping a pixel at each step is ok pixelHeight /= 2; transform.Multiply(CGAffineTransform.MakeScale(0.5f, 0.5f)); } RecalculateRatio(); lock(textureLoadBufferLockObject) { CreateTextureLoadBuffer(); unsafe { fixed(byte* data = textureLoadBuffer) { var colorSpace = CGColorSpace.CreateDeviceRGB(); var context = new CGBitmapContext(new IntPtr(data), potWidth, potHeight, 8, 4 * potWidth, colorSpace, CGImageAlphaInfo.PremultipliedLast); context.ClearRect(new RectangleF(0, 0, potWidth, potHeight)); context.TranslateCTM(0, potHeight - pixelHeight); // TODO: this does not play nice with the precision-loss above (keeping half-pixel to the edge) if(!transform.IsIdentity) context.ConcatCTM(transform); context.DrawImage(new RectangleF(0, 0, image.Width, image.Height), image); SetupTexture(new IntPtr(data), filter); context.Dispose(); colorSpace.Dispose(); } } } }
private CGBitmapContext CreateCompatibleBitmapContext(int width, int height, PixelFormat pixelFormat) { int bitsPerComponent, bytesPerRow; CGColorSpace colorSpace; CGImageAlphaInfo alphaInfo; bool premultiplied = false; int bitsPerPixel = 0; // CoreGraphics only supports a few options so we have to make do with what we have // https://developer.apple.com/library/mac/qa/qa1037/_index.html switch (pixelFormat) { case PixelFormat.Format32bppPArgb: case PixelFormat.DontCare: premultiplied = true; colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; alphaInfo = CGImageAlphaInfo.PremultipliedLast; break; case PixelFormat.Format32bppArgb: colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; alphaInfo = CGImageAlphaInfo.PremultipliedLast; break; case PixelFormat.Format32bppRgb: colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; alphaInfo = CGImageAlphaInfo.PremultipliedLast; break; case PixelFormat.Format24bppRgb: colorSpace = CGColorSpace.CreateDeviceRGB (); bitsPerComponent = 8; bitsPerPixel = 32; alphaInfo = CGImageAlphaInfo.PremultipliedLast; break; default: throw new Exception ("Format not supported: " + pixelFormat); } bytesPerRow = width * bitsPerPixel/bitsPerComponent; int size = bytesPerRow * height; var bitmapBlock = Marshal.AllocHGlobal (size); var bitmap = new CGBitmapContext (bitmapBlock, width, height, bitsPerComponent, bytesPerRow, colorSpace, alphaInfo); bitmap.ClearRect (new CGRect (0,0,width,height)); //colorSpace.Dispose (); return bitmap; }
public static TextureData FromUIImage(UIImage uiImage) { if (uiImage == null) { throw new ArgumentNullException("uiImage"); } var image = uiImage.CGImage; if (image == null) { throw new ArgumentNullException("uiImage.CGImage"); } var info = image.AlphaInfo; var hasAlpha = ((info == CGImageAlphaInfo.PremultipliedLast) || (info == CGImageAlphaInfo.PremultipliedFirst) || (info == CGImageAlphaInfo.Last) || (info == CGImageAlphaInfo.First)); var pixelFormat = TexturePixelFormat.RGBA8888; if (image.ColorSpace != null) { if (hasAlpha) { pixelFormat = TexturePixelFormat.RGBA8888; } else { pixelFormat = TexturePixelFormat.RGB565; } } else //NOTE: No colorspace means a mask image { pixelFormat = TexturePixelFormat.A8; } var width = image.Width; var height = image.Height; var data = IntPtr.Zero; CGBitmapContext context = null; switch (pixelFormat) { case TexturePixelFormat.RGBA8888: using (var colorSpace = CGColorSpace.CreateDeviceRGB()) { data = Marshal.AllocHGlobal(height * width * 4); context = new CGBitmapContext(data, width, height, 8, 4 * width, colorSpace, (CGImageAlphaInfo)((uint)CGImageAlphaInfo.PremultipliedLast | (uint)CGBitmapFlags.ByteOrder32Big)); } break; case TexturePixelFormat.RGB565: using (var colorSpace = CGColorSpace.CreateDeviceRGB()) { data = Marshal.AllocHGlobal(height * width * 4); context = new CGBitmapContext(data, width, height, 8, 4 * width, colorSpace, (CGImageAlphaInfo)((uint)CGImageAlphaInfo.NoneSkipLast | (uint)CGBitmapFlags.ByteOrder32Big)); } break; case TexturePixelFormat.A8: data = Marshal.AllocHGlobal(height * width); context = new CGBitmapContext(data, width, height, 8, width, null, CGImageAlphaInfo.Only); break; default: throw new NotSupportedException(pixelFormat + " is not supported"); } context.ClearRect(new RectangleF(0, 0, width, height)); context.DrawImage(new RectangleF(0, 0, width, height), image); context.Dispose(); if (pixelFormat == TexturePixelFormat.RGB565) { var tempData = Marshal.AllocHGlobal(height * width * 2); unsafe { var inPixel32 = (uint *)data; var outPixel16 = (ushort *)tempData; for (var i = 0; i < width * height; ++i, ++inPixel32) { *outPixel16++ = (ushort)(((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0)); } } Marshal.FreeHGlobal(data); data = tempData; } return(new TextureData(data, pixelFormat, width, height)); }
public Texture2D(UIImage uiImage) { if (uiImage == null) { throw new ArgumentNullException("uiImage"); } CGImage image = uiImage.CGImage; if (image == null) { throw new InvalidOperationException("Attempted to create a Texture2D from UIImage, but resulting CGImage is null"); } CGImageAlphaInfo info = image.AlphaInfo; bool hasAlpha = info == CGImageAlphaInfo.PremultipliedLast || info == CGImageAlphaInfo.PremultipliedFirst || info == CGImageAlphaInfo.Last || info == CGImageAlphaInfo.First; int bpp = image.BitsPerComponent; Texture2DPixelFormat pixelFormat; if (image.ColorSpace != null) { if (hasAlpha || bpp >= 8) { pixelFormat = Texture2DPixelFormat.Default; } else { pixelFormat = Texture2DPixelFormat.RGB565; } } else { pixelFormat = Texture2DPixelFormat.A8; } int width = image.Width; if (width != 1 && (width & (width - 1)) != 0) { int i = 1; while (i < width) { i *= 2; } width = i; } int height = image.Height; if (height != 1 && (height & (height - 1)) != 0) { int i = 1; while (i < height) { i *= 2; } height = i; } if (width > MaxTextureSize || height > MaxTextureSize) { throw new InvalidOperationException("Image is too large. Width or height larger than MaxTextureSize"); } CGColorSpace colorSpace = null; CGContext context; byte[] data; unsafe { // all formats require w*h*4, except A8 requires just w*h int dataSize = width * height * 4; if (pixelFormat == Texture2DPixelFormat.A8) { dataSize = width * height; } data = new byte[dataSize]; fixed (byte* dp = data) { switch (pixelFormat) { case Texture2DPixelFormat.RGBA8888: case Texture2DPixelFormat.RGBA4444: case Texture2DPixelFormat.RGB5A1: colorSpace = CGColorSpace.CreateDeviceRGB(); context = new CGBitmapContext((IntPtr)dp, (int)width, (int)height, 8, 4 * (int)width, colorSpace, CGImageAlphaInfo.PremultipliedLast); break; case Texture2DPixelFormat.RGB565: colorSpace = CGColorSpace.CreateDeviceRGB(); context = new CGBitmapContext((IntPtr)dp, (int)width, (int)height, 8, 4 * (int)width, colorSpace, CGImageAlphaInfo.NoneSkipLast); break; case Texture2DPixelFormat.A8: context = new CGBitmapContext((IntPtr)dp, (int)width, (int)height, 8, (int)width, null, CGImageAlphaInfo.Only); break; default: throw new InvalidEnumArgumentException("pixelFormat", (int)pixelFormat, typeof(Texture2DPixelFormat)); } if (colorSpace != null) { colorSpace.Dispose(); } context.ClearRect(new RectangleF(0, 0, width, height)); context.TranslateCTM(0, height - image.Height); // why is this here? make an identity transform, then immediately not use it? Need to look into this CGAffineTransform transform = CGAffineTransform.MakeIdentity(); if (!transform.IsIdentity) { context.ConcatCTM(transform); } context.DrawImage(new RectangleF(0, 0, image.Width, image.Height), image); } } if (pixelFormat == Texture2DPixelFormat.RGB565) { //Convert "RRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" byte[] tempData = new byte[height * width * 2]; unsafe { fixed (byte* inPixel32b = data) { uint* inPixel32 = (uint*)inPixel32b; fixed (byte* outPixel16b = tempData) { ushort* outPixel16 = (ushort*)outPixel16b; for (int i = 0; i < width * height; ++i,++inPixel32) { uint tempInt32 = ((((*inPixel32 >> 0) & 0xff) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xff) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xff) >> 3) << 0); *outPixel16++ = (ushort)tempInt32; } } } } data = tempData; } else if (pixelFormat == Texture2DPixelFormat.RGBA4444) { //Convert "RRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA" byte[] tempData = new byte[height * width * 2]; unsafe { fixed (byte* inPixel32b = data) { uint* inPixel32 = (uint*)inPixel32b; fixed (byte* outPixel16b = tempData) { ushort* outPixel16 = (ushort*)outPixel16b; for (int i = 0; i < width * height; ++i,++inPixel32) { uint tempInt32 = ((((*inPixel32 >> 0) & 0xff) >> 4) << 12) | ((((*inPixel32 >> 8) & 0xff) >> 4) << 8) | ((((*inPixel32 >> 16) & 0xff) >> 4) << 4) | ((((*inPixel32 >> 24) & 0xff) >> 4) << 0); *outPixel16++ = (ushort)tempInt32; } } } } data = tempData; } else if (pixelFormat == Texture2DPixelFormat.RGB5A1) { //Convert "RRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA" byte[] tempData = new byte[height * width * 2]; unsafe { fixed (byte* inPixel32b = data) { uint* inPixel32 = (uint*)inPixel32b; fixed (byte* outPixel16b = tempData) { ushort* outPixel16 = (ushort*)outPixel16b; for (int i = 0; i < width * height; ++i,++inPixel32) { uint tempInt32 = ((((*inPixel32 >> 0) & 0xff) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xff) >> 3) << 6) | ((((*inPixel32 >> 16) & 0xff) >> 3) << 1) | ((((*inPixel32 >> 24) & 0xff) >> 7) << 0); *outPixel16++ = (ushort)tempInt32; } } } } data = tempData; } InitWithData(data, pixelFormat, width, height, new SizeF(image.Width, image.Height)); HasPremultipliedAlpha = info == CGImageAlphaInfo.PremultipliedLast || info == CGImageAlphaInfo.PremultipliedFirst; context.Dispose(); }