The ColorPalette class has no constructor so how does one use it?
I define a variable by:
Dim cp as ColorPalette
but don't know how assign an object to the variable.
Thanks in advance
Jul 14 '07
19 2436
Have a look at http://www.codeproject.com/cs/media/...essing_Lab.asp
To create a grayscale image from a 256-color image, he creates
a new 8-bit image of the same size as the original, sets the Palette
values of the new image to 0,0,0 1,1,1 2,2,2 ... 255,255,255,
then proceeds to set the pixel data of the new image by calculating
the intensities of the original image.
It would have been much faster had he just modified the palette
entries of the original image.
I made another test (create a new Windows application project):
---snip---
Private _bm As Bitmap
Private Sub Form1_Load(ByVa l sender As System.Object, ByVal e As
System.EventArg s) Handles MyBase.Load
Test2()
End Sub
Private Sub Test2()
Dim lena8 As New Bitmap("d:\lena 8.bmp")
SetGrayscalePal ette(lena8)
_bm = lena8
lena8.Save("d:\ lena8-gray.bmp",
System.Drawing. Imaging.ImageFo rmat.Bmp)
End Sub
Public Shared Sub SetGrayscalePal ette(ByVal image As Bitmap)
If (image.PixelFor mat <PixelFormat.Fo rmat8bppIndexed ) Then
Throw New ArgumentExcepti on
End If
Dim palette As ColorPalette = image.Palette
Dim i As Integer
For i = 0 To &H100 - 1
'palette.Entrie s(i) = Color.FromArgb( i, i, i)
Dim original As Color = palette.Entries (i)
Dim gray As Integer = CType((original .G * 4 + original.R *
2 + original.B) / 7, Integer)
palette.Entries (i) = Color.FromArgb( gray, gray, gray)
Next i
image.Palette = palette
End Sub
Private Sub Form1_Paint(ByV al sender As Object, ByVal e As
System.Windows. Forms.PaintEven tArgs) Handles Me.Paint
If _bm Is Nothing Then
Exit Sub
End If
e.Graphics.Draw Image(_bm, 0, 0, _bm.Width, _bm.Height)
End Sub
---snip---
(Yes, I know that (G*4+R*2+B)/7 is simplistic and incorrect)
You will notice that the palette entries actually have changed when
the image is painted on the form, but the saved copy retains the
original colors.
If we were to paint the image from the code above onto a 24-bit
bitmap and save it, we get a nice grayscale image, albeit 24-bit:
---snip---
Dim dst As New Bitmap(lena8.Wi dth, lena8.Height,
PixelFormat.For mat24bppRgb)
Dim g As Graphics = Graphics.FromIm age(dst)
g.DrawImage(len a8, 0, 0, dst.Width, dst.Height)
g.Dispose()
dst.Save("d:\ds t.bmp", ImageFormat.Bmp )
---snip---
(it is not possible to create a Graphics object from an indexed
image).
I have not spent any time digging into why the original palette
is used when saving an indexed image, but as I mentioned in the
other post, I use an imaging library myself (LeadTools).
Perhaps the link at the top might give you a few ideas of how
to go about this in an entirely different way.
Regards,
Joergen Bech
On Sat, 14 Jul 2007 21:37:24 -0400, " active"
<ac********** @a-znet.comwrote:
>What was MS thinking? Why not make Entries readonly? I add a statement to yout code: The line written did not reflect i,i,i
lena8.Palette. Entries(i) = Color.FromArgb( i, i, i)
Console.WriteL ine("Entry({0} = {1}", i, lena8.Palette.E ntries(i))
"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNO SPAMwrote in message news:5n******* *************** **********@4ax. com...
>> My suggestion was that if you needed a class with the same behavior as ColorPalette, but with a few changes, you could just copy the code from the ColorPalette class to another class with the name and additional functionality of your choice. There are various tools for decompiling the framework.
But if you need to assign a ColorPalette object to a property that expects the type found in the framework, this might not be an option.
As for assigning a palette from a dummy palette indirectly created by creating a new bitmap of the same bit depth: No can do.
MyBitmap.Palet te = <ColorPalette object>
is not the same as
MyBitmap.Palet te = <some other bitmap>.Palette .
In the latter case, you are going through some GDI+ functions to get a new palette rather than just getting a ColorPalette object directly.
When assigned to MyBitmap.Palett e, you are jumping through similar hoops.
Try the code below. You will find that nothing works as expected. All copies are identical to the original. Attempts to change the colors in any of these manners are ignored.
I use an imaging toolkit for similar needs, so I haven't digged deeper into this. There might be a solution. Then again, there might not. It is possible that Microsoft has made it *possible* to change the Palette.Entrie s values, but not *intended* for them to be changed or react to such changes.
Please prove me wrong.
Regards,
Joergen Bech
---snip---
'Load image Dim lena8 As New Bitmap("d:\lena 8.bmp")
'Save it again to verify that we read it correctly lena8.Save("d:\ lena8-original.bmp", System.Drawing .Imaging.ImageF ormat.Bmp)
'Work with a palette created as a copy of the palette of the original image Dim cp As ColorPalette = lena8.Palette
For i As Integer = 0 To 255 cp.Entries(i) = Color.FromArgb( i, i, i) Next lena8.Palette = cp lena8.Save("d:\ lena8-cp.bmp", System.Drawing .Imaging.ImageF ormat.Bmp)
'Work with a dummy palette created by creating another bitmap Dim bm As New Bitmap(1, 1, PixelFormat.For mat8bppIndexed) For i As Integer = 0 To 255 bm.Palette.Entr ies(i) = Color.FromArgb( i, i, i) Next lena8.Palette = bm.Palette lena8.Save("d:\ lena8-bm.bmp", System.Drawing .Imaging.ImageF ormat.Bmp)
'Modify palette entries directly in the original image For i As Integer = 0 To 255 lena8.Palette.E ntries(i) = Color.FromArgb( i, i, i) Next lena8.Save("d:\ lena8-0-255.bmp", System.Drawing .Imaging.ImageF ormat.Bmp)
---snip---
On Sat, 14 Jul 2007 17:31:09 -0400, " active" <ac**********@ a-znet.comwrote:
>>>For each entry: get an entry from a Bitmap color table modify it store the modified entry in a color table
Assign the new color table to the bitmap.
So I think I can do what the other posters suggested.
But I would like to know what you meant by the following. Just copy the class to MyColorPalette
Thanks
How dose powell get a way with this.
It works including saving to a file.
The last line I show he is inserting a color table into a Bitmap!
He then inserts the bitmap data.
Isn't this what we are saying can't be effective?
Thanks if you can explain this
Private Sub panel1_Click(.. .
'Creates a new GIF image with a modified colour palette
If Not (cp Is Nothing) Then
'Create a new 8 bit per pixel image
Dim bm As New Bitmap(_gifImag e.Width, _gifImage.Heigh t,
PixelFormat.For mat8bppIndexed)
'get it's palette
Dim ncp As ColorPalette = bm.Palette
'copy all the entries from the old palette removing any transparency
Dim n As Integer = 0
Dim c As Color
For Each c In cp.Entries
ncp.Entries(n) = Color.FromArgb( 255, c)
n += 1
Next c
'Set the newly selected transparency
ncp.Entries(Cur rentEntry) = Color.FromArgb( 0,
cp.Entries(Curr entEntry))
're-insert the palette
bm.Palette = ncp
"Joergen Bech @ post1.tele.dk>" wrote:
>
Have a look at http://www.codeproject.com/cs/media/...essing_Lab.asp
To create a grayscale image from a 256-color image, he creates
a new 8-bit image of the same size as the original, sets the Palette
values of the new image to 0,0,0 1,1,1 2,2,2 ... 255,255,255,
then proceeds to set the pixel data of the new image by calculating
the intensities of the original image.
It would have been much faster had he just modified the palette
entries of the original image.
I made another test (create a new Windows application project):
---snip---
Private _bm As Bitmap
Private Sub Form1_Load(ByVa l sender As System.Object, ByVal e As
System.EventArg s) Handles MyBase.Load
Test2()
End Sub
Private Sub Test2()
Dim lena8 As New Bitmap("d:\lena 8.bmp")
SetGrayscalePal ette(lena8)
_bm = lena8
lena8.Save("d:\ lena8-gray.bmp",
System.Drawing. Imaging.ImageFo rmat.Bmp)
End Sub
Public Shared Sub SetGrayscalePal ette(ByVal image As Bitmap)
If (image.PixelFor mat <PixelFormat.Fo rmat8bppIndexed ) Then
Throw New ArgumentExcepti on
End If
Dim palette As ColorPalette = image.Palette
Dim i As Integer
For i = 0 To &H100 - 1
'palette.Entrie s(i) = Color.FromArgb( i, i, i)
Dim original As Color = palette.Entries (i)
Dim gray As Integer = CType((original .G * 4 + original.R *
2 + original.B) / 7, Integer)
palette.Entries (i) = Color.FromArgb( gray, gray, gray)
Next i
image.Palette = palette
End Sub
Private Sub Form1_Paint(ByV al sender As Object, ByVal e As
System.Windows. Forms.PaintEven tArgs) Handles Me.Paint
If _bm Is Nothing Then
Exit Sub
End If
e.Graphics.Draw Image(_bm, 0, 0, _bm.Width, _bm.Height)
End Sub
---snip---
(Yes, I know that (G*4+R*2+B)/7 is simplistic and incorrect)
You will notice that the palette entries actually have changed when
the image is painted on the form, but the saved copy retains the
original colors.
If we were to paint the image from the code above onto a 24-bit
bitmap and save it, we get a nice grayscale image, albeit 24-bit:
---snip---
Dim dst As New Bitmap(lena8.Wi dth, lena8.Height,
PixelFormat.For mat24bppRgb)
Dim g As Graphics = Graphics.FromIm age(dst)
g.DrawImage(len a8, 0, 0, dst.Width, dst.Height)
g.Dispose()
dst.Save("d:\ds t.bmp", ImageFormat.Bmp )
---snip---
(it is not possible to create a Graphics object from an indexed
image).
I have not spent any time digging into why the original palette
is used when saving an indexed image, but as I mentioned in the
other post, I use an imaging library myself (LeadTools).
Perhaps the link at the top might give you a few ideas of how
to go about this in an entirely different way.
Regards,
Joergen Bech
On Sat, 14 Jul 2007 21:37:24 -0400, " active"
<ac********** @a-znet.comwrote:
What was MS thinking?
Why not make Entries readonly?
I add a statement to yout code:
The line written did not reflect i,i,i
lena8.Palette.E ntries(i) = Color.FromArgb( i, i, i)
Console.WriteLi ne("Entry({0} = {1}", i, lena8.Palette.E ntries(i))
"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNO SPAMwrote in message
news:5n******** *************** *********@4ax.c om...
>
My suggestion was that if you needed a class
with the same behavior as ColorPalette, but with
a few changes, you could just copy the code from
the ColorPalette class to another class with the
name and additional functionality of your choice.
There are various tools for decompiling the framework.
But if you need to assign a ColorPalette object
to a property that expects the type found in the
framework, this might not be an option.
As for assigning a palette from a dummy palette
indirectly created by creating a new bitmap of the
same bit depth: No can do.
MyBitmap.Palett e = <ColorPalette object>
is not the same as
MyBitmap.Palett e = <some other bitmap>.Palette .
In the latter case, you are going through some
GDI+ functions to get a new palette rather than
just getting a ColorPalette object directly.
When assigned to MyBitmap.Palett e, you are
jumping through similar hoops.
Try the code below. You will find that nothing
works as expected. All copies are identical to
the original. Attempts to change the colors in
any of these manners are ignored.
I use an imaging toolkit for similar needs, so I
haven't digged deeper into this. There might be
a solution. Then again, there might not. It is possible
that Microsoft has made it *possible* to change the
Palette.Entries values, but not *intended* for them
to be changed or react to such changes.
Please prove me wrong.
Regards,
Joergen Bech
---snip---
'Load image
Dim lena8 As New Bitmap("d:\lena 8.bmp")
'Save it again to verify that we read it correctly
lena8.Save("d:\ lena8-original.bmp",
System.Drawing. Imaging.ImageFo rmat.Bmp)
'Work with a palette created as a copy of the palette of the
original image
Dim cp As ColorPalette = lena8.Palette
For i As Integer = 0 To 255
cp.Entries(i) = Color.FromArgb( i, i, i)
Next
lena8.Palette = cp
lena8.Save("d:\ lena8-cp.bmp",
System.Drawing. Imaging.ImageFo rmat.Bmp)
'Work with a dummy palette created by creating another bitmap
Dim bm As New Bitmap(1, 1, PixelFormat.For mat8bppIndexed)
For i As Integer = 0 To 255
bm.Palette.Entr ies(i) = Color.FromArgb( i, i, i)
Next
lena8.Palette = bm.Palette
lena8.Save("d:\ lena8-bm.bmp",
System.Drawing. Imaging.ImageFo rmat.Bmp)
'Modify palette entries directly in the original image
For i As Integer = 0 To 255
lena8.Palette.E ntries(i) = Color.FromArgb( i, i, i)
Next
lena8.Save("d:\ lena8-0-255.bmp",
System.Drawing. Imaging.ImageFo rmat.Bmp)
---snip---
On Sat, 14 Jul 2007 17:31:09 -0400, " active"
<ac********** @a-znet.comwrote:
For each entry: get an entry from a Bitmap color table modify it store the modified entry in a color table
Assign the new color table to the bitmap.
So I think I can do what the other posters suggested.
But I would like to know what you meant by the following. Just copy the class to MyColorPalette
Thanks
If my memory serves me right, the original problem was that
if the 8-bit indexed image was loaded from a file, any attempt
(at least any attempt I made) would fail to change the palette.
In your (Powell's) example, you are creating a NEW bitmap
object, then setting the palette - which actually works - but
that is not as interesting as changing the palette for an
existing image we just loaded.
As you say, the last line you show sets the palette for the
bitmap object, but you fail to show how Powell "inserts the
bitmap data"?!?
Could you please post a complete, working sample based
on this information that actually loads a gif from disk, changes
the palette, then writes it back to disk, changed palette and all?
Regards,
Joergen Bech
On Mon, 20 Aug 2007 11:20:03 -0700, active
<ac****@discuss ions.microsoft. comwrote:
>How dose powell get a way with this. It works including saving to a file. The last line I show he is inserting a color table into a Bitmap! He then inserts the bitmap data.
Isn't this what we are saying can't be effective?
Thanks if you can explain this
Private Sub panel1_Click(.. .
'Creates a new GIF image with a modified colour palette
If Not (cp Is Nothing) Then
'Create a new 8 bit per pixel image
Dim bm As New Bitmap(_gifImag e.Width, _gifImage.Heigh t, PixelFormat.Fo rmat8bppIndexed )
'get it's palette
Dim ncp As ColorPalette = bm.Palette
'copy all the entries from the old palette removing any transparency
Dim n As Integer = 0
Dim c As Color
For Each c In cp.Entries
ncp.Entries(n) = Color.FromArgb( 255, c)
n += 1
Next c
'Set the newly selected transparency
ncp.Entries(Cur rentEntry) = Color.FromArgb( 0, cp.Entries(Cur rentEntry))
're-insert the palette
bm.Palette = ncp "Joergen Bech @ post1.tele.dk>" wrote:
>> Have a look at http://www.codeproject.com/cs/media/...essing_Lab.asp
To create a grayscale image from a 256-color image, he creates a new 8-bit image of the same size as the original, sets the Palette values of the new image to 0,0,0 1,1,1 2,2,2 ... 255,255,255, then proceeds to set the pixel data of the new image by calculating the intensities of the original image.
It would have been much faster had he just modified the palette entries of the original image.
I made another test (create a new Windows application project): ---snip--- Private _bm As Bitmap
Private Sub Form1_Load(ByVa l sender As System.Object, ByVal e As System.EventAr gs) Handles MyBase.Load Test2() End Sub
Private Sub Test2() Dim lena8 As New Bitmap("d:\lena 8.bmp") SetGrayscalePal ette(lena8) _bm = lena8 lena8.Save("d:\ lena8-gray.bmp", System.Drawing .Imaging.ImageF ormat.Bmp) End Sub
Public Shared Sub SetGrayscalePal ette(ByVal image As Bitmap) If (image.PixelFor mat <PixelFormat.Fo rmat8bppIndexed ) Then Throw New ArgumentExcepti on End If Dim palette As ColorPalette = image.Palette Dim i As Integer For i = 0 To &H100 - 1 'palette.Entrie s(i) = Color.FromArgb( i, i, i) Dim original As Color = palette.Entries (i) Dim gray As Integer = CType((original .G * 4 + original.R * 2 + original.B) / 7, Integer) palette.Entries (i) = Color.FromArgb( gray, gray, gray) Next i image.Palette = palette End Sub
Private Sub Form1_Paint(ByV al sender As Object, ByVal e As System.Windows .Forms.PaintEve ntArgs) Handles Me.Paint If _bm Is Nothing Then Exit Sub End If
e.Graphics.Draw Image(_bm, 0, 0, _bm.Width, _bm.Height)
End Sub
---snip---
(Yes, I know that (G*4+R*2+B)/7 is simplistic and incorrect)
You will notice that the palette entries actually have changed when the image is painted on the form, but the saved copy retains the original colors.
If we were to paint the image from the code above onto a 24-bit bitmap and save it, we get a nice grayscale image, albeit 24-bit: ---snip--- Dim dst As New Bitmap(lena8.Wi dth, lena8.Height, PixelFormat.Fo rmat24bppRgb) Dim g As Graphics = Graphics.FromIm age(dst) g.DrawImage(len a8, 0, 0, dst.Width, dst.Height) g.Dispose() dst.Save("d:\ds t.bmp", ImageFormat.Bmp ) ---snip---
(it is not possible to create a Graphics object from an indexed image).
I have not spent any time digging into why the original palette is used when saving an indexed image, but as I mentioned in the other post, I use an imaging library myself (LeadTools).
Perhaps the link at the top might give you a few ideas of how to go about this in an entirely different way.
Regards,
Joergen Bech On Sat, 14 Jul 2007 21:37:24 -0400, " active" <ac**********@ a-znet.comwrote:
>What was MS thinking? Why not make Entries readonly? I add a statement to yout code: The line written did not reflect i,i,i
lena8.Palette. Entries(i) = Color.FromArgb( i, i, i)
Console.WriteL ine("Entry({0} = {1}", i, lena8.Palette.E ntries(i))
"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNO SPAMwrote in message news:5n******* *************** **********@4ax. com...
My suggestion was that if you needed a class with the same behavior as ColorPalette, but with a few changes, you could just copy the code from the ColorPalette class to another class with the name and additional functionality of your choice. There are various tools for decompiling the framework.
But if you need to assign a ColorPalette object to a property that expects the type found in the framework, this might not be an option.
As for assigning a palette from a dummy palette indirectly created by creating a new bitmap of the same bit depth: No can do.
MyBitmap.Palet te = <ColorPalette object>
is not the same as
MyBitmap.Palet te = <some other bitmap>.Palette .
In the latter case, you are going through some GDI+ functions to get a new palette rather than just getting a ColorPalette object directly.
When assigned to MyBitmap.Palett e, you are jumping through similar hoops.
Try the code below. You will find that nothing works as expected. All copies are identical to the original. Attempts to change the colors in any of these manners are ignored.
I use an imaging toolkit for similar needs, so I haven't digged deeper into this. There might be a solution. Then again, there might not. It is possible that Microsoft has made it *possible* to change the Palette.Entrie s values, but not *intended* for them to be changed or react to such changes.
Please prove me wrong.
Regards,
Joergen Bech
---snip---
'Load image Dim lena8 As New Bitmap("d:\lena 8.bmp")
'Save it again to verify that we read it correctly lena8.Save("d:\ lena8-original.bmp", System.Drawing .Imaging.ImageF ormat.Bmp)
'Work with a palette created as a copy of the palette of the original image Dim cp As ColorPalette = lena8.Palette
For i As Integer = 0 To 255 cp.Entries(i) = Color.FromArgb( i, i, i) Next lena8.Palette = cp lena8.Save("d:\ lena8-cp.bmp", System.Drawing .Imaging.ImageF ormat.Bmp)
'Work with a dummy palette created by creating another bitmap Dim bm As New Bitmap(1, 1, PixelFormat.For mat8bppIndexed) For i As Integer = 0 To 255 bm.Palette.Entr ies(i) = Color.FromArgb( i, i, i) Next lena8.Palette = bm.Palette lena8.Save("d:\ lena8-bm.bmp", System.Drawing .Imaging.ImageF ormat.Bmp)
'Modify palette entries directly in the original image For i As Integer = 0 To 255 lena8.Palette.E ntries(i) = Color.FromArgb( i, i, i) Next lena8.Save("d:\ lena8-0-255.bmp", System.Drawing .Imaging.ImageF ormat.Bmp)
---snip---
On Sat, 14 Jul 2007 17:31:09 -0400, " active" <ac**********@ a-znet.comwrote:
For each entry: get an entry from a Bitmap color table modify it store the modified entry in a color table
Assign the new color table to the bitmap.
So I think I can do what the other posters suggested.
But I would like to know what you meant by the following. Just copy the class to MyColorPalette
Thanks
I believe I just found the answer in Q319061.
....snip
You can write an unmodified Bitmap with the GIF encoder and keep the Bitmap
color table intact; therefore, you can use this method to save a .gif file
with a new color table.
The method is to copy the image data from an original Image object to a
temporary Bitmap object. This temporary Bitmap is created as an 8-BPP
indexed Bitmap, which is the pixel format that is used to save a .gif file.
The Bitmap color table is set by using the SetPalette method, and then the
image definition is copied to the temporary Bitmap. After you create the
temporary Bitmap with a duplicate definition, you can use the Save() method
to save it with the GIF encoder, which preserves the 8-BPP color table.
...snip
I guess the "unmodified " is what allows it. Maybe when the bitmap data is
added the "save" color table get frozen. You think?
Q319061 shows how and I believe it is just what Powell does.
Code is at the bottom of this link in the panel1_Click sub at http://www.bobpowell.net/giftransparency.htm
====
Do you know why it is always 8bpp. Other formats such as 4bpp are possible
but never seem to be saved by GDI+
Also, I found Q319061 when I was looking for the file format for a GIF file
(read via a stream) if you know where that is I'd appreciate the link.
Thanks for answering
"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNO SPAMwrote in message
news:7q******** *************** *********@4ax.c om...
>
If my memory serves me right, the original problem was that
if the 8-bit indexed image was loaded from a file, any attempt
(at least any attempt I made) would fail to change the palette.
In your (Powell's) example, you are creating a NEW bitmap
object, then setting the palette - which actually works - but
that is not as interesting as changing the palette for an
existing image we just loaded.
He copies the image data so it creates a new bitmap with the same image an a
new palette which can be saved and viewed.
>
As you say, the last line you show sets the palette for the
bitmap object, but you fail to show how Powell "inserts the
bitmap data"?!?
It's a little long and I don't know if that is OK with Powell.
>
Could you please post a complete, working sample based
on this information that actually loads a gif from disk, changes
the palette, then writes it back to disk, changed palette and all?
He plays with the transparency but that can be removed.
>
Regards,
Joergen Bech
On Mon, 20 Aug 2007 11:20:03 -0700, active
<ac****@discuss ions.microsoft. comwrote:
>>How dose powell get a way with this. It works including saving to a file. The last line I show he is inserting a color table into a Bitmap! He then inserts the bitmap data.
Isn't this what we are saying can't be effective?
Thanks if you can explain this
Private Sub panel1_Click(.. . 'Creates a new GIF image with a modified colour palette
If Not (cp Is Nothing) Then
'Create a new 8 bit per pixel image
Dim bm As New Bitmap(_gifImag e.Width, _gifImage.Heigh t, PixelFormat.F ormat8bppIndexe d)
'get it's palette
Dim ncp As ColorPalette = bm.Palette 'copy all the entries from the old palette removing any transparency
Dim n As Integer = 0
Dim c As Color
For Each c In cp.Entries
ncp.Entries(n) = Color.FromArgb( 255, c)
n += 1
Next c
'Set the newly selected transparency
ncp.Entries(Cur rentEntry) = Color.FromArgb( 0, cp.Entries(Cu rrentEntry))
're-insert the palette
bm.Palette = ncp "Joergen Bech @ post1.tele.dk>" wrote:
>>> Have a look at http://www.codeproject.com/cs/media/...essing_Lab.asp
To create a grayscale image from a 256-color image, he creates a new 8-bit image of the same size as the original, sets the Palette values of the new image to 0,0,0 1,1,1 2,2,2 ... 255,255,255, then proceeds to set the pixel data of the new image by calculating the intensities of the original image.
It would have been much faster had he just modified the palette entries of the original image.
I made another test (create a new Windows application project): ---snip--- Private _bm As Bitmap
Private Sub Form1_Load(ByVa l sender As System.Object, ByVal e As System.EventA rgs) Handles MyBase.Load Test2() End Sub
Private Sub Test2() Dim lena8 As New Bitmap("d:\lena 8.bmp") SetGrayscalePal ette(lena8) _bm = lena8 lena8.Save("d:\ lena8-gray.bmp", System.Drawin g.Imaging.Image Format.Bmp) End Sub
Public Shared Sub SetGrayscalePal ette(ByVal image As Bitmap) If (image.PixelFor mat <PixelFormat.Fo rmat8bppIndexed ) Then Throw New ArgumentExcepti on End If Dim palette As ColorPalette = image.Palette Dim i As Integer For i = 0 To &H100 - 1 'palette.Entrie s(i) = Color.FromArgb( i, i, i) Dim original As Color = palette.Entries (i) Dim gray As Integer = CType((original .G * 4 + original.R * 2 + original.B) / 7, Integer) palette.Entries (i) = Color.FromArgb( gray, gray, gray) Next i image.Palette = palette End Sub
Private Sub Form1_Paint(ByV al sender As Object, ByVal e As System.Window s.Forms.PaintEv entArgs) Handles Me.Paint If _bm Is Nothing Then Exit Sub End If
e.Graphics.Draw Image(_bm, 0, 0, _bm.Width, _bm.Height)
End Sub
---snip---
(Yes, I know that (G*4+R*2+B)/7 is simplistic and incorrect)
You will notice that the palette entries actually have changed when the image is painted on the form, but the saved copy retains the original colors.
If we were to paint the image from the code above onto a 24-bit bitmap and save it, we get a nice grayscale image, albeit 24-bit: ---snip--- Dim dst As New Bitmap(lena8.Wi dth, lena8.Height, PixelFormat.F ormat24bppRgb) Dim g As Graphics = Graphics.FromIm age(dst) g.DrawImage(len a8, 0, 0, dst.Width, dst.Height) g.Dispose() dst.Save("d:\ds t.bmp", ImageFormat.Bmp ) ---snip---
(it is not possible to create a Graphics object from an indexed image).
I have not spent any time digging into why the original palette is used when saving an indexed image, but as I mentioned in the other post, I use an imaging library myself (LeadTools).
Perhaps the link at the top might give you a few ideas of how to go about this in an entirely different way.
Regards,
Joergen Bech On Sat, 14 Jul 2007 21:37:24 -0400, " active" <ac********** @a-znet.comwrote:
What was MS thinking? Why not make Entries readonly? I add a statement to yout code: The line written did not reflect i,i,i
lena8.Palette .Entries(i) = Color.FromArgb( i, i, i)
Console.Write Line("Entry({0} = {1}", i, lena8.Palette.E ntries(i))
"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNO SPAMwrote in message news:5n****** *************** ***********@4ax .com...
My suggestion was that if you needed a class with the same behavior as ColorPalette, but with a few changes, you could just copy the code from the ColorPalette class to another class with the name and additional functionality of your choice. There are various tools for decompiling the framework.
But if you need to assign a ColorPalette object to a property that expects the type found in the framework, this might not be an option.
As for assigning a palette from a dummy palette indirectly created by creating a new bitmap of the same bit depth: No can do.
MyBitmap.Pale tte = <ColorPalette object>
is not the same as
MyBitmap.Pale tte = <some other bitmap>.Palette .
In the latter case, you are going through some GDI+ functions to get a new palette rather than just getting a ColorPalette object directly.
When assigned to MyBitmap.Palett e, you are jumping through similar hoops.
Try the code below. You will find that nothing works as expected. All copies are identical to the original. Attempts to change the colors in any of these manners are ignored.
I use an imaging toolkit for similar needs, so I haven't digged deeper into this. There might be a solution. Then again, there might not. It is possible that Microsoft has made it *possible* to change the Palette.Entri es values, but not *intended* for them to be changed or react to such changes.
Please prove me wrong.
Regards,
Joergen Bech
---snip---
'Load image Dim lena8 As New Bitmap("d:\lena 8.bmp")
'Save it again to verify that we read it correctly lena8.Save("d:\ lena8-original.bmp", System.Drawin g.Imaging.Image Format.Bmp)
'Work with a palette created as a copy of the palette of the original image Dim cp As ColorPalette = lena8.Palette
For i As Integer = 0 To 255 cp.Entries(i) = Color.FromArgb( i, i, i) Next lena8.Palette = cp lena8.Save("d:\ lena8-cp.bmp", System.Drawin g.Imaging.Image Format.Bmp)
'Work with a dummy palette created by creating another bitmap Dim bm As New Bitmap(1, 1, PixelFormat.For mat8bppIndexed) For i As Integer = 0 To 255 bm.Palette.Entr ies(i) = Color.FromArgb( i, i, i) Next lena8.Palette = bm.Palette lena8.Save("d:\ lena8-bm.bmp", System.Drawin g.Imaging.Image Format.Bmp)
'Modify palette entries directly in the original image For i As Integer = 0 To 255 lena8.Palette.E ntries(i) = Color.FromArgb( i, i, i) Next lena8.Save("d:\ lena8-0-255.bmp", System.Drawin g.Imaging.Image Format.Bmp)
---snip---
On Sat, 14 Jul 2007 17:31:09 -0400, " active" <ac********** @a-znet.comwrote:
For each entry: get an entry from a Bitmap color table modify it store the modified entry in a color table
Assign the new color table to the bitmap.
So I think I can do what the other posters suggested.
But I would like to know what you meant by the following. Just copy the class to MyColorPalette
Thanks
On Tue, 21 Aug 2007 13:51:05 -0400, "\"Frank\"" <Fr***@a-znet.com>
wrote:
>I believe I just found the answer in Q319061. ...snip You can write an unmodified Bitmap with the GIF encoder and keep the Bitmap color table intact; therefore, you can use this method to save a .gif file with a new color table.
The method is to copy the image data from an original Image object to a temporary Bitmap object. This temporary Bitmap is created as an 8-BPP indexed Bitmap, which is the pixel format that is used to save a .gif file. The Bitmap color table is set by using the SetPalette method, and then the image definition is copied to the temporary Bitmap. After you create the temporary Bitmap with a duplicate definition, you can use the Save() method to save it with the GIF encoder, which preserves the 8-BPP color table.
>I guess the "unmodified " is what allows it. Maybe when the bitmap data is added the "save" color table get frozen. You think?
I wouldn't presume to guess, but it appears to be the case.
>Q319061 shows how and I believe it is just what Powell does.
Code is at the bottom of this link in the panel1_Click sub at
http://www.bobpowell.net/giftransparency.htm
ok, that is exactly what I thought. Surely there must be faster
methods of transferring the image data, but I guess that sample
would work fine for small images.
>Do you know why it is always 8bpp. Other formats such as 4bpp are possible but never seem to be saved by GDI+
The GDI+ codecs are extremely limited. Use a proper image library if
you need anything other than the most basic formats.
>Also, I found Q319061 when I was looking for the file format for a GIF file (read via a stream) if you know where that is I'd appreciate the link.
A link to the gif specification? http://www.w3.org/Graphics/GIF/spec-gif89a.txt
Surely you are not thinking about converting raw<->gif yourself?
Too much work. No need to reinvent the wheel.
Yes, Q319061 seems to hold all the answers we (you) were looking
for.
Regards,
Joergen Bech
>
>>Do you know why it is always 8bpp. Other formats such as 4bpp are possible but never seem to be saved by GDI+
The GDI+ codecs are extremely limited. Use a proper image library if
you need anything other than the most basic formats.
You don't know of a free one do you?
>
>>Also, I found Q319061 when I was looking for the file format for a GIF file (read via a stream) if you know where that is I'd appreciate the link.
A link to the gif specification? http://www.w3.org/Graphics/GIF/spec-gif89a.txt
thanks
>
Surely you are not thinking about converting raw<->gif yourself?
Too much work. No need to reinvent the wheel.
No. Maybe just reading things like the Color Resolution because I don't
know what's in the file and what GDI+ did to the data.
On Tue, 21 Aug 2007 15:53:31 -0400, "\"Frank\"" <Fr***@a-znet.com>
wrote:
>>>Do you know why it is always 8bpp. Other formats such as 4bpp are possible but never seem to be saved by GDI+
The GDI+ codecs are extremely limited. Use a proper image library if you need anything other than the most basic formats.
You don't know of a free one do you?
Not really. There are free or open source imaging libraries around,
but they usually add functionality not found in GDI+ rather than
completely replacing GDI+
What you want is probably something that allows you to control
the image format and perform image operations within that format
without ever going to 32-bit and back again, which GDI+ is likely
to force you to do. Something like LeadTools, which will set you back
a pretty penny.
I have yet to find a freeware imaging library that completely replaces
GDI+ - codecs, raster operations, and all.
Even something like Paint .Net does not really let you work with
8-bit images natively. You can load and save 8-bit images, but as
soon as the image goes in, it is converted to 32-bit and the image
must be converted again if saving using one of the 8-bit formats.
Not much general interest in <32-bit imaging these days :)
/Joergen Bech
I would think that for the Internet if a 4-bpp would look OK it would be
preferred to 8-bpp.
Don't you think?
">
Not much general interest in <32-bit imaging these days :)
/Joergen Bech
No, when we are dealing with low-color images in the compressed
formats (such as gif or png), it does not really matter much if the
image is stored using 16 colors or 256 colors (where the 240 colors
are unused).
As a test, I took an enormous image, reduced it to 4 colors and
saved it as a 4-bit (16MB) as well as an 8-bit (32MB) image.
I then compressed those two. The results were 1.0MB for the
4-bit version and 1.1MB for the 8-bit version.
Yes, the 8-bit version was larger, but do you really want to jump
through hoops (write a lot of code and decide on different color
depths for each image) just to save 10% or thereabouts?
I think you are optimizing before actually having tested if the
optimization is necessary.
Keep it simple. You really only need to decide between 8-bit
and lossless, 24-bit and lossy, or 24-bit and lossless. The latter
case is probably rare.
/Joergen Bech
On Wed, 22 Aug 2007 10:53:38 -0400, "\"Frank\"" <Fr***@a-znet.com>
wrote:
>I would think that for the Internet if a 4-bpp would look OK it would be preferred to 8-bpp.
Don't you think?
">
>Not much general interest in <32-bit imaging these days :)
/Joergen Bech
"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNO SPAMwrote in message
news:ck******** *************** *********@4ax.c om...
>
No, when we are dealing with low-color images in the compressed
formats (such as gif or png), it does not really matter much if the
image is stored using 16 colors or 256 colors (where the 240 colors
are unused).
As a test, I took an enormous image, reduced it to 4 colors and
saved it as a 4-bit (16MB) as well as an 8-bit (32MB) image.
I then compressed those two. The results were 1.0MB for the
4-bit version and 1.1MB for the 8-bit version.
Yes, the 8-bit version was larger, but do you really want to jump
through hoops (write a lot of code and decide on different color
depths for each image) just to save 10% or thereabouts?
I think you are optimizing before actually having tested if the
optimization is necessary.
I'm not doing Internet development.
It was just a random thought.
Thanks for the insight
>
Keep it simple. You really only need to decide between 8-bit
and lossless, 24-bit and lossy, or 24-bit and lossless. The latter
case is probably rare.
/Joergen Bech
On Wed, 22 Aug 2007 10:53:38 -0400, "\"Frank\"" <Fr***@a-znet.com>
wrote:
>>I would think that for the Internet if a 4-bpp would look OK it would be preferred to 8-bpp.
Don't you think?
">
>>Not much general interest in <32-bit imaging these days :)
/Joergen Bech This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Dan Perl |
last post by:
There is something with initializing mutable class attributes that I am
struggling with. I'll use an example to explain:
class Father:
attr1=None # this is OK
attr2= # this is wrong
def foo(self, data):
self.attr1=data
self.attr2.append(data)
The initialization of attr1 is obviously OK, all instances of Father
redefine it in the method foo. But the initialization of attr2 is wrong
|
by: Bryan Parkoff |
last post by:
I have created three classes according to my own design. First class
is called CMain. It is the Top Class. Second class and third class are
called CMemory and CMPU. They are the sub-classes.
Two sub-classes have the relationship to communicate back and forth
through this pointer. The pointer is responsible inside Top class for
allocating and deallocating two sub-classes.
CMemory class is responsible to allocate and deallocate memory...
|
by: Fabian Müller |
last post by:
Hi all,
my question is as follows:
If have a class X and a class Y derived from X.
Constructor of X is X(param1, param2) .
Constructor of Y is Y(param1, ..., param4) .
|
by: G. Purby |
last post by:
What is the proper way of defining a class that inherits from a base class
that has no constructor with 0 arguments?
The following code generates compiler error CS1501, "No overload for method
'BaseClass' takes '0' arguments".
class BaseClass
{
public BaseClass(double x)
{
|
by: Joel |
last post by:
Is it true that if we don't specify a default constructor for
our class, then the C# compiler provides us with its own
that zeroes (or assigns default values) to the data members?
I wrote a no-parameter constructor for my class with an
empty function body. I then instantiated an object and tried
printing its values, amazingly the members were already initialized.
But how is this possible if I have not included any code for doing
so. The...
| |
by: Nathan Sokalski |
last post by:
How do I create a new System.Drawing.Imaging.ColorPalette? ColorPalette does
not have a constructor, and the Entries property is ReadOnly. How are we
supposed to specify a palette other than the default? If there were a method
to import an Array or Collection of System.Drawing.Color or something, it
would be no problem, but the way it is set up right now I pretty much feel
like it is useless. Any ideas? Thanks.
--
Nathan Sokalski...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
| |
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
|
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |