C# 与IntPtr的混淆和对结构的封送
我正在学习Objective C代码,并将其转换为Xamarin iOS项目的C#代码 我正在拍摄一张UIImage,并尝试获取像素,以便获取RGB值,以便在收据上打印图像 我有这样一个结构:C# 与IntPtr的混淆和对结构的封送,c#,xamarin.ios,marshalling,intptr,C#,Xamarin.ios,Marshalling,Intptr,我正在学习Objective C代码,并将其转换为Xamarin iOS项目的C#代码 我正在拍摄一张UIImage,并尝试获取像素,以便获取RGB值,以便在收据上打印图像 我有这样一个结构: public struct ARGBPixel { public byte alpha; public byte red; public byte green; public byte blue;
public struct ARGBPixel {
public byte alpha;
public byte red;
public byte green;
public byte blue;
};
private NSData GetMiniData(UIImage image)
{
NSMutableData commands = new NSMutableData ();
int width = (int)image.Size.Width;
int height = (int)image.Size.Height;
var pixels = RequestImagePixelData (image);
int w = width / 8;
if ((width % 8) != 0)
w++;
int mWidth = w * 8;
int byteWidth = mWidth / 8;
commands.AppendBytes (new byte[]{ 0x1b, 0x40 });
byte totalRowCount = 0;
while (totalRowCount < height) {
byte[] data = new byte[sizeof(byte) * byteWidth * 24];
UInt32 pos = 0;
for (int y = 0; y < 24; y++) {
if (totalRowCount < height) {
for (byte x = 0; x < byteWidth; x++) {
int bits = 8;
if ((x == byteWidth - 1) && (width < mWidth)) {
bits = 8 - (mWidth - width);
}
byte work = 0x00;
for (byte xbit = 0; xbit < bits; xbit++) {
work <<= 1;
byte[] dataBytes = new byte[2048];
Marshal.Copy (pixels, dataBytes, 0, Convert.ToInt32 (2048));
//ARGBPixel argbpixel = MarshalPixel (dataBytes [PixelIndex ((byte)(xbit + x * 8), totalRowCount, (byte)width)]);
//Marshal.PtrToStructure(dataBytes[PixelIndex ((byte)(xbit + x * 8), totalRowCount, (byte)width)], typeof(ARGBPixel));
var pix = 255;
if (PixelBrightness(argbpixel.red, argbpixel.green, argbpixel.blue) < 127)
{
work |= 0x01;
}
}
data [pos++] = work;
}
}
totalRowCount++;
}
NSMutableData command = null;
/*if (true) {
command = SMPort.GenerateBitImageCommand (byteWidth, 24, data, "mini");
}*/
if (command != null) {
commands.AppendData (command);
} else {
byte[] imageBytes = new byte[]{ 0x1b, 0x58, 0x34, 0, 24 }; // [ESC X 4]
imageBytes [3] = (byte) byteWidth;
commands.AppendBytes (imageBytes);
commands.AppendBytes (data);
byte[] printBytes = new byte[] { 0x1b, 0x58, 0x32, 24 };
commands.AppendBytes (printBytes);
}
//free(data);
}
byte[] endingBytes = new byte[]{ 0x0c, 0x1b, 0x4A, 0x78 };
commands.AppendBytes (endingBytes);
//free(pixels);
return NSData.FromBytes (commands.Bytes, commands.Length);
//[someData release];
//return imageData;
}
public ARGBPixel MarshalPixel(byte[] bytes)
{
GCHandle handle = GCHandle.Alloc (bytes, GCHandleType.Pinned);
ARGBPixel pix = (ARGBPixel)Marshal.PtrToStructure (handle.AddrOfPinnedObject (), typeof(ARGBPixel));
handle.Free ();
return pix;
}
我有一些代码(由提供)将获取UIImage并返回指向如下数据的指针:
protected CGBitmapContext CreateARGBBitmapContext(CGImage inImage)
{
var pixelsWide = inImage.Width;
var pixelsHigh = inImage.Height;
var bitmapBytesPerRow = pixelsWide * 4;
var bitmapByteCount = bitmapBytesPerRow * pixelsHigh;
//Note implicit colorSpace.Dispose()
using(var colorSpace = CGColorSpace.CreateDeviceRGB())
{
//Allocate the bitmap and create context
var bitmapData = Marshal.AllocHGlobal(bitmapByteCount);
//I think this is unnecessary, as I believe Marshal.AllocHGlobal will throw OutOfMemoryException
if(bitmapData == IntPtr.Zero)
{
throw new Exception("Memory not allocated.");
}
var context = new CGBitmapContext(bitmapData, pixelsWide, pixelsHigh, 8,
bitmapBytesPerRow, colorSpace, CGImageAlphaInfo.PremultipliedFirst);
if(context == null)
{
throw new Exception("Context not created");
}
return context;
}
}
//Store pixel data as an ARGB Bitmap
protected IntPtr RequestImagePixelData(UIImage inImage)
{
var imageSize = inImage.Size;
CGBitmapContext ctxt = CreateARGBBitmapContext(inImage.CGImage);
var rect = new RectangleF(0.0f, 0.0f, imageSize.Width, imageSize.Height);
ctxt.DrawImage(rect, inImage.CGImage);
var data = ctxt.Data;
return data;
}
获取数据后,我希望通过以下操作将数据数组中的每个元素封送到ARGBPixel
:
ARGBPixel argbpixel = //stuck here
代码如下所示:
public struct ARGBPixel {
public byte alpha;
public byte red;
public byte green;
public byte blue;
};
private NSData GetMiniData(UIImage image)
{
NSMutableData commands = new NSMutableData ();
int width = (int)image.Size.Width;
int height = (int)image.Size.Height;
var pixels = RequestImagePixelData (image);
int w = width / 8;
if ((width % 8) != 0)
w++;
int mWidth = w * 8;
int byteWidth = mWidth / 8;
commands.AppendBytes (new byte[]{ 0x1b, 0x40 });
byte totalRowCount = 0;
while (totalRowCount < height) {
byte[] data = new byte[sizeof(byte) * byteWidth * 24];
UInt32 pos = 0;
for (int y = 0; y < 24; y++) {
if (totalRowCount < height) {
for (byte x = 0; x < byteWidth; x++) {
int bits = 8;
if ((x == byteWidth - 1) && (width < mWidth)) {
bits = 8 - (mWidth - width);
}
byte work = 0x00;
for (byte xbit = 0; xbit < bits; xbit++) {
work <<= 1;
byte[] dataBytes = new byte[2048];
Marshal.Copy (pixels, dataBytes, 0, Convert.ToInt32 (2048));
//ARGBPixel argbpixel = MarshalPixel (dataBytes [PixelIndex ((byte)(xbit + x * 8), totalRowCount, (byte)width)]);
//Marshal.PtrToStructure(dataBytes[PixelIndex ((byte)(xbit + x * 8), totalRowCount, (byte)width)], typeof(ARGBPixel));
var pix = 255;
if (PixelBrightness(argbpixel.red, argbpixel.green, argbpixel.blue) < 127)
{
work |= 0x01;
}
}
data [pos++] = work;
}
}
totalRowCount++;
}
NSMutableData command = null;
/*if (true) {
command = SMPort.GenerateBitImageCommand (byteWidth, 24, data, "mini");
}*/
if (command != null) {
commands.AppendData (command);
} else {
byte[] imageBytes = new byte[]{ 0x1b, 0x58, 0x34, 0, 24 }; // [ESC X 4]
imageBytes [3] = (byte) byteWidth;
commands.AppendBytes (imageBytes);
commands.AppendBytes (data);
byte[] printBytes = new byte[] { 0x1b, 0x58, 0x32, 24 };
commands.AppendBytes (printBytes);
}
//free(data);
}
byte[] endingBytes = new byte[]{ 0x0c, 0x1b, 0x4A, 0x78 };
commands.AppendBytes (endingBytes);
//free(pixels);
return NSData.FromBytes (commands.Bytes, commands.Length);
//[someData release];
//return imageData;
}
public ARGBPixel MarshalPixel(byte[] bytes)
{
GCHandle handle = GCHandle.Alloc (bytes, GCHandleType.Pinned);
ARGBPixel pix = (ARGBPixel)Marshal.PtrToStructure (handle.AddrOfPinnedObject (), typeof(ARGBPixel));
handle.Free ();
return pix;
}
在这一点上我完全糊涂了。我只想能够得到像素,以便告诉什么是亮度,这将决定我的字节数组中的下一个序列作为命令馈送到我的打印机
如果这有帮助的话……以下是我试图更改的目标c代码,以便使用我的Xamarin应用程序:
- (NSData *)getImageMiniDataForPrinting:(BOOL)compressionEnable pageModeEnable:(BOOL)pageModeEnable
{
if (imageData != nil)
{
return imageData;
}
CGImageRef cgImage = [m_image CGImage];
int32_t width = CGImageGetWidth(cgImage);
int32_t height = CGImageGetHeight(cgImage);
ARGBPixel * pixels = malloc(width * height * sizeof(ARGBPixel));
ManipulateImagePixelData(cgImage, pixels);
if (ditheringSupported == true)
{
ConvertToMonochromeSteinbertDithering(pixels, width, height, 1.5);
}
if (pixels == NULL)
{
return NULL;
}
int w = width / 8;
if ((width % 8) != 0)
w++;
int mWidth = w * 8;
int byteWidth = mWidth / 8;
NSMutableData *someData = [[NSMutableData alloc] init];
if (pageModeEnable)
{
u_int8_t beginingBytes[] = {0x1b, 0x40,
0x1b, 0x4c,
// 0x1b, 0x57, 0x00, 0x00, 0x00, 0x00, mWidth % 256, mWidth / 256, height % 256, height / 256,
0x1b, 0x57, 0x00, 0x00, 0x00, 0x00, mWidth % 256, mWidth / 256, (height + 50) % 256, (height + 50) / 256,
0x1b, 0x58, 0x32, 0x18};
[someData appendBytes:beginingBytes length:2 + 2 + 10 + 4];
}
else
{
u_int8_t beginingBytes[] = {0x1b, 0x40};
[someData appendBytes:beginingBytes length:2];
}
int totalRowCount = 0;
while (totalRowCount < height)
{
u_int8_t *data = malloc(sizeof(u_int8_t) * byteWidth * 24);
memset(data, 0, sizeof(u_int8_t) * byteWidth * 24);
uint32_t pos = 0;
for (int y = 0; y < 24; y++)
{
if (totalRowCount < height)
{
for (int x = 0; x < byteWidth; x++)
{
int bits = 8;
if ((x == byteWidth - 1) && (width < mWidth))
{
bits = 8 - (mWidth - width);
}
u_int8_t work = 0x00;
for (int xbit = 0; xbit < bits; xbit++)
{
work <<= 1;
ARGBPixel pixel = pixels[PixelIndex(xbit + x * 8, totalRowCount, width)];
if (PixelBrightness(pixel.red, pixel.green, pixel.blue) < 127)
{
work |= 0x01;
}
}
data[pos++] = work;
}
}
totalRowCount++;
}
NSMutableData *command = nil;
if (compressionEnable)
{
NSString *portSettings = @"mini";
command = [SMPort generateBitImageCommand:byteWidth :24 :data :portSettings];
}
if (command != nil)
{
[someData appendData:command];
[command release];
}
else
{
u_int8_t imageBytes[] = {0x1b, 0x58, 0x34, 0, 24}; // [ESC X 4]
imageBytes[3] = byteWidth;
[someData appendBytes:imageBytes length:5];
[someData appendBytes:data length:sizeof(u_int8_t) * byteWidth * 24];
u_int8_t printBytes[] = {0x1b, 0x58, 0x32, 24};
[someData appendBytes:printBytes length:4];
}
free(data);
}
u_int8_t endingBytes[] = {0x0c,
0x1b, 0x4A, 0x78};
[someData appendBytes:endingBytes length:1 + 3];
free(pixels);
imageData = [[NSData alloc] initWithBytes:[someData mutableBytes] length:[someData length]];
[someData release];
return imageData;
}
u_int8_t PixelBrightness(u_int8_t red, u_int8_t green, u_int8_t blue)
{
int level = ((int)red + (int)green + (int)blue)/3;
return level;
}
u_int32_t PixelIndex(u_int32_t x, u_int32_t y, u_int32_t width)
{
return (x + (y * width));
}
-(NSData*)获取用于打印的图像最小数据:(BOOL)压缩启用页面模式启用:(BOOL)页面模式启用
{
如果(imageData!=nil)
{
返回图像数据;
}
CGImageRef cgImage=[m_图像cgImage];
int32_t width=CGImageGetWidth(cgImage);
int32_t height=CGImageGetHeight(cgImage);
ARGBPixel*像素=malloc(宽度*高度*大小(ARGBPixel));
操纵图像像素数据(cgImage,像素);
如果(抖动支持==真)
{
converttonochromesteinberthering(像素、宽度、高度,1.5);
}
如果(像素==NULL)
{
返回NULL;
}
int w=宽度/8;
如果((宽度%8)!=0)
w++;
int mWidth=w*8;
int字节宽度=mWidth/8;
NSMutableData*someData=[[NSMutableData alloc]init];
如果(页面模式启用)
{
u_int8_t beginingBytes[]={0x1b,0x40,
0x1b,0x4c,
//0x1b、0x57、0x00、0x00、0x00、0x00、mWidth%256、mWidth/256、高度%256、高度/256、,
0x1b,0x57,0x00,0x00,0x00,0x00,mWidth%256,mWidth/256,(高度+50)%256,(高度+50)/256,
0x1b,0x58,0x32,0x18};
[someData appendBytes:beginingBytes长度:2+2+10+4];
}
其他的
{
u_int8_t beginingBytes[]={0x1b,0x40};
[someData appendBytes:beginingBytes长度:2];
}
int totalRowCount=0;
while(总行数<高度)
{
u_int8_t*data=malloc(sizeof(u_int8_t)*字节宽度*24);
memset(数据,0,大小(u_int8_t)*字节宽度*24);
uint32_t pos=0;
对于(int y=0;y<24;y++)
{
if(总行数<高度)
{
for(int x=0;x 工作我看不到问题我编辑了问题。我想知道我是否能够从指针获取像素以及我将如何操作。您已经有了指向数据的指针,它由RequestImagePixels返回,这是一个指向数据的IntPtr。您可以使用Marshal.ReadXXX方法,也可以强制转换为字节*并对其进行操作那样。