ColorMatrix filter

Share your advanced PureBasic knowledge/code with the community.
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: ColorMatrix filter

Post by c4s »

Looks really interesting!

A couple of ASM-newbie questions: Is this for Windows only? Is there a way to detect if SSE2 is available? And if it's not available, what would be a fallback solution that would still work with the provided "framework"?
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: ColorMatrix filter

Post by wilbert »

c4s wrote:Looks really interesting!

A couple of ASM-newbie questions: Is this for Windows only? Is there a way to detect if SSE2 is available? And if it's not available, what would be a fallback solution that would still work with the provided "framework"?
The code is cross platform. I tested it on OS X and Windows but I see no reason why it shouldn't work on Linux also.

You can detect if SSE2 is supported

Code: Select all

Procedure HasSSE2()
  !mov eax, 1
  !cpuid
  !xor eax, eax
  !bt edx, 26
  !rcl eax, 1
  ProcedureReturn
EndProcedure

Debug HasSSE2()
You could create a similar filter using PureBasic code only as a fallback but it would be much slower.
It might not be good but personally I don't code fallbacks for SSE2. I just tell it requires SSE2.
My main OS is OS X and all Intel Macs have SSE2. Windows 8 also requires SSE2.
Intel introduced SSE2 in 2001, AMD followed in 2003.
SSE2 has a lot of advantages. For the few people that still use a 10 year old computer ... sorry :(
Windows (x64)
Raspberry Pi OS (Arm64)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: ColorMatrix filter

Post by wilbert »

Just for once a fallback and some comparisons.

Fallback for CM_Apply

Code: Select all

Procedure.l CM_ApplyNoSSE2(Color.l, *Filter.CM_Filter)
  Protected.f r, r0, g, g0, b, b0, a, a0
  Protected *M.CM_Matrix = (*Filter + 15) & -16
  r0 = Red(Color)
  g0 = Green(Color)
  b0 = Blue(Color)
  a0 = Alpha(Color)
  r = *M\m[0] * r0 + *M\m[4] * g0 + *M\m[8] * b0 + *M\m[12] * a0 + *M\m[16]
  g = *M\m[1] * r0 + *M\m[5] * g0 + *M\m[9] * b0 + *M\m[13] * a0 + *M\m[17]
  b = *M\m[2] * r0 + *M\m[6] * g0 + *M\m[10] * b0 + *M\m[14] * a0 + *M\m[18]
  a = *M\m[3] * r0 + *M\m[7] * g0 + *M\m[11] * b0 + *M\m[15] * a0 + *M\m[19]
  If r < 0 : r = 0 : EndIf
  If g < 0 : g = 0 : EndIf
  If b < 0 : b = 0 : EndIf
  If a < 0 : a = 0 : EndIf
  If r > 255 : r = 255 : EndIf
  If g > 255 : g = 255 : EndIf
  If b > 255 : b = 255 : EndIf
  If a > 255 : a = 255 : EndIf
  ProcedureReturn RGBA(r, g, b, a)
EndProcedure
Speed comparison of a 32 bit image with 3488 x 2616 pixels on OS X

Point / Plot without a filter : 336 ms
Point / Plot with CM_Apply (SSE2) : 486 ms
Point / Plot with CM_Apply fallback (No SSE2) : 1094 ms
CM_ApplyToImage (SSE2) : 40 ms

You see that the SSE2 routine optimized for 32 bit images working directly on the drawing buffer is over 25x faster compared to the fallback routine.
Last edited by wilbert on Fri Aug 09, 2013 11:40 am, edited 1 time in total.
Windows (x64)
Raspberry Pi OS (Arm64)
c4s
Addict
Addict
Posts: 1981
Joined: Thu Nov 01, 2007 5:37 pm
Location: Germany

Re: ColorMatrix filter

Post by c4s »

@wilbert
Thanks for your reply and the explanation (edit: and the code ;)).

The reason I'm asking for a fallback isn't really to support old computers but rather that I don't understand too much of ASM. I would appreciate a PB-only solution simply for the sake of understanding what's going on under the hood...
If any of you native English speakers have any suggestions for the above text, please let me know (via PM). Thanks!
User avatar
BasicallyPure
Enthusiast
Enthusiast
Posts: 539
Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA

Re: ColorMatrix filter

Post by BasicallyPure »

I have updated the code for my demo program.
It seems to be working as intended now.
I still want to add the 'save as' option.

@Wilbert,
I found a problem with your CM_ApplyToImage() procedure.

Code: Select all

Procedure CM_ApplyToImage(Image, *Filter.CM_Filter)
  
  Protected.i w, x, y, max_x, max_y
  Protected.i addr, pitch, byte_order
  
  ;If StartDrawing(ImageOutput(0)) ; <--- this is wrong
  If StartDrawing(ImageOutput(Image)) ; <--- this is what it should be
    w = OutputWidth()
    max_y = OutputHeight() - 1
What is the 'Black and White' filter exactly?
It is not really monochrome but seems to be a different form of gray scale.

BP.

edit:
Experimenting with the Black and White reveals that it is like a grayscale with very high contrast.
You can get something similar by using grayscale then adjusting contrast to maximum then adjusting
contrast to maximum again.

I find that decreasing brightness some before using Black and White gives better results.
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: ColorMatrix filter

Post by wilbert »

BasicallyPure wrote:What is the 'Black and White' filter exactly?
It is not really monochrome but seems to be a different form of gray scale.
Thanks for pointing out the bug in the code. I corrected it.
The black and white filter is just one I found on the internet as it is :wink:
Windows (x64)
Raspberry Pi OS (Arm64)
Post Reply