Search code examples
c#.netimagematlabsystem.drawing

extract pixels from System.Drawing.Bitmap


I am using some .NET assembly from MATLAB which produces a System.Drawing.Bitmap object. I would like to get a MATLAB matrix with the pixels out of it. How do you do that?

I don't want to save the image to disk and then use imread.


Solution

  • Based on Jeroen's answer, here is the MATLAB code to do the conversion:

    % make sure the .NET assembly is loaded
    NET.addAssembly('System.Drawing');
    
    % read image from file as Bitmap
    bmp = System.Drawing.Bitmap(which('football.jpg'));
    w = bmp.Width;
    h = bmp.Height;
    
    % lock bitmap into memory for reading
    bmpData = bmp.LockBits(System.Drawing.Rectangle(0, 0, w, h), ...
        System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
    
    % get pointer to pixels, and copy RGB values into an array of bytes
    num = abs(bmpData.Stride) * h;
    bytes = NET.createArray('System.Byte', num);
    System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, bytes, 0, num);
    
    % unlock bitmap
    bmp.UnlockBits(bmpData);
    
    % cleanup
    clear bmp bmpData num
    
    % convert to MATLAB image
    bytes = uint8(bytes);
    img = permute(flipdim(reshape(reshape(bytes,3,w*h)',[w,h,3]),3),[2 1 3]);
    
    % show result
    imshow(img)
    

    The last statement can be hard to understand. It is in fact equivalent to the following:

    % bitmap RGB values are interleaved: b1,g1,r1,b2,g2,r2,...
    % and stored in a row-major order
    b = reshape(bytes(1:3:end), [w,h])';
    g = reshape(bytes(2:3:end), [w,h])';
    r = reshape(bytes(3:3:end), [w,h])';
    img = cat(3, r,g,b);
    

    The result:

    image