Convert image to 8bit 256 colors (windows only)

Share your advanced PureBasic knowledge/code with the community.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

pant pant drool drool hubba hubbaa woof woof........

Aye, and the girl's not bad either!

I think this is another instance when that Sparkie fella start's worring! :wink:

Seriously; some excellent work here netty. Great stuff.
I may look like a mule, but I'm not a complete ass.
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

Great! This is how "levels" works (one of the most useful photoshop's tool). It creates an histogram of used colours, and you can see how colours are used in the picture, to adjust them accordingly to your perception, the black and white points, and so on.
Now it's time for dithering ;)
User avatar
Rings
Moderator
Moderator
Posts: 1435
Joined: Sat Apr 26, 2003 1:11 am

Post by Rings »

great work!!
SPAMINATOR NR.1
Coolman
Enthusiast
Enthusiast
Posts: 103
Joined: Sat Sep 03, 2005 4:07 pm

Post by Coolman »

There is an error message:

'Ligne 188 :ArraySize() is not a function, array, macro or linked list'

Add this :

; Author: freak (updated for PB 4.00 by Deeem2031)
Procedure ArraySize(*Array)
ProcedureReturn PeekL(*Array-8)
EndProcedure

great work

However, IrfanView is more efficient ...
*** Excuse my bad English, I uses has translating program ***
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

On PB 4.3, ArraySize() is a native function.
I may look like a mule, but I'm not a complete ass.
Coolman
Enthusiast
Enthusiast
Posts: 103
Joined: Sat Sep 03, 2005 4:07 pm

Post by Coolman »

srod wrote:On PB 4.3, ArraySize() is a native function.
******************
; Library commands: ImageTo8bit() and Save8bitImage()
; Author: Lloyd Gallant (netmaestro)
; Date: December 12, 2008
; Target OS: Microsoft Windows All
; Target Compiler: PureBasic 4.0 and later
; License: Free, unrestricted, no warranty
******************

I thought it was compatible PureBasic 4.00...

However, good to know, I never used a beta version of PureBasic

8)
*** Excuse my bad English, I uses has translating program ***
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

-Fixed a bug where some images were being rendered upside down

-Modified the adaptive colortable routine to avoid placing duplicate entries in the color table

-Removed some small memory leaks

Code is updated in the first post.
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

netmaestro wrote:-Fixed a bug where some images were being rendered upside down
Interested to see how you fixed that part! :) Had decided that the best way was to retrieve the DIB bits first as there seems to be no simple way of getting a hold of a valid bitmapinfoheader structure for the original DIB etc. I think you've just confirmed my supposition! :)

Again, great code.
I may look like a mule, but I'm not a complete ass.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Yes, the trick is to get the DIBits in the same format that you're going to set them. I was taking a shortcut and just feeding SetDIBits the pointer from the object but I see now that you can't do that. The quality difference between this and the professional programs seems to be in the lack of dithering. I have no idea how to do dithering but I'll research it and give it a go. Any thoughts or suggestions on approach would be most appreciated.
BERESHEIT
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

netmaestro wrote:Yes, the trick is to get the DIBits in the same format that you're going to set them. I was taking a shortcut and just feeding SetDIBits the pointer from the object but I see now that you can't do that. The quality difference between this and the professional programs seems to be in the lack of dithering. I have no idea how to do dithering but I'll research it and give it a go. Any thoughts or suggestions on approach would be most appreciated.
http://en.wikipedia.org/wiki/Floyd-Steinberg_dithering
LCD
Enthusiast
Enthusiast
Posts: 206
Joined: Sun Jun 01, 2003 10:55 pm
Location: Austria, Vienna
Contact:

Post by LCD »

Great work! The MSX2 Palette is excellent for ordered dither (I included it in my Retro-X), because you can dither 3, 3 and 2 Bits (8, 8 and 4 levels) and join the bits together.
The adaptive palette calculation is something I was looking for, for the Sprinter 2000 picture conversion.
My PC
Ryzen 9 5950, 64 GB RAM, nVidia RTX A4000, Win 10
Ryzen 7 1700, 32 GB RAM, nVidia RTX A2000, Win 10
User avatar
Blue
Addict
Addict
Posts: 964
Joined: Fri Oct 06, 2006 4:41 am
Location: Canada

Post by Blue »

As you say, netmaestro, the adaptive colortable delivers a truly amazing approximation of the original color distribution.
Very nice work and demonstration.

Now waiting for the dithering procedure to clear up the blotches on that poor girl's skin :shock:
She must be impatient too... :lol:

BTW:
to better compare the original picture with the modified one, i added 3 lines to your example code, just before the Events loop:

Code: Select all

j = hImage
OpenWindow(1,WindowWidth(0)+24,0,ImageWidth(j),ImageHeight(j),"") 
ImageGadget(1,0,0,0,0,ImageID(j))
PB Forums : Proof positive that 2 heads (or more...) are better than one :idea:
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Blue wrote: BTW:
to better compare the original picture with the modified one, i added 3 lines to your example code, just before the Events loop:

Code: Select all

j = hImage
OpenWindow(1,WindowWidth(0)+24,0,ImageWidth(j),ImageHeight(j),"") 
ImageGadget(1,0,0,0,0,ImageID(j))
Cool Code, thanks :!:

For even more comfort, you can add some constants...

Code: Select all

#Eight_BlackWhite=0
#Eight_StandardPalette=1
#Eight_AdaptivePalette=2

hImage = LoadImage(#PB_Any, "girl.jpg")
i = ImageTo8bit(hImage, #Eight_AdaptivePalette,0)
and name the windows "8 Bit Picture" and "Original Picture" - because the new picture can look quite similar like the original (because netmaestro did a brilliant job -- once again)
LCD
Enthusiast
Enthusiast
Posts: 206
Joined: Sun Jun 01, 2003 10:55 pm
Location: Austria, Vienna
Contact:

Post by LCD »

Just changed the code a little for testing 16 colours Palette reduction, and it still looks very okay. It can be easy modified to work with almost any number of colours.
My PC
Ryzen 9 5950, 64 GB RAM, nVidia RTX A4000, Win 10
Ryzen 7 1700, 32 GB RAM, nVidia RTX A2000, Win 10
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Code is updated to work with PB v4.40, should still be fine with earlier versions of PB.
BERESHEIT
Post Reply