「Xamarin.Macで画素配列からCGImageを生成する」の版間の差分
ナビゲーションに移動
検索に移動
imported>Administrator (→RGB画像) |
Administrator (トーク | 投稿記録) 細 (Administrator がページ「Xamarin.Mac/画素配列からCGImageを生成する」を「Xamarin.Macで画素配列からCGImageを生成する」に移動しました) |
2019年12月25日 (水) 08:04時点における最新版
勉強がてらJPEGのコーデックをC#で実装してみているのだが、デコード済みの画素データが格納されたbyte配列からCGImageを生成したい。
RGB画像[編集 | ソースを編集]
RGBなのでコンポーネント数は3で問題ないと思う。
public static CGImage CreateImage()
{
var colorSpace = CGColorSpace.CreateDeviceRGB();
var width = 512;
var height = 512;
var bitsPerSample = 8;
var components = 3;//RGB
var bitsPerPixel = bitsPerSample * components;
var bytesPerRow = bitsPerPixel / 8 * width;
var buffer = new byte[width * height * components];
int a = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
var c = (byte)((1 << bitsPerSample) * ((float)y / width));
buffer[a++] = c;
buffer[a++] = 0;
buffer[a++] = 0;
}
}
var data = new CGDataProvider(buffer);
var cgImage = new CGImage(
width,
height,
bitsPerSample,
bitsPerPixel,
bytesPerRow,
colorSpace,
CGBitmapFlags.ByteOrderDefault,
data,
decode: null,
shouldInterpolate: false,
intent: CGColorRenderingIntent.Default);
return cgImage;
}
拾ってきたLennaの画像は正常にデコードできたようだ。 画素の入ったbyte配列をCGDataProviderクラスでラップしてCGImageのコンストラクタに渡すのがポイント。
var error = "";
var header = new JlsParameters();
var dst = new MemoryStream();
var path = Path.Combine(NSBundle.MainBundle.BundlePath, "Contents", "Resources", "lena24b.jpg");
var src = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None);
var result = Jpeg.Decode(dst, src, header, out error);
Console.WriteLine(header);
dst.Seek(0, SeekOrigin.Begin);
var buf = dst.ToArray();
// 画素データ
var data = new CGDataProvider(buf);
var colorspace = CGColorSpace.CreateDeviceRGB();
var cgImage = new CGImage(
header.width,
header.height,
header.bitsPerSample,
header.bitsPerSample * header.components,
header.components * header.width,
colorspace,
CGBitmapFlags.ByteOrderDefault,
data,
decode: null,
shouldInterpolate: false,
intent: CGColorRenderingIntent.Default);
var nsImage = new NSImage(cgImage, new CGSize(cgImage.Width, cgImage.Height));
インデックスカラー画像[編集 | ソースを編集]
ついでにインデックスカラーも試してみた。
public static CGImage CreateIndexedImage()
{
var colors = new byte[] {
0, 0, 0,
63, 0, 0,
127, 0, 0,
191, 0, 0,
255, 0, 0
};
var colorSpace = CGColorSpace.CreateIndexed(CGColorSpace.CreateDeviceRGB(), colors.Length / 3, colors);
var width = 512;
var height = 512;
var bitsPerSample = 8;
var components = 1;// Indexed Color
var bitsPerPixel = bitsPerSample * components;
var bytesPerRow = bitsPerPixel / 8 * width;
var buffer = new byte[width * height * components];
int a = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
var c = (byte)((colors.Length / 3) * ((float)y / width));
buffer[a++] = c;
}
}
var data = new CGDataProvider(buffer);
var cgImage = new CGImage(
width,
height,
bitsPerSample,
bitsPerPixel,
bytesPerRow,
colorSpace,
CGBitmapFlags.ByteOrderDefault,
data,
decode: null,
shouldInterpolate: false,
intent: CGColorRenderingIntent.Default);
return cgImage;
}