与IntPtr和Marshaling混淆到一个结构

时间:2014-02-07 23:50:51

标签: 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;
        };

我有一些代码(由here提供)将采用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

代码如下所示:

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;
}

此处有更多代码:

byte PixelBrightness(byte red, byte green, byte blue)
{
    int level = ((int)red + (int)green + (int)blue)/3;
        return (byte)level;
}

UInt32 PixelIndex(UInt32 x, UInt32 y, UInt32 width)
{
    return (UInt32)(x + (y * width));
}

此时我完全感到困惑。我只是希望能够得到像素,以便知道亮度是多少,这将决定我的字节数组中的下一个序列作为命令提供给我的打印机......

如果这有帮助......这里是我想要更改的目标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));
}

我的问题是如何从指针中获取结构数组(像素) - 所以我想将一个点更改为一个结构数组?

0 个答案:

没有答案