(ASM) Calculating the Inverse colour of a 24-bit colour

Started by Theo Gottwald, June 06, 2007, 02:46:05 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Theo Gottwald

One of those many ASM Gems, you need - or not.
In this case, you see an example how to deal with ASM and BYREF Parameter.


' inverts the color BYREF
' May not work if the colour includes Alpha-channels, because the whole number is been inverted.
'
' invertiert variable mit farbwert (Komplemtärfarbe durch invertierung (NOT) Rückgabe BYREF
SUB X_HP(BYREF rgbColor AS LONG)
!mov eax,rgbColor ' eax hat 24-bit farbe
!mov ecx,[eax] ' get Value from BYREF
!not ecx           ' Farbe invertieren
!mov ebx,rgbColor
!mov [ebx],ecx
END SUB


In DisASM things look like expected.


4023CA 8B4508                 MOV EAX, DWORD PTR [EBP+08]
4023CD 8B08                   MOV ECX, DWORD PTR [EAX]
4023CF F7D1                   NOT  ECX
4023D1 8B5D08                 MOV EBX, DWORD PTR [EBP+08]
4023D4 890B                   MOV DWORD PTR [EBX], ECX
4023D6 8D65F4                 LEA ESP, DWORD PTR [EBP-0C]
4023D9 5F                     POP EDI
4023DA 5E                     POP ESI
4023DB 5B                     POP EBX
4023DC 5D                     POP EBP
4023DD C20400                 RET NEAR 0004



Here is another one, which returns the colours in RGB.


' returns INVERSE Colour from 24-bit in RGB Parts
'
SUB X_HN(BYVAL rgbColor AS LONG,BYREF Red AS BYTE,BYREF Green AS BYTE,BYREF Blue AS BYTE)
!mov eax,rgbColor ' eax hat 24-bit farbe
!not eax           ' Farbe invertieren
!mov rgbColor,eax

!mov eax,rgbColor
!mov ebx,Red
!mov [ebx],al
!shr eax,8
!mov ebx,Green
!mov [ebx],al
!shr eax,8
!mov ebx,Blue
!mov [ebx],al
END SUB
         

Charles Pegge

#1
Here is a trick for preserving the alpha channel while inverting the r g b.
instead of NOT ecx


!xor ecx &h00ffffff


And if you are preparing an image for display in Opengl, the R and B bytes need to be swapped so instead of MOVing the whole 32 bit word:


!mov cl, [eax]
!mov ch,[eax+2]
!mov [eax+2],cl
!mov [eax],ch


Theo Gottwald

@Charles,
I have just added the code tags for better readability.
Can you provide the complete Subroutine, then people can just copy and paste it?

Charles Pegge

#3
I was just offering suggestions rather than code, Theo  :)

Currently I am without Microsoft or Powerbasic, working on a dedicated Linux box. Do you mind examples in Freebasic?  I dont want to confuse anyone. There are a few differences, some subtle.

Theo Gottwald

#4
I don't Mind Freebasic, just have the wish, that you make a note in the title like this:

(FREEBASIC) titletext ....

then noone will be confused that it doesnt compile "as is" with PB.

While I can do that also :-).


' returns INVERSE Colour from 24-bit in RGB Parts, preserves Alpha-Channel
'
SUB X_HN(BYVAL rgbColor AS LONG,BYREF Red AS BYTE,BYREF Green AS BYTE,BYREF Blue AS BYTE)
!mov eax,rgbColor ' eax hat 24-bit farbe
!xor eax &h00ffffff
!mov rgbColor,eax

!mov eax,rgbColor
!mov ebx,Red
!mov [ebx],al
!shr eax,8
!mov ebx,Green
!mov [ebx],al
!shr eax,8
!mov ebx,Blue
!mov [ebx],al
END SUB

Charles Pegge

#5
This does an entire image in one go.

Supposing your image is held in an array of LONG integers:
Pass the location of he start of the image and the number of pixels:

Example:

InvertImage(varptr(img(0)), 60000 )

PS: I have just optimised the routine by operating directly on the pixels without loading them into the eax register.


' Converts a 32 bit RGBA  Image into its INVERSE Colour while preserving the Alpha-Channel
'
SUB InvertImage(BYVAL image AS LONG PTR, BYVAL size AS LONG)

  ! mov edx, image
  ! mov ecx,size
'  safety checks
  ! cmp edx, 0
  ! jle xit
  ! cmp ecx, 0
  ! jle xit
' main code
nextpixel:
  ! xor [edx], &h00ffffff
  ! add edx, 4
  ! dec ecx
  ! jg nextpixel
xit:
END SUB