This function will create a grayscale version of the specified input image and output it via the output image. See the comments in the function for more information.
; Converts the pixels in 'input_image' to grayscale and stores them in 'output_image'. The two images can either be the same image or different images.
; The output image should already exist and must be the same size as the input image. A zero will be returned if these conditions aren't met.
; Returns 1 on success and 0 on failure.
Code: Select all
Procedure.i GrayscaleImage( input_image, output_image )
; Converts the pixels in 'input_image' to grayscale and stores them in 'output_image'. The two images can be the same image or different images.
; The output image should already exist and must be the same size as the input image. A zero will be returned if these conditions aren't met.
; Returns 1 on success and 0 on failure.
If ( IsImage( input_image ) = 0 ) Or ( IsImage( output_image ) = 0 ) : ProcedureReturn 0 : EndIf ; Ensure that both images exist.
Protected image_width = ImageWidth( input_image )
Protected image_height = ImageHeight( input_image )
If ( image_width <> ImageWidth( output_image ) ) Or ( image_height <> ImageHeight( output_image ) ) : ProcedureReturn 0 : EndIf ; Ensure that both images are the same size.
Protected image_max_x = image_width - 1
Protected image_max_y = image_height - 1
Protected Dim TempImageArray.a( image_max_x, image_max_y )
Protected pixel, result
If StartDrawing( ImageOutput( input_image ) )
For x = 0 To image_max_x
For y = 0 To image_max_y
pixel = Point( x, y )
; https://www.purebasic.fr/english/viewtopic.php?t=79054
; http://poynton.ca/notes/colour_and_gamma/ColorFAQ.txt
; https://www.tutorialspoint.com/dip/grayscale_to_rgb_conversion.htm
; https://stackoverflow.com/questions/687261/converting-rgb-to-grayscale-intensity
TempImageArray( x, y ) = Red( pixel ) * 0.2126 + Green( pixel ) * 0.7152 + Blue( pixel ) * 0.0722 ; ; Y = 0.2126 * R + 0.7152 * G + 0.0722 * B;
Next
Next
StopDrawing()
If StartDrawing( ImageOutput( output_image ) )
For x = 0 To image_max_x
For y = 0 To image_max_y
pixel = TempImageArray( x, y )
Plot( x, y, RGB( pixel, pixel, pixel ) )
Next
Next
StopDrawing()
result = 1
EndIf
EndIf
ProcedureReturn result
EndProcedure
; --
This version uses 'GrayscaleImageCallback' for a 50% speed boost. Unlike the previous version, it creates a new separate output image within the function and returns the PureBasic ID of the resulting grayscale output image.
; Converts the pixels in 'input_image' to grayscale and returns the PureBasic ID of the resulting output image. The input image will be unaffected with a new image being created for the grayscale version.
; This function requires the 'GrayscaleImageCallback' function above.
; Returns the PureBasic ID of the resulting output image on success, and 0 on failure.
Code: Select all
; - Method 2 using 'CustomFilterCallback' -
Procedure.i GrayscaleImageCallback( x, y, source_color, target_color )
Protected brightness.a = Red( source_color ) * 0.2126 + Green( source_color ) * 0.7152 + Blue( source_color ) * 0.0722
ProcedureReturn RGBA( brightness.a, brightness.a, brightness.a, 255 )
EndProcedure
Procedure.i GrayscaleImage( input_image )
; Converts the pixels in 'input_image' to grayscale and returns the PureBasic ID of the resulting output image. The input image will be unaffected with a new image being created for the grayscale version.
; This function requires the 'GrayscaleImageCallback' function above.
; Returns the PureBasic ID of the resulting output image on success, and 0 on failure.
If IsImage( input_image ) = 0 : ProcedureReturn 0 : EndIf ; Ensure that the input image exists.
Protected image_width = ImageWidth( input_image )
Protected image_height = ImageHeight( input_image )
Protected output_image = CreateImage( #PB_Any, image_width, image_height, 24 )
If output_image = 0 : ProcedureReturn 0 : EndIf ; Ensure that the output image was created.
If StartDrawing( ImageOutput( output_image ) )
DrawingMode( #PB_2DDrawing_CustomFilter )
CustomFilterCallback( @GrayscaleImageCallback() )
DrawImage( ImageID( input_image ), 0, 0 )
StopDrawing()
Else
FreeImage( output_image ) : output_image = 0
EndIf
ProcedureReturn output_image
EndProcedure
; --
Test code using both methods.
Code: Select all
; NOTE: Change the filepath stored in 'G_input_image_filepath.s' to that of a JPEG image that is available on your computer.
UseJPEGImageDecoder()
UseJPEGImageEncoder()
ElapsedMilliseconds() ; Run this once to initialize it.
Global G_input_image_filepath.s = "C:\Users\axe73\Desktop\My Files\Pixabay Animal Images\USED\rabbit-1903016.jpg"
Global G_input_image = LoadImage( #PB_Any, G_input_image_filepath.s )
If G_input_image = 0 : MessageRequester( "FATAL ERROR", "Unable to load input image." ) : End : EndIf
Global G_output_image
; ================
; - Method 1 using an array as an intermediate -
Procedure.i GrayscaleImage1( input_image, output_image )
; Converts the pixels in 'input_image' to grayscale and stores them in 'output_image'. The two images can be the same image or different images.
; The output image should already exist and must be the same size as the input image. A zero will be returned if these conditions aren't met.
; Returns 1 on success and 0 on failure.
If ( IsImage( input_image ) = 0 ) Or ( IsImage( output_image ) = 0 ) : ProcedureReturn 0 : EndIf ; Ensure that both images exist.
Protected image_width = ImageWidth( input_image )
Protected image_height = ImageHeight( input_image )
If ( image_width <> ImageWidth( output_image ) ) Or ( image_height <> ImageHeight( output_image ) ) : ProcedureReturn 0 : EndIf ; Ensure that both images are the same size.
Protected image_max_x = image_width - 1
Protected image_max_y = image_height - 1
Protected Dim TempImageArray.a( image_max_x, image_max_y )
Protected pixel, result
If StartDrawing( ImageOutput( input_image ) )
For x = 0 To image_max_x
For y = 0 To image_max_y
pixel = Point( x, y )
; https://www.purebasic.fr/english/viewtopic.php?t=79054
; http://poynton.ca/notes/colour_and_gamma/ColorFAQ.txt
; https://www.tutorialspoint.com/dip/grayscale_to_rgb_conversion.htm
; https://stackoverflow.com/questions/687261/converting-rgb-to-grayscale-intensity
TempImageArray( x, y ) = Red( pixel ) * 0.2126 + Green( pixel ) * 0.7152 + Blue( pixel ) * 0.0722 ; ; Y = 0.2126 * R + 0.7152 * G + 0.0722 * B;
Next
Next
StopDrawing()
If StartDrawing( ImageOutput( output_image ) )
For x = 0 To image_max_x
For y = 0 To image_max_y
pixel = TempImageArray( x, y )
Plot( x, y, RGB( pixel, pixel, pixel ) )
Next
Next
StopDrawing()
result = 1
EndIf
EndIf
ProcedureReturn result
EndProcedure
; ================
; - Method 2 using 'CustomFilterCallback' -
Procedure.i GrayscaleImageCallback( x, y, source_color, target_color )
Protected brightness.a = Red( source_color ) * 0.2126 + Green( source_color ) * 0.7152 + Blue( source_color ) * 0.0722
ProcedureReturn RGBA( brightness.a, brightness.a, brightness.a, 255 )
EndProcedure
Procedure.i GrayscaleImage2( input_image )
; Converts the pixels in 'input_image' to grayscale and returns the PureBasic ID of the resulting output image. The input image will be unaffected with a new image being created for the grayscale version.
; This function requires the 'GrayscaleImageCallback' function above.
; Returns the PureBasic ID of the resulting output image on success, and 0 on failure.
If IsImage( input_image ) = 0 : ProcedureReturn 0 : EndIf ; Ensure that the input image exists.
Protected image_width = ImageWidth( input_image )
Protected image_height = ImageHeight( input_image )
Protected output_image = CreateImage( #PB_Any, image_width, image_height, 24 )
If output_image = 0 : ProcedureReturn 0 : EndIf ; Ensure that the output image was created.
If StartDrawing( ImageOutput( output_image ) )
DrawingMode( #PB_2DDrawing_CustomFilter )
CustomFilterCallback( @GrayscaleImageCallback() )
DrawImage( ImageID( input_image ), 0, 0 )
StopDrawing()
Else
FreeImage( output_image ) : output_image = 0
EndIf
ProcedureReturn output_image
EndProcedure
; ================
t1 = ElapsedMilliseconds()
G_output_image = CreateImage( #PB_Any, ImageWidth( G_input_image ), ImageHeight( G_input_image ), 24 ) : If G_output_image = 0 : MessageRequester( "FATAL ERROR", "Unable to create output image for GrayscaleImage1." ) : End : EndIf
Global G_result = GrayscaleImage1( G_input_image, G_output_image )
t2 = ElapsedMilliseconds()
If G_result = 0 : MessageRequester( "FATAL ERROR", "GrayscaleImage1 failed." ) : End : EndIf
SaveImage( G_output_image, "output-1.jpg", #PB_ImagePlugin_JPEG, 10, 24 )
; --
t3 = ElapsedMilliseconds()
G_output_image = GrayscaleImage2( G_input_image )
t4 = ElapsedMilliseconds()
If G_output_image
SaveImage( G_output_image, "output-2.jpg", #PB_ImagePlugin_JPEG, 10, 24 )
Else
MessageRequester( "FATAL ERROR", "GrayscaleImage2 failed." ) : End
EndIf
MessageRequester( "Time Results (millisecs)", "GrayscaleImage1: " + Str( t2 - t1 ) + " | GrayscaleImage2: " + Str( t4 - t3 ) )