NSBitmapImageRep from scratch?

JohnErnestJohnErnest USMember ✭✭

I have an RGBA array of pixels from an image embedded in a PDF that I want to convert over to a PNG at runtime.

I try this method but I get errors on rep.SetColorAt(color, x, y) that the colorspace is -1 when it shouldn't be and so no pixels are written. Any ideas?

        private NSData ImageToNSData(ParsePdf.Image image)
        {
            var colorSpace = CGColorSpace.CreateDeviceRGB();
            CGBitmapContext ctx = new CGBitmapContext(IntPtr.Zero, image.Width, image.Height, 8, image.Width * 4, colorSpace, CGImageAlphaInfo.PremultipliedLast);
            NSBitmapImageRep rep = new NSBitmapImageRep(ctx.ToImage());

            for (int y=0;y<image.Height;y++)
            {
                for (int x=0;x<image.Width;x++)
                {
                    ParsePdf.ByteColor bcolor = image.Pixels[x, y];
                    NSColor color = NSColor.FromRgba(bcolor.R, bcolor.G, bcolor.B, bcolor.A);
                    rep.SetColorAt(color, x, y);
                }
            }

            NSData data = rep.RepresentationUsingTypeProperties(NSBitmapImageFileType.Png);
            return data;
        }
Tagged:

Best Answer

  • JohnErnestJohnErnest US ✭✭
    Accepted Answer

    Thanks Chris, I managed to get it working yesterday. Initializing CGBitmapContext with an IntPtr.Zero fails with Xamarin Mac, unlike the stack exchanges mention. It will tell me something like the colorspace is -1.

    Here instead I create an RGBA byte[] with the image data from the PDF and pass it to CGBitmapContext and it works, then I can return a Png from an image made from scratch..

            private NSData ImageToNSData(ParsePdf.Image image)
            {
                CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB();
                byte[] bdata = new byte[image.Width * image.Height * 4];
                int counter = 0;
                for (int y=0;y<image.Height;y++)
                {
                    for (int x=0;x<image.Width;x++)
                    {
                        bdata[counter] = image.Pixels[x, y].R;
                        bdata[counter+1] = image.Pixels[x, y].G;
                        bdata[counter+2] = image.Pixels[x, y].B;
                        bdata[counter+3] = image.Pixels[x, y].A;
                        counter += 4;
                    }
                }
                CGBitmapContext ctx = new CGBitmapContext(bdata, image.Width, image.Height, 8, image.Width * 4, colorSpace, CGImageAlphaInfo.PremultipliedLast);
                CGImage img = ctx.ToImage();
                NSBitmapImageRep rep = new NSBitmapImageRep(img);
                NSData newdata = rep.RepresentationUsingTypeProperties(NSBitmapImageFileType.Png);
                return newdata;
            }
    

    Except that I realized last night that Inkscape doesn't save PDFs right at all from an SVG with blurring effects, which is a bummer, and SkiaSharp doesn't support feGaussianBlur yet, which is an egregious bummer also.

Answers

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Maybe something like this answers your question?

    https://stackoverflow.com/questions/12799920/drawing-on-nsbitmapimagerep

    https://stackoverflow.com/a/7446993/36782

    I don't have specific details on drawing, but searching for "cocoa NSBitmapImageRep drawing" came up with a number of possible stack overflow questions.

  • JohnErnestJohnErnest USMember ✭✭
    Accepted Answer

    Thanks Chris, I managed to get it working yesterday. Initializing CGBitmapContext with an IntPtr.Zero fails with Xamarin Mac, unlike the stack exchanges mention. It will tell me something like the colorspace is -1.

    Here instead I create an RGBA byte[] with the image data from the PDF and pass it to CGBitmapContext and it works, then I can return a Png from an image made from scratch..

            private NSData ImageToNSData(ParsePdf.Image image)
            {
                CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB();
                byte[] bdata = new byte[image.Width * image.Height * 4];
                int counter = 0;
                for (int y=0;y<image.Height;y++)
                {
                    for (int x=0;x<image.Width;x++)
                    {
                        bdata[counter] = image.Pixels[x, y].R;
                        bdata[counter+1] = image.Pixels[x, y].G;
                        bdata[counter+2] = image.Pixels[x, y].B;
                        bdata[counter+3] = image.Pixels[x, y].A;
                        counter += 4;
                    }
                }
                CGBitmapContext ctx = new CGBitmapContext(bdata, image.Width, image.Height, 8, image.Width * 4, colorSpace, CGImageAlphaInfo.PremultipliedLast);
                CGImage img = ctx.ToImage();
                NSBitmapImageRep rep = new NSBitmapImageRep(img);
                NSData newdata = rep.RepresentationUsingTypeProperties(NSBitmapImageFileType.Png);
                return newdata;
            }
    

    Except that I realized last night that Inkscape doesn't save PDFs right at all from an SVG with blurring effects, which is a bummer, and SkiaSharp doesn't support feGaussianBlur yet, which is an egregious bummer also.

Sign In or Register to comment.