probably this one more correct, than old one... but anyway it is a little wrong. i am get first 15 different colors from image, but maybe it can be some procedure as Gif Animator do? i mean he can set for image how many colors he can have. he merge almost same colors, so image loose not so many, as my case with first 15 colors. only then make some nearest for 15. it will be more correct. any solution? i mean get image, get 512 colors from allow table colors and take from this 512 only 15 for image. not first 15 as i am do, but make some oprimization into 15 of allowing colors.
Code: Select all
;{
Global Dim FullPalette.l(513)
Dim col.a(8)
col(1) = 0
col(2) = 36
col(3) = 72
col(4) = 109
col(5) = 145
col(6) = 181
col(7) = 219
col(8) = 255
x = 0
y = 0
If CreateImage(0, 256, 32)
If StartDrawing(ImageOutput(0))
For i = 1 To 8
For l = 1 To 8
For k = 1 To 8
Box(x,y,4,4, RGB(col(k),col(l),col(i)))
num + 1
FullPalette(num) = RGB(col(k),col(l),col(i))
x + 4
Next
x - 32
y + 4
Next
x + 32
y - 32
Next
StopDrawing()
EndIf
EndIf ;}
;{
Global Dim Palette.l(1)
Global Dim IndexG.l(255)
EnableASM
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Macro rdx : edx : EndMacro
CompilerEndIf
Macro M_FindNearest(i, st)
!nearestcolor.findnearest#i#_loop:
!mov ecx, [p.v_c#i#]
!test ecx, ecx
!jz nearestcolor.findnearest#i#_cont2
!movzx eax, byte [p.v_Color + 1]
!movzx ecx, ch
!sub eax, ecx
!imul eax, eax
!shl eax, 11
!cmp eax, [p.v_bestd]
!jnc nearestcolor.findnearest#i#_cont1
!mov [p.v_d], eax
!movzx eax, byte [p.v_Color]
!movzx ecx, byte [p.v_c#i#]
!lea edx, [eax + ecx] ; edx = rsum
!sub eax, ecx
!imul eax, eax ; eax = r*r
!lea ecx, [edx + 0x400] ; ecx = $400 + rsum
!imul eax, ecx ; eax = ($400+rsum)*r*r
!add [p.v_d], eax
!movzx eax, byte [p.v_Color + 2]
!movzx ecx, byte [p.v_c#i# + 2]
!sub eax, ecx
!imul eax, eax ; eax = b*b
!neg edx
!add edx, 0x5fe ; edx = $5fe - rsum
!imul eax, edx ; eax = ($5fe-rsum)*b*b
!add eax, [p.v_d]
!cmp eax, [p.v_bestd]
!jnc nearestcolor.findnearest#i#_cont0
!mov [p.v_bestd], eax
!mov eax, [p.v_c#i#]
!mov [p.v_c], eax
!nearestcolor.findnearest#i#_cont0:
mov rdx, *p#i
add rdx, st
mov *p#i, rdx
mov eax, [rdx]
!mov [p.v_c#i#], eax
CompilerIf i = 1
!jmp nearestcolor.findnearest0_loop
CompilerElse
!jmp nearestcolor.findnearest1_loop
CompilerEndIf
!nearestcolor.findnearest#i#_cont1:
!mov dword [p.v_c#i#], 0
!nearestcolor.findnearest#i#_cont2:
CompilerIf i = 1
!cmp dword [p.v_c0], 0
!jnz nearestcolor.findnearest0_loop
CompilerEndIf
EndMacro
Procedure.l FindNearest(Color.l)
; Find the nearest color
Protected.l c, c0, c1, d, bestd = $12000000
Protected.Long *p0, *p1
!movzx eax, byte [p.v_Color + 1]
!mov [p.v_d], eax
*p1 = @Palette(IndexG(d)) : *p0 = *p1 - 4
c0 = *p0\l : c1 = *p1\l
M_FindNearest(0, -4)
M_FindNearest(1, 4)
ProcedureReturn c
EndProcedure
Procedure CatchPalette(*MemoryAddress.Long, NumColors.i)
; Catch a palette from memory
Protected.i i, j = 1, t
ReDim Palette(NumColors + 1)
Palette(0) = 0 : Palette(NumColors + 1) = 0
For i = 1 To NumColors
Palette(i) = $ff000000 | *MemoryAddress\l
Debug Hex(Palette(i))
*MemoryAddress + 4
Next
SortStructuredArray(Palette(), 0, 0, #PB_Unicode, 1, NumColors)
For i = 0 To 255
IndexG(i) = j
While ((Palette(j) >> 8) & $ff) = i And j < NumColors
j + 1
Wend
IndexG(i) = (IndexG(i) + j) >> 1
Next
EndProcedure
DisableASM
;}
; fill 1 to palette. 1 like marker, says this slot is empty.
Dim ColorArr(16)
For i = 1 To 15
ColorArr(i) = 1
Next
color.i
If LoadImage(1, "AC-130.bmp")
SetClipboardImage(1)
EndIf
If GetClipboardImage(1, 32)
CatchPalette(@FullPalette(), 513) ; accessible colors
If OpenWindow(0, 100, 200, 500, 360, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
ImageGadget(10, 10, 10, 96, 56, ImageID(1))
; get first 15 colors. (0 color is purple for transparent)
If StartDrawing(ImageOutput(1))
y = 0
While y < 56
x = 0
While x < 96
bingo = 0
color = Point(x, y)
color = FindNearest(color)
For i = 1 To 15
If ColorArr(i) = color
; already have this color in a palette
bingo = 1
Break
EndIf
Next
If bingo = 0
For i = 1 To 15
If ColorArr(i) = 1
; this slot is empty
ColorArr(i) = color
bingo = 1
Debug "catch some color " + Str(color)
Break
EndIf
Next
If bingo = 0
Debug "all passible colors is catch, ignore others"
Break
EndIf
EndIf
x + 1
Wend
y + 1
Wend
StopDrawing()
EndIf
; create some palette images and gadgets for show
For i = 0 To 15
CreateImage(100 + i, 20, 20, 32, ColorArr(i))
ImageGadget(12 + i, 20 + i * 21, 150, 20, 20, ImageID(100+i))
Next
CopyImage(1, 2)
; now catch from 16 colors
CatchPalette(@ColorArr(), 16)
; repaint with 16 colors
If StartDrawing(ImageOutput(2))
y = 0
While y < 56
x = 0
While x < 96
Plot(x, y, FindNearest(Point(x, y)))
x + 1
Wend
y + 1
Wend
StopDrawing()
EndIf
ImageGadget(11, 10, 70, 96, 56, ImageID(2))
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_CloseWindow ; If the user has pressed on the close button
Quit = 1
EndIf
Until Quit = 1
EndIf
EndIf
End