У меня проблема, и я месяцами искал решение, прежде чем публиковать здесь.
Проблема с прозрачными файлами PNG в Monotouch:
Я пытаюсь загрузить прозрачный PNG в контексте , чтобы считывать и записывать цвета пикселей . Я использую код ниже, который отлично работает с непрозрачными PNG. (Я также включаю несколько других попыток сделать правильный результат)
При использовании прозрачных PNG-файлов проблема заключается в том, что мне нужно загрузить изображение в контексте с предварительно умноженной альфа-информацией ( CGImageAlphaInfo.PremultipliedLast ). Это приводит к изменению значений RGB по сравнению с их исходными значениями при загрузке в контексте.
Я пытался создать контекст с CGImageAlphaInfo.Last (что теоретически правильно), но я получил исключение (недопустимая комбинация параметров).
Я думал попробовать CoreImage, но это ограничило бы наших пользователей iOS 5 или более поздней версией, и я решил, что это неприемлемо.
Мне крайне необходимо найти способ получения и установки пикселей в прозрачных PNG, поскольку я создаю кроссплатформенное программное обеспечение (iPhone, iPad, Mac с использованием MonoMac и Windows), которое должно обрабатывать прозрачные PNG.
Любая помощь будет принята с благодарностью.
Спасибо!
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Drawing;
using MonoTouch.CoreGraphics;
using System.Runtime.InteropServices;
using MonoTouch.CoreImage;
namespace TestPNG
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
// class-level declarations
UIWindow window;
TestPNGViewController viewController;
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
window = new UIWindow (UIScreen.MainScreen.Bounds);
viewController = new TestPNGViewController ();
window.RootViewController = viewController;
window.MakeKeyAndVisible ();
UIImage _CarrierImage = UIImage.FromFile ("Blue50.png");
int width = _CarrierImage.CGImage.Width;
int height = _CarrierImage.CGImage.Height;
CGImage cg = _CarrierImage.CGImage;
Console.WriteLine ("width: " + width.ToString ("000") + ", height: " + height.ToString ("000"));
Console.WriteLine ("BitsPerComponent: " + cg.BitsPerComponent.ToString ());
Console.WriteLine ("BytesPerRow: " + cg.BytesPerRow.ToString ());
Console.WriteLine ("BitsPerPixel: " + cg.BitsPerPixel.ToString ());
Console.WriteLine ("ColorSpace: " + cg.ColorSpace.ToString ());
Console.WriteLine ("For image Blue0.png should have values: R:0, G:0, B:255, A: 0");
Console.WriteLine ("For image Blue50.png should have values: R:0, G:0, B:255, A: 128");
Console.WriteLine ("For image Blue100.png should have values: R:0, G:0, B:255, A: 255");
// METHOD 1
// CGDataProvider p = CGDataProvider.FromFile("Blue50.png");
// CGImage cgimg = CGImage.FromPNG(p,null,false,CGColorRenderingIntent.Default);
// UIImage _CarrierImage = new UIImage(cgimg);
// METHOD 2
// NSData dt = _CarrierImage.AsPNG();
// IntPtr bitmapData = dt.Bytes;
//
// Console.WriteLine("Length: " + dt.Length.ToString());
// for (int i=0; i < dt.Length; i++)
// {
// Console.WriteLine("i: " + i.ToString("00") + ", byte: " + dt[i].ToString());
// }
//
// METHOD 3
// UIGraphics.BeginImageContext (_CarrierImage.Size);
// CGContext ctx = UIGraphics.GetCurrentContext ();
// ctx.DrawImage (new RectangleF (0, 0, _CarrierImage.Size.Width, _CarrierImage.Size.Height), _CarrierImage.CGImage);
// IntPtr dt = ctx.Handle;
// for (int i=0; i < 100; i++)
// {
// Console.WriteLine("i: " + i.ToString("00") + ", byte: " + GetByte(i, dt).ToString ());
// }
// UIGraphics.EndImageContext();
// METHOD 4
int bitmapBytesPerRow = width * 4;
IntPtr bitmapData = Marshal.AllocHGlobal (width * 4 * height);
CGBitmapContext ctxt = new CGBitmapContext (bitmapData, width, height, cg.BitsPerComponent, bitmapBytesPerRow, cg.ColorSpace, CGImageAlphaInfo.PremultipliedLast);
RectangleF rect = new RectangleF (0.0f, 0.0f, width, height);
ctxt.DrawImage (rect, _CarrierImage.CGImage);
IntPtr dt = ctxt.Data;
Console.WriteLine ("R: " + GetByte (0, dt).ToString ());
Console.WriteLine ("G: " + GetByte (1, dt).ToString ());
Console.WriteLine ("B: " + GetByte (2, dt).ToString ());
Console.WriteLine ("A: " + GetByte (3, dt).ToString ());
return true;
}
unsafe byte GetByte (int offset, IntPtr buffer)
{
byte* bufferAsBytes = (byte*)buffer;
return bufferAsBytes [offset];
}
}
}