DotNetNewsgroup.com  
web access to complete list of Microsoft.NET newsgroups
   home   |   control panel login   |   archive  |  
 
  carried group
academic
adonet
aspnet
aspnet.announcements
aspnet.buildingcontrols
aspnet.caching
aspnet.datagridcontrol
aspnet.mobile
aspnet.security
aspnet.webcontrols
aspnet.webservices
assignment_manager
datatools
dotnet.distributed_apps
dotnet.general
dotnet.myservices
dotnet.nternationalization
dotnet.scripting
dotnet.security
dotnet.vjsharp
dotnet.vsa
dotnet.xml
dotnetfaqs
framework
framework.clr
framework.compactframework
framework.component_services
framework.controls
framework.databinding
framework.drawing
framework.enhancements
framework.interop
framework.odbcnet
framework.performance
framework.remoting
framework.sdk
framework.setup
framework.webservices
framework.windowsforms
framework.wmi
frwk.windowsforms.designtime
lang.csharp
lang.jscript
lang.vb
lang.vb.controls
lang.vb.data
lang.vb.upgrade
lang.vc
lang.vc.libraries
  
 
start date: Mon, 30 Jul 2007 11:30:02 -0700,    posted on: microsoft.public.dotnet.framework.drawing        back       

Thread Index
  1    Brian
          2    Michael Phillips, Jr. 0.c0m
          3    Michael C
                 4    Brian
                 5    Michael C
                 6    Brian
                        7    Michael Phillips, Jr. 0.c0m
                        8    Karsten Sosna
                               9    Brian
                 10    Karsten Sosna
                 11    Michael Phillips, Jr. 0.c0m
                 12    Brian


Raw RGB pixel data into a bitmap   
Hello there,

I have a 2-dimensional byte array of RGB pixel data.  The first dimension is 
the image width * 3, and the second is the image height.   The format is as 
follows:

R1G1B1R2G2B2..... etc. for each line in the image.

I've been searching for an easy fast way to get the 2-dimensional array into 
a Bitmap or Image class so I can easily save it.  

I first tried converting the byte array to a memorystream, but the 
memorystream requires a 1-dimensional array.  Then I found out that it may 
need the header information.  I'm getting a bit confused and possibly over my 
head.  

So my basic question is how to create a Bitmap/Image in memory using a 
2-dimensional byte array of RGB values.  

Any help would be greatly appreciated.  I've been googling for a couple days 
now, and I am more confused than when I started.  

Thanks,

-Brian
Date:Mon, 30 Jul 2007 11:30:02 -0700   Author:  

Re: Raw RGB pixel data into a bitmap   

> So my basic question is how to create a Bitmap/Image in memory using a
> 2-dimensional byte array of RGB values.


1) Create a MemoryStream.
  Since a bitmap is aligned on an unsigned integer boundary you need to 
allocate the necessary padding between scanlines.
  The memory layout of a bitmap is as follows:
    BITMAPFILEHEADER 14 bytes
    BITMAPINFOHEADER 40 bytes
    Color Table, if any... number of colors * 4 bytes
    or bitfield array of 3 unsigned integers if your image uses RGB masks.
    Bitmap's bits<----------1st scanline points to bottom of bitmap
3) After filling in the appropriate headers, write them to your stream
4) Now create a loop where you copy your RGB data one scanline at a time.
    Assuming your image is 24bpp, copy width*3 bytes each scanline, pad when 
necessary to fill out the unsigned integer aligned scanline boundary.
5) After you have finished with your stream, rewind it.
6) You now have a bitmap that is ready to be saved with the 
Bitmap.Save(MemoryStream) method

"Brian"  wrote in message 
news:0CFA3B85-39F1-4152-8D32-E579C7A311C7@microsoft.com...

> Hello there,
>
> I have a 2-dimensional byte array of RGB pixel data.  The first dimension 
> is
> the image width * 3, and the second is the image height.   The format is 
> as
> follows:
>
> R1G1B1R2G2B2..... etc. for each line in the image.
>
> I've been searching for an easy fast way to get the 2-dimensional array 
> into
> a Bitmap or Image class so I can easily save it.
>
> I first tried converting the byte array to a memorystream, but the
> memorystream requires a 1-dimensional array.  Then I found out that it may
> need the header information.  I'm getting a bit confused and possibly over 
> my
> head.
>
> So my basic question is how to create a Bitmap/Image in memory using a
> 2-dimensional byte array of RGB values.
>
> Any help would be greatly appreciated.  I've been googling for a couple 
> days
> now, and I am more confused than when I started.
>
> Thanks,
>
> -Brian 
Date:Mon, 30 Jul 2007 14:55:03 -0400   Author:  

Re: Raw RGB pixel data into a bitmap   
"Brian"  wrote in message 
news:0CFA3B85-39F1-4152-8D32-E579C7A311C7@microsoft.com...

> Hello there,
>
> I have a 2-dimensional byte array of RGB pixel data.  The first dimension 
> is
> the image width * 3, and the second is the image height.   The format is 
> as
> follows:
>
> R1G1B1R2G2B2..... etc. for each line in the image.
>
> I've been searching for an easy fast way to get the 2-dimensional array 
> into
> a Bitmap or Image class so I can easily save it.
>
> I first tried converting the byte array to a memorystream, but the
> memorystream requires a 1-dimensional array.  Then I found out that it may
> need the header information.  I'm getting a bit confused and possibly over 
> my
> head.
>
> So my basic question is how to create a Bitmap/Image in memory using a
> 2-dimensional byte array of RGB values.
>
> Any help would be greatly appreciated.  I've been googling for a couple 
> days
> now, and I am more confused than when I started.


Hi Brian,

Memory stream is not the way to go IMO. Instead, have a look into help on 
the Bitmap.LockBits function. The basic steps would be:

1) Create a Bitmap of appropriate size and color depth.
2) Call LockBits
3) Copy data into bitmap from array
4) Call UnlockBits
5) You're done

If you're using C# this is easier because it supports points but it will 
still work in VB just fine using Marshal.Copy (from memory).

Michael
Date:Tue, 31 Jul 2007 12:02:53 +1000   Author:  

Re: Raw RGB pixel data into a bitmap   
Thanks to both of you!  I'll look into the header information and into 
Lockbits.  I've been reading a bunch on Lockbits being the way to go for fast 
image operations.  Every example I read though used an image that was already 
in existence.  I'll have to find an example of creating the header 
information.  And yes, I'm doing this in VB, not C#.  

Thanks again,

-Brian
Date:Tue, 31 Jul 2007 04:30:01 -0700   Author:  

Re: Raw RGB pixel data into a bitmap   
"Brian"  wrote in message 
news:C199889A-8B53-431B-823E-3607D3856459@microsoft.com...

> Thanks to both of you!  I'll look into the header information and into
> Lockbits.  I've been reading a bunch on Lockbits being the way to go for 
> fast
> image operations.  Every example I read though used an image that was 
> already
> in existence.  I'll have to find an example of creating the header
> information.  And yes, I'm doing this in VB, not C#.


For your particular case it doesn't matter that you're using VB. With C# you 
can use pointers and avoid copying the bitmap data to an array but because 
your data is already in an array it doesn't matter.

Michael
Date:Wed, 1 Aug 2007 11:17:00 +1000   Author:  

Re: Raw RGB pixel data into a bitmap   
"Michael C" wrote:

> For your particular case it doesn't matter that you're using VB. With C# you 
> can use pointers and avoid copying the bitmap data to an array but because 
> your data is already in an array it doesn't matter.
> 
> Michael 


Ok . . . I think I'm getting somewhere now.  Thanks again.  

Here's my fuction:

Imports System.Drawing
Imports System.Runtime.InteropServices

    Public Function saveImages(ByVal inBuf(,,) As Byte) As Boolean

        Dim bmp As New Bitmap((inBuf.GetUpperBound(1) + 1) / 3, 
inBuf.GetUpperBound(2) + 1, Imaging.PixelFormat.Format24bppRgb)
        Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
        Dim bmpData As Imaging.BitmapData = bmp.LockBits(rect, 
Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)
        Dim ptr As IntPtr = bmpData.Scan0

        Dim bytes As Long = bmp.Width * bmp.Height * 3
        Dim rgbValues(bytes - 1) As Byte
        Dim intIndex As Long = 0

        For i As Integer = 0 To inBuf.GetUpperBound(1)
            For j As Integer = 0 To inBuf.GetUpperBound(2)
                rgbValues(intIndex) = inBuf(0, i, j)
                intIndex += 1
            Next
        Next

        Marshal.Copy(rgbValues, 0, ptr, bytes)

        bmp.UnlockBits(bmpData)

        bmp.Save("C:\testSave.jpg", Imaging.ImageFormat.Jpeg)

    End Function

I am actually using a 3-dimensional array.  It's basically an array of 
multiple images' RGB data "inBuf(#images, Width*3, Height)".  But for testing 
purposes, I'm only referencing the 1st image.  Again, the 2nd dimension is 
the image width * 3, and the 3rd dimension is the image height.  

Here's the problem.  I'm getting an image, but the colors are off.  It's 
almost like it's missing a channel, or that it's putting the RGB values in 
the wrong place.  I can't quite figure out what's going on.  Here are the two 
images:  The original: http://www.jfreitasphotography.com/Temp/original.jpg  
This is where I get 3-dimensional array from.  After the function I get this: 
http://www.jfreitasphotography.com/Temp/fromFunction.jpg 

When I step through the code, everything looks good until after the save.  
The first value in the rgbValues byte array is the the Red pixel value of the 
first pixel in the original image.  But after the save, you can see that the 
first pixel in the new image is not the same number.  

So I'm guessing this would be related to the header info again?  Or is there 
some sort of padding that I'm missing.  I was kind of assuming that the 
header info was taken care of with the new Bitmap declaration.
Date:Wed, 1 Aug 2007 05:26:06 -0700   Author:  

Re: Raw RGB pixel data into a bitmap   
I do not know how your pixels are organized in the original raw data but 
when you copy them
to the System.Drawing.Bitmap the pixels need to be in byte order,  Blue, 
Green, Red for each scanline in a 24bpp bitmap.

"Brian"  wrote in message 
news:04D38177-B1D6-436F-89C3-A4ECDECCB41D@microsoft.com...

>
> "Michael C" wrote:
>> For your particular case it doesn't matter that you're using VB. With C# 
>> you
>> can use pointers and avoid copying the bitmap data to an array but 
>> because
>> your data is already in an array it doesn't matter.
>>
>> Michael
>
> Ok . . . I think I'm getting somewhere now.  Thanks again.
>
> Here's my fuction:
>
> Imports System.Drawing
> Imports System.Runtime.InteropServices
>
>    Public Function saveImages(ByVal inBuf(,,) As Byte) As Boolean
>
>        Dim bmp As New Bitmap((inBuf.GetUpperBound(1) + 1) / 3,
> inBuf.GetUpperBound(2) + 1, Imaging.PixelFormat.Format24bppRgb)
>        Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
>        Dim bmpData As Imaging.BitmapData = bmp.LockBits(rect,
> Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)
>        Dim ptr As IntPtr = bmpData.Scan0
>
>        Dim bytes As Long = bmp.Width * bmp.Height * 3
>        Dim rgbValues(bytes - 1) As Byte
>        Dim intIndex As Long = 0
>
>        For i As Integer = 0 To inBuf.GetUpperBound(1)
>            For j As Integer = 0 To inBuf.GetUpperBound(2)
>                rgbValues(intIndex) = inBuf(0, i, j)
>                intIndex += 1
>            Next
>        Next
>
>        Marshal.Copy(rgbValues, 0, ptr, bytes)
>
>        bmp.UnlockBits(bmpData)
>
>        bmp.Save("C:\testSave.jpg", Imaging.ImageFormat.Jpeg)
>
>    End Function
>
> I am actually using a 3-dimensional array.  It's basically an array of
> multiple images' RGB data "inBuf(#images, Width*3, Height)".  But for 
> testing
> purposes, I'm only referencing the 1st image.  Again, the 2nd dimension is
> the image width * 3, and the 3rd dimension is the image height.
>
> Here's the problem.  I'm getting an image, but the colors are off.  It's
> almost like it's missing a channel, or that it's putting the RGB values in
> the wrong place.  I can't quite figure out what's going on.  Here are the 
> two
> images:  The original: 
> http://www.jfreitasphotography.com/Temp/original.jpg
> This is where I get 3-dimensional array from.  After the function I get 
> this:
> http://www.jfreitasphotography.com/Temp/fromFunction.jpg
>
> When I step through the code, everything looks good until after the save.
> The first value in the rgbValues byte array is the the Red pixel value of 
> the
> first pixel in the original image.  But after the save, you can see that 
> the
> first pixel in the new image is not the same number.
>
> So I'm guessing this would be related to the header info again?  Or is 
> there
> some sort of padding that I'm missing.  I was kind of assuming that the
> header info was taken care of with the new Bitmap declaration. 
Date:Wed, 1 Aug 2007 14:48:22 -0400   Author:  

Re: Raw RGB pixel data into a bitmap   

>        Dim bmp As New Bitmap((inBuf.GetUpperBound(1) + 1) / 3,
> inBuf.GetUpperBound(2) + 1, Imaging.PixelFormat.Format24bppRgb)
>        Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
>        Dim bmpData As Imaging.BitmapData = bmp.LockBits(rect,
> Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)
>        Dim ptr As IntPtr = bmpData.Scan0
>
>        Dim bytes As Long = bmp.Width * bmp.Height * 3
>        Dim rgbValues(bytes - 1) As Byte

Brian,
you have a 24Bit-Bitmap. The BitMapData have an alignment of 4 each line. 
Now if you have a bitmap with 1x1 pixel, the BitMapData.Stride will need 4 
bytes instead of 3 bytes. But your rgbValues-Array is too short. In Example: 
A 24Bit-Bitmap(10x50 pixel) will need 10 * 3 = 30 bytes <<Alignment to 4 = 
32 bytes each line. With 50 lines vou need 50 * 32 = 1600 bytes. But you 
calculate 10 * 3 * 50 = 1500 bytes. Now correct is:
\\\
Dim rgbValues(bmpData.Stride * bmpData.Height - 1) As Byte
///


>        For i As Integer = 0 To inBuf.GetUpperBound(1)
>            For j As Integer = 0 To inBuf.GetUpperBound(2)
>                rgbValues(intIndex) = inBuf(0, i, j)
>                intIndex += 1
>            Next
>        Next


This is an accident that this code works a little bit. The reason is your 
image is 640 pixel width. 640 * 3 = 1920 bytes/ line. 1920 Mod 4 = 0 >> No 
alignment needed. You can control that, if you take a look to 
bmpData.Stride-Property, it must be set to 1920. Untested:
\\\
Dim align As Integer = bmpData.Stride - bmpData.Width * 3
For i As Integer = 0 To inBuf.GetUpperBound(1)
    For j As Integer = 0 To inBuf.GetUpperBound(2)
        rgbValues(intIndex) = inBuf(0, i, j)
        intIndex += 1
    Next
    intIndex += align
Next
///


> Here's the problem.  I'm getting an image, but the colors are off.  It's
> almost like it's missing a channel, or that it's putting the RGB values in
> the wrong place.  I can't quite figure out what's going on.  Here are the 
> two
> images:  The original: 
> http://www.jfreitasphotography.com/Temp/original.jpg
> This is where I get 3-dimensional array from.  After the function I get 
> this:
> http://www.jfreitasphotography.com/Temp/fromFunction.jpg


This comes form the order of colors in the array B, G, R, B, G, R,..., not 
R, G, B. For 32BitbppArgb i.e.is the order B, G, R, A not A, R, G , B.

Excuse my bad engilish.
--
Regards Karsten
Date:Thu, 2 Aug 2007 08:53:56 +0200   Author:  

Re: Raw RGB pixel data into a bitmap   
Awesome!!  Thanks for the help guys!  It's working like a charm.

I knew I was getting into some programming that I'm a little unfamiliar with 
.. . . bitmaps, padding, stride . . . etc.  But I think I get it now.  

Now why would they make the bitmap class GRB . . . not RGB??  I'm sure 
there's a reason, but it doesn't seem logical.  

Anyway, for the record, here's my function now that works:

Imports System.Drawing
Imports System.Runtime.InteropServices

    Public Function saveImages(ByVal inBuf(,,) As Byte) As Boolean

        Dim bmp As New Bitmap((inBuf.GetUpperBound(1) + 1) / 3, 
inBuf.GetUpperBound(2) + 1, Imaging.PixelFormat.Format24bppRgb)
        Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
        Dim bmpData As Imaging.BitmapData = bmp.LockBits(rect, 
Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)
        Dim ptr As IntPtr = bmpData.Scan0
        Dim bytes As Long = bmpData.Stride * bmpData.Height - 1
        Dim rgbValues(bmpData.Stride * bmpData.Height - 1) As Byte
        Dim intIndex As Long = 0

        Dim align As Integer = bmpData.Stride - bmpData.Width * 3
        For i As Integer = 0 To inBuf.GetUpperBound(1)
            For j As Integer = 0 To inBuf.GetUpperBound(2) Step 3
                rgbValues(intIndex) = inBuf(0, i, j + 2)
                rgbValues(intIndex + 1) = inBuf(0, i, j + 1)
                rgbValues(intIndex + 2) = inBuf(0, i, j)
                intIndex += 3
            Next
            intIndex += align
        Next

        Marshal.Copy(rgbValues, 0, ptr, bytes)
        bmp.UnlockBits(bmpData)
        bmp.Save("C:\testSave.jpg", Imaging.ImageFormat.Jpeg)
    End Function



Thank's again!

-Brian
Date:Thu, 2 Aug 2007 05:48:03 -0700   Author:  

Re: Raw RGB pixel data into a bitmap   

> Now why would they make the bitmap class GRB . . . not RGB??  I'm sure
> there's a reason, but it doesn't seem logical.


Hello Brian,
not GRB, BGR!
It's logical. Colors are stored with 32 Bits. If you have A, R, G, B it was 
stored as Int32 in format Low-Word, High Word, Low Byte, High Byte. If you 
have a color no trancpareny(&FF),  Red(&H80), Green(&H40), Blue(&H20) it was 
&HFF804020. Stored in the memory it is &204080FF. Now you copy the 
memoryblock to the bytearray then is arr(index + 0) = &H20(Blue),arr (index 
+ 1) = &H40(Green), arr(index + 2) = &H80(Red),arr (index + 3) = 
&HFF(Alpha). Analog to 24Bit the Format is &HFFrrggbb, stored in memory it 
is bbggrr because the alphachannel are ignored.
--
Regards Karsten
Date:Fri, 3 Aug 2007 06:09:32 +0200   Author:  

Re: Raw RGB pixel data into a bitmap   

> Now why would they make the bitmap class GRB . . . not RGB??  I'm sure
> there's a reason, but it doesn't seem logical.


In the Window's 3.1 Bitmap Specification, the bitmap is upside down.

The first scanline's first pixel is the bottom right of the bitmap.

The last scanline's last pixel is the top left of your bitmap.

Each pixel is BGR in memory.

If you look at the bitmap in your mind as if it righted itself,  each pixel 
is RGB.
Date:Fri, 3 Aug 2007 12:20:21 -0400   Author:  

Re: Raw RGB pixel data into a bitmap   
"Karsten Sosna" wrote:

> Hello Brian,
> not GRB, BGR!
> It's logical. Colors are stored with 32 Bits. If you have A, R, G, B it was 
> stored as Int32 in format Low-Word, High Word, Low Byte, High Byte. If you 
> have a color no trancpareny(&FF),  Red(&H80), Green(&H40), Blue(&H20) it was 
> &HFF804020. Stored in the memory it is &204080FF. Now you copy the 
> memoryblock to the bytearray then is arr(index + 0) = &H20(Blue),arr (index 
> + 1) = &H40(Green), arr(index + 2) = &H80(Red),arr (index + 3) = 
> &HFF(Alpha). Analog to 24Bit the Format is &HFFrrggbb, stored in memory it 
> is bbggrr because the alphachannel are ignored.
> --
> Regards Karsten


GRB!  That's what I meant.  :-)

Thanks for the explanation.  I figured it had something to do with how they 
were stored in memory.  

-Brian
Date:Fri, 3 Aug 2007 10:18:05 -0700   Author:  

Google
 
Web dotnetnewsgroup.com


COPYRIGHT ?2005, EUROFRONT WORLDWIDE LTD., ALL RIGHT RESERVE  |   Contact us