467,880 Members | 1,265 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 467,880 developers. It's quick & easy.

The ColorPalette class has no constructor so how does one use it?

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 #1
  • viewed: 2108
Share:
19 Replies
On Sat, 14 Jul 2007 13:49:13 -0400, " active"
<ac**********@a-znet.comwrote:
>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.
If there is no constructor, then you can only get a ColorPalette from
other objects. For example:

Dim cp As ColorPalette
Dim bmp As Bitmap = New Bitmap("figure2.bmp")

cp = bmp.Palette
Jul 14 '07 #2
Lke the other poster says...

Just create a 1x1 bitmap of the appropriate bit depth and retrieve it's
color palette into your variable.

It's not elegant, but it's the only way.

" active" <ac**********@a-znet.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
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 #3
thanks

"Jack Jackson" <ja********@pebbleridge.comwrote in message
news:nm********************************@4ax.com...
On Sat, 14 Jul 2007 13:49:13 -0400, " active"
<ac**********@a-znet.comwrote:
>>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.

If there is no constructor, then you can only get a ColorPalette from
other objects. For example:

Dim cp As ColorPalette
Dim bmp As Bitmap = New Bitmap("figure2.bmp")

cp = bmp.Palette

Jul 14 '07 #4
thanks

"Blake" <no@emailwrote in message
news:%2****************@TK2MSFTNGP03.phx.gbl...
Lke the other poster says...

Just create a 1x1 bitmap of the appropriate bit depth and retrieve it's
color palette into your variable.

It's not elegant, but it's the only way.

" active" <ac**********@a-znet.comwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
>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 #5

What do you need it for anyway?

The ColorPalette class is just a wrapper for a simple
1-dimensional array of System.Drawing.Color entries.

It contains two internal (Friend) methods:
- ConvertFromMemory
- ConvertToMemory

All they do is to convert between 32-bit integers and
System.Drawing.Color.

Just copy the class to MyColorPalette or whatever and
add the missing "Entries" setter, if that is what you are
looking for.

Do you just want the conversion functions or do you
actually need to assign an actual
System.Drawing.Imaging.ColorPalette object to something?

Regards,

Joergen Bech

On Sat, 14 Jul 2007 13:49:13 -0400, " active"
<ac**********@a-znet.comwrote:
>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 #6
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
Jul 14 '07 #7

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.Palette = <ColorPalette object>

is not the same as

MyBitmap.Palette = <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.Palette, 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:\lena8.bmp")

'Save it again to verify that we read it correctly
lena8.Save("d:\lena8-original.bmp",
System.Drawing.Imaging.ImageFormat.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.ImageFormat.Bmp)

'Work with a dummy palette created by creating another bitmap
Dim bm As New Bitmap(1, 1, PixelFormat.Format8bppIndexed)
For i As Integer = 0 To 255
bm.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Palette = bm.Palette
lena8.Save("d:\lena8-bm.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)

'Modify palette entries directly in the original image
For i As Integer = 0 To 255
lena8.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Save("d:\lena8-0-255.bmp",
System.Drawing.Imaging.ImageFormat.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
Jul 14 '07 #8
Never decompiled the framework so it didn't occur to me that was what you
meant.

Thanks for taking so much time to answer so completely.

I need to study the code.

thanks

"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNOSPAMwrote 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.Palette = <ColorPalette object>

is not the same as

MyBitmap.Palette = <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.Palette, 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:\lena8.bmp")

'Save it again to verify that we read it correctly
lena8.Save("d:\lena8-original.bmp",
System.Drawing.Imaging.ImageFormat.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.ImageFormat.Bmp)

'Work with a dummy palette created by creating another bitmap
Dim bm As New Bitmap(1, 1, PixelFormat.Format8bppIndexed)
For i As Integer = 0 To 255
bm.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Palette = bm.Palette
lena8.Save("d:\lena8-bm.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)

'Modify palette entries directly in the original image
For i As Integer = 0 To 255
lena8.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Save("d:\lena8-0-255.bmp",
System.Drawing.Imaging.ImageFormat.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

Jul 14 '07 #9
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.WriteLine("Entry({0} = {1}", i, lena8.Palette.Entries(i))


"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNOSPAMwrote 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.Palette = <ColorPalette object>

is not the same as

MyBitmap.Palette = <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.Palette, 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:\lena8.bmp")

'Save it again to verify that we read it correctly
lena8.Save("d:\lena8-original.bmp",
System.Drawing.Imaging.ImageFormat.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.ImageFormat.Bmp)

'Work with a dummy palette created by creating another bitmap
Dim bm As New Bitmap(1, 1, PixelFormat.Format8bppIndexed)
For i As Integer = 0 To 255
bm.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Palette = bm.Palette
lena8.Save("d:\lena8-bm.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)

'Modify palette entries directly in the original image
For i As Integer = 0 To 255
lena8.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Save("d:\lena8-0-255.bmp",
System.Drawing.Imaging.ImageFormat.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

Jul 15 '07 #10

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(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Test2()
End Sub

Private Sub Test2()
Dim lena8 As New Bitmap("d:\lena8.bmp")
SetGrayscalePalette(lena8)
_bm = lena8
lena8.Save("d:\lena8-gray.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)
End Sub

Public Shared Sub SetGrayscalePalette(ByVal image As Bitmap)
If (image.PixelFormat <PixelFormat.Format8bppIndexed) Then
Throw New ArgumentException
End If
Dim palette As ColorPalette = image.Palette
Dim i As Integer
For i = 0 To &H100 - 1
'palette.Entries(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(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles Me.Paint
If _bm Is Nothing Then
Exit Sub
End If

e.Graphics.DrawImage(_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.Width, lena8.Height,
PixelFormat.Format24bppRgb)
Dim g As Graphics = Graphics.FromImage(dst)
g.DrawImage(lena8, 0, 0, dst.Width, dst.Height)
g.Dispose()
dst.Save("d:\dst.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.WriteLine("Entry({0} = {1}", i, lena8.Palette.Entries(i))


"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNOSPAMwrote 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.Palette = <ColorPalette object>

is not the same as

MyBitmap.Palette = <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.Palette, 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:\lena8.bmp")

'Save it again to verify that we read it correctly
lena8.Save("d:\lena8-original.bmp",
System.Drawing.Imaging.ImageFormat.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.ImageFormat.Bmp)

'Work with a dummy palette created by creating another bitmap
Dim bm As New Bitmap(1, 1, PixelFormat.Format8bppIndexed)
For i As Integer = 0 To 255
bm.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Palette = bm.Palette
lena8.Save("d:\lena8-bm.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)

'Modify palette entries directly in the original image
For i As Integer = 0 To 255
lena8.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Save("d:\lena8-0-255.bmp",
System.Drawing.Imaging.ImageFormat.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
Jul 15 '07 #11
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(_gifImage.Width, _gifImage.Height,
PixelFormat.Format8bppIndexed)

'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(CurrentEntry) = Color.FromArgb(0,
cp.Entries(CurrentEntry))

'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(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Test2()
End Sub

Private Sub Test2()
Dim lena8 As New Bitmap("d:\lena8.bmp")
SetGrayscalePalette(lena8)
_bm = lena8
lena8.Save("d:\lena8-gray.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)
End Sub

Public Shared Sub SetGrayscalePalette(ByVal image As Bitmap)
If (image.PixelFormat <PixelFormat.Format8bppIndexed) Then
Throw New ArgumentException
End If
Dim palette As ColorPalette = image.Palette
Dim i As Integer
For i = 0 To &H100 - 1
'palette.Entries(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(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles Me.Paint
If _bm Is Nothing Then
Exit Sub
End If

e.Graphics.DrawImage(_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.Width, lena8.Height,
PixelFormat.Format24bppRgb)
Dim g As Graphics = Graphics.FromImage(dst)
g.DrawImage(lena8, 0, 0, dst.Width, dst.Height)
g.Dispose()
dst.Save("d:\dst.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.WriteLine("Entry({0} = {1}", i, lena8.Palette.Entries(i))


"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNOSPAMwrote 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.Palette = <ColorPalette object>

is not the same as

MyBitmap.Palette = <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.Palette, 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:\lena8.bmp")

'Save it again to verify that we read it correctly
lena8.Save("d:\lena8-original.bmp",
System.Drawing.Imaging.ImageFormat.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.ImageFormat.Bmp)

'Work with a dummy palette created by creating another bitmap
Dim bm As New Bitmap(1, 1, PixelFormat.Format8bppIndexed)
For i As Integer = 0 To 255
bm.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Palette = bm.Palette
lena8.Save("d:\lena8-bm.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)

'Modify palette entries directly in the original image
For i As Integer = 0 To 255
lena8.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Save("d:\lena8-0-255.bmp",
System.Drawing.Imaging.ImageFormat.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


Aug 20 '07 #12

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****@discussions.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(_gifImage.Width, _gifImage.Height,
PixelFormat.Format8bppIndexed)

'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(CurrentEntry) = Color.FromArgb(0,
cp.Entries(CurrentEntry))

'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(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Test2()
End Sub

Private Sub Test2()
Dim lena8 As New Bitmap("d:\lena8.bmp")
SetGrayscalePalette(lena8)
_bm = lena8
lena8.Save("d:\lena8-gray.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)
End Sub

Public Shared Sub SetGrayscalePalette(ByVal image As Bitmap)
If (image.PixelFormat <PixelFormat.Format8bppIndexed) Then
Throw New ArgumentException
End If
Dim palette As ColorPalette = image.Palette
Dim i As Integer
For i = 0 To &H100 - 1
'palette.Entries(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(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles Me.Paint
If _bm Is Nothing Then
Exit Sub
End If

e.Graphics.DrawImage(_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.Width, lena8.Height,
PixelFormat.Format24bppRgb)
Dim g As Graphics = Graphics.FromImage(dst)
g.DrawImage(lena8, 0, 0, dst.Width, dst.Height)
g.Dispose()
dst.Save("d:\dst.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.WriteLine("Entry({0} = {1}", i, lena8.Palette.Entries(i))


"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNOSPAMwrote 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.Palette = <ColorPalette object>

is not the same as

MyBitmap.Palette = <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.Palette, 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:\lena8.bmp")

'Save it again to verify that we read it correctly
lena8.Save("d:\lena8-original.bmp",
System.Drawing.Imaging.ImageFormat.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.ImageFormat.Bmp)

'Work with a dummy palette created by creating another bitmap
Dim bm As New Bitmap(1, 1, PixelFormat.Format8bppIndexed)
For i As Integer = 0 To 255
bm.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Palette = bm.Palette
lena8.Save("d:\lena8-bm.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)

'Modify palette entries directly in the original image
For i As Integer = 0 To 255
lena8.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Save("d:\lena8-0-255.bmp",
System.Drawing.Imaging.ImageFormat.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

Aug 21 '07 #13
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<NOSPAMNOSPAMwrote in message
news:7q********************************@4ax.com...
>
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****@discussions.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(_gifImage.Width, _gifImage.Height,
PixelFormat.Format8bppIndexed)

'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(CurrentEntry) = Color.FromArgb(0,
cp.Entries(CurrentEntry))

'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(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Test2()
End Sub

Private Sub Test2()
Dim lena8 As New Bitmap("d:\lena8.bmp")
SetGrayscalePalette(lena8)
_bm = lena8
lena8.Save("d:\lena8-gray.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)
End Sub

Public Shared Sub SetGrayscalePalette(ByVal image As Bitmap)
If (image.PixelFormat <PixelFormat.Format8bppIndexed) Then
Throw New ArgumentException
End If
Dim palette As ColorPalette = image.Palette
Dim i As Integer
For i = 0 To &H100 - 1
'palette.Entries(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(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles Me.Paint
If _bm Is Nothing Then
Exit Sub
End If

e.Graphics.DrawImage(_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.Width, lena8.Height,
PixelFormat.Format24bppRgb)
Dim g As Graphics = Graphics.FromImage(dst)
g.DrawImage(lena8, 0, 0, dst.Width, dst.Height)
g.Dispose()
dst.Save("d:\dst.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.WriteLine("Entry({0} = {1}", i, lena8.Palette.Entries(i))


"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNOSPAMwrote 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.Palette = <ColorPalette object>

is not the same as

MyBitmap.Palette = <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.Palette, 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:\lena8.bmp")

'Save it again to verify that we read it correctly
lena8.Save("d:\lena8-original.bmp",
System.Drawing.Imaging.ImageFormat.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.ImageFormat.Bmp)

'Work with a dummy palette created by creating another bitmap
Dim bm As New Bitmap(1, 1, PixelFormat.Format8bppIndexed)
For i As Integer = 0 To 255
bm.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Palette = bm.Palette
lena8.Save("d:\lena8-bm.bmp",
System.Drawing.Imaging.ImageFormat.Bmp)

'Modify palette entries directly in the original image
For i As Integer = 0 To 255
lena8.Palette.Entries(i) = Color.FromArgb(i, i, i)
Next
lena8.Save("d:\lena8-0-255.bmp",
System.Drawing.Imaging.ImageFormat.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



Aug 21 '07 #14
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

Aug 21 '07 #15
>
>>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.
Aug 21 '07 #16
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

Aug 22 '07 #17
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

Aug 22 '07 #18

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
Aug 22 '07 #19

"Joergen Bech @ post1.tele.dk>" <jbech<NOSPAMNOSPAMwrote in message
news:ck********************************@4ax.com...
>
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

Aug 22 '07 #20

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

50 posts views Thread by Dan Perl | last post: by
13 posts views Thread by Bryan Parkoff | last post: by
23 posts views Thread by Fabian MŁller | last post: by
3 posts views Thread by G. Purby | last post: by
10 posts views Thread by Joel | last post: by
10 posts views Thread by Nathan Sokalski | last post: by
reply views Thread by MrMoon | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.