Danke @Helle für die Assembler Hilfe
Nach längerem basteln will ich nun den aktuellen OBJ - Code und ein PureBasic Beispiel zeigen.
Das Dithering (Atkinson) funktioniert ganz gut allerdings belieben links und ganz unten im Bild unter Umständen Artefakte!
Die Ursache hierfür liegt noch im Dunkeln
Über weiter Ratschläge (vor allem zum Assembler Code) würde ich mich freuen
OBJ:
Code: Alles auswählen
format MS64 COFF
;.......................................
public nifEncodeColor
public nifDither
;.......................................
section '.text' code readable executable
;.......................................
nifEncodeColor:;*Pixel,*Error
push rbp
mov rbp,rsp
sub rsp,8h
;------------------- GET PIXEL COLOR
movzx rax,byte[rcx+2h]
movzx r8,word[rcx]
shl rax,10h
or rax,r8
;------------------- STORE PIXEL COLOR ADDRESS
mov [rsp+8h],rax
;------------------- RESET ORIGINAL PIXEL COLOR
mov byte[rcx],0h
mov word[rcx+1h],0h
;------------------- CALCULATE & SET NEW PIXEL COLOR
cmp byte[rsp+8h],7Fh
ja @f
mov byte[rcx],0FFh
@@:
cmp byte[rsp+9h],7Fh
ja @f
mov byte[rcx+1h],0FFh
@@:
cmp byte[rsp+0Ah],7Fh
ja @f
mov byte[rcx+2h],0FFh
@@:
;------------------- CALCULATE ERROR
mov al,byte[rsp+8h]
sub al,byte[rcx]
mov byte[rdx],al
mov al,byte[rsp+9h]
sub al,byte[rcx+1h]
mov byte[rdx+1h],al
mov al,byte[rsp+0Ah]
sub al,byte[rcx+2h]
mov byte[rdx+2h],al
add rsp,8h
mov rsp,rbp
pop rbp
ret
nifDither:;*Pixel,*Exit,*Error,*Factor - Dank Helle :)
cmp rcx,rdx
ja @f
push rbp
mov rbp,rsp
sub rsp,8h
movzx rax,byte[rcx+2h]
movzx rdx,word[rcx]
shl rax,10h
or rax,rdx
mov [rsp+8h],rax
pmovzxbd xmm0,[r8]
cvtdq2ps xmm1,xmm0
pmovzxbd xmm0,[rsp+8h]
cvtdq2ps xmm3,xmm0
movups xmm0,[r9]
pshufd xmm2,xmm0,0h
mulps xmm1,xmm2
addps xmm1,xmm3
cvtps2dq xmm0,xmm1
pextrb byte[rcx],xmm0,0b
pextrb byte[rcx+1h],xmm0,100b
pextrb byte[rcx+2h],xmm0,1000b
add rsp,8h
mov rsp,rbp
pop rbp
@@:
ret
Beispiel:
Code: Alles auswählen
;PureBasic v.6.52 x64
EnableExplicit
UseJPEGImageDecoder();Unterstützung für JPEG und PNG!
UseJPEG2000ImageDecoder()
UsePNGImageDecoder()
Import "nifDither.obj"
nifEncodeColor.i(*Pixel,*Error)
nifDither.i(*Pixel,*Exit,*Error,*Factor)
EndImport
Structure BITMAP_STRUCT
bmType.l
bmWidth.l
bmHeight.l
bmWidthBytes.l
bmPlanes.w
bmBitsPixel.w
Alignment.b[4]
*bmBits
PixelSize.i
Bytes.i
Exit.i
EndStructure
Structure IMAGE_STRUCT
Id.i
Handle.i
Bitmap.BITMAP_STRUCT
EndStructure
Procedure.i nifFree(*nif.IMAGE_STRUCT)
With *nif
If IsImage(\Id)
FreeImage(\Id)
EndIf
FreeStructure(*nif)
EndWith
EndProcedure
Procedure.i nifBitmap(*nif.IMAGE_STRUCT)
With *nif
If \Handle
If GetObject_(\Handle,SizeOf(BITMAP),@\Bitmap)
\Bitmap\PixelSize = \Bitmap\bmBitsPixel / 8
\Bitmap\Bytes = \Bitmap\bmWidthBytes * \Bitmap\bmHeight
\Bitmap\Exit = \Bitmap\bmBits + \Bitmap\Bytes - \Bitmap\PixelSize
ProcedureReturn #True
EndIf
EndIf
EndWith
EndProcedure
Procedure.i nifEncode(*nif.IMAGE_STRUCT)
Protected ImageX.i
Protected ImageY.i
Protected *Scanline
Protected *Pixel
Protected Index.i
Protected Factor1.f
Protected Factor2.f
With *nif
If \Bitmap\bmBitsPixel = 24
Factor1 = 0.375
Factor2 = 0.125
For ImageY = 0 To \Bitmap\bmHeight - 1
*Scanline = \Bitmap\bmBits +(ImageY * \Bitmap\bmWidthBytes)
For ImageX = 0 To \Bitmap\bmWidth - 1
*Pixel = *Scanline + (ImageX * \Bitmap\PixelSize)
nifEncodeColor(*Pixel,@Error)
nifDither(*Pixel + \Bitmap\PixelSize,\Bitmap\Exit,@Error,@Factor1);Atkinson
nifDither(*Pixel + \Bitmap\bmWidthBytes + \Bitmap\PixelSize,\Bitmap\Exit,@Error,@Factor2)
nifDither(*Pixel + \Bitmap\PixelSize + \Bitmap\PixelSize,\Bitmap\Exit,@Error,@Factor2)
nifDither(*Pixel + \Bitmap\bmWidthBytes,\Bitmap\Exit,@Error,@Factor2)
nifDither(*Pixel + \Bitmap\bmWidthBytes - \Bitmap\PixelSize,\Bitmap\Exit,@Error,@Factor2)
nifDither(*Pixel + \Bitmap\bmWidthBytes + \Bitmap\bmWidthBytes,\Bitmap\Exit,@Error,@Factor2)
Next
Next
ProcedureReturn #True
Else
;Bild mit Alpha!
EndIf
EndWith
EndProcedure
Procedure.i nifHandle(*nif.IMAGE_STRUCT)
With *nif
ProcedureReturn \Handle
EndWith
EndProcedure
Procedure.i nifLoadImage(File.s)
Protected *nif.IMAGE_STRUCT
Protected Timer.q
*nif = AllocateStructure(IMAGE_STRUCT)
If *nif
With *nif
\Id = LoadImage(#PB_Any,File)
If \Id
\Handle = ImageID(\Id)
If nifBitmap(*nif)
Timer = ElapsedMilliseconds()
If nifEncode(*nif)
Timer = ElapsedMilliseconds() - Timer
MessageRequester("","Timer: " + Str(Timer))
ProcedureReturn *nif
EndIf
EndIf
EndIf
nifFree(*nif)
EndWith
EndIf
EndProcedure
Procedure.i nifSaveBitmap(*nif.IMAGE_STRUCT,File.s)
With *nif
ProcedureReturn SaveImage(\Id,File,#PB_ImagePlugin_BMP,#Null,\Bitmap\bmBitsPixel)
EndWith
EndProcedure
Global Image.i
Global File.s
File = "XYZ";<- ÄNDERN!!!
Image = nifLoadImage(File)
If Image
;nifSaveBitmap(Image,"converted_" + File)
If OpenWindow(0,0,0,800,580,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
If StartVectorDrawing(WindowVectorOutput(0))
MovePathCursor(0,0)
DrawVectorImage(nifHandle(Image),$FF,800,580)
EndIf
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
CloseWindow(0)
EndIf
nifFree(Image)
EndIf
End