Re: SetBits / GetBits gut genug?
Verfasst: 03.11.2018 10:28
Code: Alles auswählen
format MS64 COFF
public nifDitherRGB
section '.text' code readable executable
nifDitherRGB:;*Pixel(Pointer zur RGB Struktur),*Exit(Pointer zum Lezten Pixel),*Error(Pointer zur Error Variable),Factor(Float)
;------------------------------------------ SETUP STACK FRAME
push rbp
mov rbp,rsp
;------------------------------------------ ALLOCATE SPACE FOR LOCAL VARIABLES
sub rsp,48h
;------------------------------------------ SET DEFAULT RETURN
xor rax,rax
;------------------------------------------ POINTER VERIFICATION
cmp rcx,rdx
jnb @f
;------------------------------------------ LOAD FACTOR
mov[rbp-8h],r9
;------------------------------------------ LOAD PIXEL (RGB)
movzx rdx,byte[rcx]
mov[rbp-28h],rdx
movzx rdx,byte[rcx+1h]
mov[rbp-30h],rdx
movzx rdx,byte[rcx+2h]
mov[rbp-38h],rdx
;------------------------------------------ CALCULATE NEW RED
fild dword[rbp-28h] ;Rot
fimul dword[rbp-8h] ;Factor
fistp dword[rbp-28h] ;Ergebnis
mov rax,[rbp-28h] ;Fehler!!! -> erhalte nicht den Wert von (Rot * Faktor)?!
;------------------------------------------ RETURN LABEL
@@:
;------------------------------------------ DEALLOCATE SPACE
add rsp,48h
;------------------------------------------ RESTORE OLD STACK
mov rsp,rbp
pop rbp
ret
Code: Alles auswählen
EnableExplicit
;PB v.6.52 x64 (Windows)
Import "nifDither.obj"
nifDitherRGB(*Pixel,*Exit,*Error,Factor.f)
EndImport
Structure RGB_STRUCT
RGB.a[3]
EndStructure
Global Pixel.RGB_STRUCT
Global Error.i
Global Factor.f
;Testwerte setzen:
Pixel\RGB[0] = 10
Pixel\RGB[1] = 20
Pixel\RGB[2] = 30
Factor = 2
Debug nifDitherRGB(@Pixel,@Pixel + 1,@Error,Factor)
Helle hat geschrieben:Wenn Factor als Float deklariert wird hat r9 damit nichts zu tun. Als 4.Parameter wird Factor dann in xmm3 an die Procedure übergeben (Windows 64-Bit).
Andererseits sind doch die Parameter schon als Global deklariert, also warum die Übergabe-Klimmzüge (und der ganze Klimbim drumrum)?
Code: Alles auswählen
Macro MM(A,B)
(A * B)
EndMacro
MM(Pixel\RGB[0],1.33)
Code: Alles auswählen
lea rbp,[imagebase+5554]
push rbp
pop rbp
movzx r15,byte ptr [rbp+00]
mov [rsp-08],r15
fild qword ptr [rsp-08]
fmul qword ptr [imagebase+502C]
fistp qword ptr [rsp-08]
mov rax,[rsp-08]
ret
Code: Alles auswählen
xmm0[Red,Green]
xmm1[Blue,0]
xmm3[Factor,Factor]
xmm0 * xmm3
xmm1 * xmm3
Code: Alles auswählen
Buffer1 = AllocateMemory(16) ;Werte-Buffer
Buffer2 = AllocateMemory(16) ;Zwischenspeicher
PokeB(Buffer1, 10) ;Beispiel-Werte
PokeB(Buffer1 + 1, 20)
PokeB(Buffer1 + 2, 30)
Factor.f = 0.4
!mov r8,[v_Buffer1] ;Register hier beliebig gewählt
!mov r9,[v_Buffer2]
!lea r10,[v_Factor]
!pshufd xmm2,[r10],0 ;Factor vervielfachen, bleibt unverändert
!pmovzxbd xmm0,[r8] ;4 Integer-Bytes zu 4 Integer-DWords erweitern (SSE4_1)
!cvtdq2ps xmm1,xmm0 ;4 Integer-DWords in 4 Floats konvertieren (SSE2)
!mulps xmm1,xmm2 ;4 Float-Multiplikationen
!cvtps2dq xmm0,xmm1 ;4 Floats in 4 integer-DWords konvertieren
!movups [r9],xmm0 ;4 integer-DWords in Buffer2 speichern
Debug PeekB(Buffer2) ;diese Einzel-Werte (als Bytes) können auch wieder in Buffer1 zurückgeschrieben werden; Buffer2 dadurch wieder verfügbar
Debug PeekB(Buffer2 + 4)
Debug PeekB(Buffer2 + 8)
Code: Alles auswählen
Factor.f = 0.4
Buffer1 = AllocateMemory(16) ;Werte-Buffer
PokeB(Buffer1, 10) ;Beispiel-Werte
PokeB(Buffer1 + 1, 20)
PokeB(Buffer1 + 2, 30)
!mov r8,[v_Buffer1] ;Register hier beliebig gewählt
!lea r10,[v_Factor]
!movups xmm0,[r10] ;über Register wegen Alignment!
!pshufd xmm2,xmm0,0 ;Factor vervielfachen, bleibt unverändert
!pmovzxbd xmm0,[r8] ;4 Integer-Bytes zu 4 Integer-DWords erweitern (SSE4_1)
!cvtdq2ps xmm1,xmm0 ;4 Integer-DWords in 4 Floats konvertieren (SSE2)
!mulps xmm1,xmm2 ;4 Float-Multiplikationen
!cvtps2dq xmm0,xmm1 ;4 Floats in 4 integer-DWords konvertieren
!pextrb byte[r8],xmm0,0b
!pextrb byte[r8+1],xmm0,100b
!pextrb byte[r8+2],xmm0,1000b
Debug PeekB(Buffer1)
Debug PeekB(Buffer1 + 1)
Debug PeekB(Buffer1 + 2)
Code: Alles auswählen
movzx rax,byte[rcx+2h]
movzx rbx,word[rcx]
shl rax,10h
or rax,rbx
Code: Alles auswählen
mov [rsp + 8h],rax
pmovzxbd xmm0,[rsp + 8h]
movups [rdx],xmm0;<- überträgt nur das erste Byte!
Code: Alles auswählen
Buffer1 = AllocateMemory(16) ;Werte-Buffer für Test
!mov rdx,[v_Buffer1]
!mov rax,102030h ;Testwert
!mov [rsp + 8h],rax ;rax auf Stack
!pmovzxbd xmm0,[rsp + 8h] ;4 Bytes vom Stack erweitern auf 4 DWords in xmm0
!movdqu [rdx],xmm0 ;die DWords rein in Buffer1, hier mal als Integers, movups tuts aber auch
;Test:
Debug Hex(PeekL(Buffer1)) ;DWord auslesen, Hex wegen optischen Vergleich
Debug Hex(PeekL(Buffer1 + 4));hier beachten, das DWords ausgelesen werden! Little Endian!
Debug Hex(PeekL(Buffer1 + 8))
Code: Alles auswählen
Buffer1 = AllocateMemory(16) ;Werte-Buffer
!mov rdx,[v_Buffer1]
!mov rax,405060h ;Testwert
!movq xmm1,rax ;rax als Quadword nach xmm1, "movd xmm1,eax" tuts genauso
!pmovzxbd xmm0,xmm1 ;4 (Low-)Bytes von rax in xmm1 erweitern auf 4 DWords in xmm0
!movdqu [rdx],xmm0 ;die DWords rein in Buffer1, hier mal als Integers, movups tuts aber auch
;Test:
Debug Hex(PeekL(Buffer1)) ;DWord auslesen, Hex wegen optischen Vergleich
Debug Hex(PeekL(Buffer1 + 4));hier beachten, das DWords ausgelesen werden! Little Endian!
Debug Hex(PeekL(Buffer1 + 8))
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
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