Luminosité Image

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Luminosité Image

Message par Mesa »

J'ai récupéré un code sur le forum anglais qui avait l'air prometteur concernant les manipulation sur les images (sans poo).
http://www.purebasic.fr/english/viewtop ... 12&t=38897

Mais ça ne fonctionne pas bien et je ne vois pas pourquoi.

Le code desous essaie de changer la luminosité d'un bmp.

Code : Tout sélectionner

;- Structures

Structure FASTIMAGEINFO
  ptrImageBuffer.l
  imgWidth.w
  imgHeight.w
  imgDepth.b
EndStructure

;- Macros

Macro FastRGB(r, g, b)
  
  ; Faster equivalent of RGB(), although only suitable for integers
  
  (((r << 8 + g) << 8 ) + b)
  
EndMacro

Macro FastRed(color)
  
  ; Faster equivalent of Red(), although only suitable for integers
  
  ((color & $FF0000) >> 16)
  
EndMacro

Macro FastGreen(color)
  
  ; Faster equivalent of Green(), although only suitable for integers
  
  ((color & $FF00) >> 8)
  
EndMacro

Macro FastBlue(color)
  
  ; Faster equivalent of Blue(), although only suitable for integers
  
  (color & $FF)
  
EndMacro

Macro ReverseRGB(color)
  
  ; Changes RGB to BGR or vice versa
  
  ((color & $FF) << 16 | (color & $FF00) | (color & $FF0000) >> 16)
  
EndMacro

Macro FastPlot(image_info, x, y, color)
  PokeL(image_info\ptrImageBuffer + (image_info\imgWidth * (y) + x) << 2, color)
EndMacro

Macro FastPoint(image_info, x, y)
  (PeekL(image_info\ptrImageBuffer + (image_info\imgWidth * (y) + x) << 2) & $FFFFFF)
EndMacro

;- Procedures

Procedure CopyImageToMemory(image_no.l, *mem)
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    Protected TemporaryDC.l, TemporaryBitmap.BITMAP, TemporaryBitmapInfo.BITMAPINFO
    TemporaryDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
    GetObject_(ImageID(image_no), SizeOf(BITMAP), TemporaryBitmap.BITMAP)
    TemporaryBitmapInfo\bmiHeader\biSize        = SizeOf(BITMAPINFOHEADER)
    TemporaryBitmapInfo\bmiHeader\biWidth       = TemporaryBitmap\bmWidth
    TemporaryBitmapInfo\bmiHeader\biHeight      = -TemporaryBitmap\bmHeight
    TemporaryBitmapInfo\bmiHeader\biPlanes      = 1
    TemporaryBitmapInfo\bmiHeader\biBitCount    = 32
    TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB
    GetDIBits_(TemporaryDC, ImageID(image_no), 0, TemporaryBitmap\bmHeight, *mem, TemporaryBitmapInfo, #DIB_RGB_COLORS)
    DeleteDC_(TemporaryDC)
  CompilerElse
    Protected x.l, y.l, mem_pos.l
    mem_pos = 0
    StartDrawing(ImageOutput(image_no))
    For y = 0 To ImageHeight(image_no) - 1
      For x = 0 To ImageWidth(image_no) - 1
        PokeL(*mem + mem_pos, ReverseRGB(Point(x, y)))
        mem_pos + 4
      Next
    Next
    StopDrawing()
  CompilerEndIf
EndProcedure

Procedure CopyMemoryToImage(*mem, image_no.l)
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    Protected TemporaryDC.l, TemporaryBitmap.BITMAP, TemporaryBitmapInfo.BITMAPINFO
    TemporaryDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
    GetObject_(ImageID(image_no), SizeOf(BITMAP), TemporaryBitmap.BITMAP)
    TemporaryBitmapInfo\bmiHeader\biSize        = SizeOf(BITMAPINFOHEADER)
    TemporaryBitmapInfo\bmiHeader\biWidth       = TemporaryBitmap\bmWidth
    TemporaryBitmapInfo\bmiHeader\biHeight      = -TemporaryBitmap\bmHeight
    TemporaryBitmapInfo\bmiHeader\biPlanes      = 1
    TemporaryBitmapInfo\bmiHeader\biBitCount    = 32
    TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB
    SetDIBits_(TemporaryDC, ImageID(image_no), 0, TemporaryBitmap\bmHeight, *mem, TemporaryBitmapInfo, #DIB_RGB_COLORS)
    DeleteDC_(TemporaryDC)
  CompilerElse
    Protected x.l, y.l, mem_pos.l
    mem_pos = 0
    StartDrawing(ImageOutput(image_no))
    For y = 0 To ImageHeight(image_no) - 1
      For x = 0 To ImageWidth(image_no) - 1
        Plot(x, y, ReverseRGB(PeekL(*mem + mem_pos)))
        mem_pos + 4
      Next
    Next   
    StopDrawing()
  CompilerEndIf
EndProcedure

;- Includes

;XIncludeFile "FastImage.pbi"

;- Constants

#MaxDistance = $FFFFFFF
#MaxDitherMethods = 128
#MaxDitherMatrixSize = 256

Enumeration
  #RotateImageLeft
  #RotateImageRight
EndEnumeration

Enumeration
  #FlipImageHorizontal
  #FlipImageVertical
EndEnumeration

Enumeration
  #GrayscaleImage_Mean
  #GrayscaleImage_Weighted
  #GrayscaleImage_Weighted2
EndEnumeration

;- Structures

Structure hsl
  h.f
  s.f
  l.f
EndStructure

Structure hsv
  h.f
  s.f
  v.f
EndStructure

;- Macros

Macro NormalizeRGB(r, g, b)
  
  ; ***************************************************************************
  ;
  ; Function: Truncates RGB values to a range of 0 to 255
  ;
  ; ***************************************************************************
  
  If r > 255
    r = 255
  ElseIf r < 0
    r = 0
  EndIf
  
  If g > 255
    g = 255
  ElseIf g < 0
    g = 0
  EndIf
  
  If b > 255
    b = 255
  ElseIf b < 0
    b = 0
  EndIf
  
EndMacro

Macro ContrastStretch_CalculateThresholds(Array, min, max)
  
  
  ; ***************************************************************************
  ;
  ; Function: Calculate thresholds for performing contrast stretching
  ;
  ; Notes:    Part of the ContrastStretchImage() procedure
  ;
  ; ***************************************************************************
  
  color = 0
  count = 0
  Repeat
    count + Array(color)
    color + 1
  Until count > lower_target Or color > 255
  min = color - 1
  color = 255
  count = 0
  Repeat
    count + Array(color)
    color - 1
  Until count > upper_target Or color < 0
  max = color + 1
  If max = min
    FreeMemory(*mem)
    ProcedureReturn 0
  EndIf
  
EndMacro

;- Procedures

Procedure.l AdjustImageBrightness(image_no.l, brightness.l = 0, r_brightness.l = 0, g_brightness.l = 0, b_brightness.l = 0)
  
  ; ***************************************************************************
  ;
  ; Function: Adjusts the brightness of an image
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; Notes:    Brightness values can be between -255 and 255
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l
  Protected color.l, r.l, g.l, b.l
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  If brightness < -255 Or brightness > 255
    ProcedureReturn 0
  EndIf
  
  If r_brightness < -255 Or r_brightness > 255
    ProcedureReturn 0
  EndIf
  
  If g_brightness < -255 Or g_brightness > 255
    ProcedureReturn 0
  EndIf
  
  If b_brightness < -255 Or b_brightness > 255
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    r = FastRed(color) + r_brightness + brightness
    g = FastGreen(color) + g_brightness + brightness
    b = FastBlue(color) + b_brightness + brightness
    NormalizeRGB(r, g, b)
    PokeL(*mem + mem_pos, FastRGB(r, g, b))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l AdjustImageContrast(image_no.l, contrast.f = 0, r_contrast.f = 0, g_contrast.f = 0, b_contrast.f = 0)
  
  ; ***************************************************************************
  ;
  ; Function: Adjusts the contrast of an image
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; Notes:    Contrast values can be between -255 to 255
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l
  Protected color.l, r.l, g.l, b.l
  Protected contrast_correction.f
  Protected r_contrast_correction.f
  Protected g_contrast_correction.f
  Protected b_contrast_correction.f
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  If contrast < -255 Or contrast > 255
    ProcedureReturn 0
  EndIf
  
  If r_contrast < -255 Or r_contrast > 255
    ProcedureReturn 0
  EndIf
  
  If g_contrast < -255 Or g_contrast > 255
    ProcedureReturn 0
  EndIf
  
  If b_contrast < -255 Or b_contrast > 255
    ProcedureReturn 0
  EndIf
  
  contrast_correction = (contrast + 255) * 259 / (255 * (259 - contrast)) 
  r_contrast_correction = (r_contrast + 255) * 259 / (255 * (259 - r_contrast))
  g_contrast_correction = (g_contrast + 255) * 259 / (255 * (259 - g_contrast))
  b_contrast_correction = (b_contrast + 255) * 259 / (255 * (259 - b_contrast))
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    r = (FastRed(color) - 128) * r_contrast_correction * contrast_correction + 128
    g = (FastGreen(color) - 128) * g_contrast_correction * contrast_correction + 128
    b = (FastBlue(color) - 128) * b_contrast_correction * contrast_correction + 128
    NormalizeRGB(r, g, b)
    PokeL(*mem + mem_pos, FastRGB(r, g, b))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l AdjustImageGamma(image_no.l, gamma.f = 1, r_gamma.f = 1, g_gamma.f = 1, b_gamma.f = 1)
  
  ; ***************************************************************************
  ;
  ; Function: Adjusts the gamma curve of an image
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l
  Protected color.l, r.l, g.l, b.l
  Protected gamma_correction.f
  Protected r_gamma_correction.f
  Protected g_gamma_correction.f
  Protected b_gamma_correction.f
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  If gamma <= 0 Or gamma >= 8
    ProcedureReturn 0
  EndIf
  
  If r_gamma <= 0 Or r_gamma >= 8
    ProcedureReturn 0
  EndIf
  
  If g_gamma <= 0 Or g_gamma >= 8
    ProcedureReturn 0
  EndIf
  
  If b_gamma <= 0 Or b_gamma >= 8
    ProcedureReturn 0
  EndIf
  
  gamma_correction = 1 / gamma
  r_gamma_correction = 1 / r_gamma
  g_gamma_correction = 1 / g_gamma
  b_gamma_correction = 1 / b_gamma
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    r = FastRed(color)
    g = FastGreen(color)
    b = FastBlue(color)
    r = 255 * Pow(r / 255, r_gamma_correction)
    r = 255 * Pow(r / 255, gamma_correction)
    g = 255 * Pow(g / 255, g_gamma_correction)
    g = 255 * Pow(g / 255, gamma_correction)
    b = 255 * Pow(b / 255, b_gamma_correction)
    b = 255 * Pow(b / 255, gamma_correction)
    NormalizeRGB(r, g, b)
    PokeL(*mem + mem_pos, FastRGB(r, g, b))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l CropImage(image_no.l, x.l, y.l, width.l, height.l)
  
  ; ***************************************************************************
  ;
  ; Function: Crops an image to given size
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected temp_image_no.l
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  If width = 0 Or height = 0
    ProcedureReturn 0
  EndIf
  
  If x + width > ImageWidth(image_no) Or y + height > ImageHeight(image_no)
    ProcedureReturn 0
  EndIf
  
  temp_image_no = GrabImage(image_no, #PB_Any, x, y, width, height)
  
  If temp_image_no = 0
    ProcedureReturn 0
  EndIf
  
  FreeImage(image_no)
  CopyImage(temp_image_no, image_no)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l ScrollImage(image_no.l, scroll_x.l, scroll_y.l, wrap.l = 0)
  
  ; ***************************************************************************
  ;
  ; Function: Scrolls an image about with optional wrapping
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem_source.l, *mem_target.l, mem_size.l
  Protected x.l, y.l, target_x.l, target_y.l
  Protected width.l, height.l
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  width = ImageWidth(0)
  height = ImageHeight(0)
  
  If scroll_x > width Or scroll_y > height
    ProcedureReturn 0
  EndIf
  
  mem_size = width * height << 2
  *mem_source = AllocateMemory(mem_size)
  If *mem_source = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem_source)
  FreeImage(image_no)
  
  *mem_target = AllocateMemory(mem_size)
  If *mem_target = 0
    
    ; Attempt to restore source image when memory allocation fails
    
    If CreateImage(image_no, width, height, 32)
      CopyMemoryToImage(*mem_source, image_no)
    EndIf
    FreeMemory(*mem_source)
    ProcedureReturn 0
  EndIf
  
  For y = 0 To height - 1
    For x = 0 To width - 1
      Select wrap
        Case 1
          target_x = (x + scroll_x) % width
          target_y = (y + scroll_y) % height       
          If target_x < 0
            target_x = width + target_x
          EndIf
          If target_y < 0
            target_y = height + target_y
          EndIf
          PokeL(*mem_target + (target_y * width + target_x) << 2, PeekL(*mem_source + (y * width + x) << 2))
        Default
          target_x = (x + scroll_x)
          target_y = (y + scroll_y)
          If target_x >= 0 And target_x < width And target_y >= 0 And target_y < height
            PokeL(*mem_target + (target_y * width + target_x) << 2, PeekL(*mem_source + (y * width + x) << 2))
          EndIf
      EndSelect
    Next
  Next
  
  FreeMemory(*mem_source)
  
  If CreateImage(image_no, width, height, 32) = 0
    FreeMemory(*mem_target)
    ProcedureReturn 0
  EndIf
  
  CopyMemoryToImage(*mem_target, image_no)
  FreeMemory(*mem_target)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l EnhanceEdges(image_no.l, strength.l = 0, outline.l = 0)
  
  ; ***************************************************************************
  ;
  ; Function: Enhances the edges of an image
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, *mem2.l
  Protected r.l, g.l, b.l
  Protected r1.l, r2.l, g1.l, g2.l, b1.l, b2.l
  Protected image_info.FASTIMAGEINFO
  Protected image_info2.FASTIMAGEINFO
  Protected x.l, y.l, i.l
  Protected threshold.l
  Protected Dim matrix.l(2, 2, 2), Dim color1.l(2), Dim color2.l(2)
  
  If strength < 0 Or strength > 100
    ProcedureReturn 0
  EndIf
  
  threshold = (100 - strength) * (254 - 64) / 100 + 64
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  *mem2 = AllocateMemory(mem_size)
  If *mem2 = 0
    FreeMemory(*mem)
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  image_info\ptrImageBuffer  = *mem
  image_info\imgWidth        = ImageWidth(image_no)
  image_info\imgHeight       = ImageHeight(image_no)
  image_info\imgDepth        = ImageDepth(image_no)
  
  CopyImageToMemory(image_no, *mem2)
  image_info2\ptrImageBuffer  = *mem2
  image_info2\imgWidth        = ImageWidth(image_no)
  image_info2\imgHeight       = ImageHeight(image_no)
  image_info2\imgDepth        = ImageDepth(image_no)
  
  For y = 0 To image_info\imgHeight - 1
    For x = 0 To image_info\imgWidth - 1
      
      If x <= 0 Or y <= 0 Or x >= image_info\imgWidth Or y >= image_info\imgHeight
        matrix(0, 0, 0) = FastRed(FastPoint(image_info, x, y))
        matrix(1, 0, 0) = FastGreen(FastPoint(image_info, x, y))
        matrix(2, 0, 0) = FastBlue(FastPoint(image_info, x, y))
      EndIf
      
      If x > 0 And y > 0     
        matrix(0, 0, 0) = FastRed(FastPoint(image_info, x - 1, y - 1))
        matrix(1, 0, 0) = FastGreen(FastPoint(image_info, x - 1, y - 1))
        matrix(2, 0, 0) = FastBlue(FastPoint(image_info, x - 1, y - 1))
      EndIf
      
      If y > 0     
        matrix(0, 1, 0) = FastRed(FastPoint(image_info, x, y - 1))
        matrix(1, 1, 0) = FastGreen(FastPoint(image_info, x, y - 1))
        matrix(2, 1, 0) = FastBlue(FastPoint(image_info, x, y - 1))
      EndIf
      
      If x < image_info\imgWidth - 1 And y > 0
        matrix(0, 2, 0) = FastRed(FastPoint(image_info, x + 1, y - 1))
        matrix(1, 2, 0) = FastGreen(FastPoint(image_info, x + 1, y - 1))
        matrix(2, 2, 0) = FastBlue(FastPoint(image_info, x + 1, y - 1))
      EndIf
      
      If x > 0
        matrix(0, 0, 1) = FastRed(FastPoint(image_info, x - 1, y))
        matrix(1, 0, 1) = FastGreen(FastPoint(image_info, x - 1, y))
        matrix(2, 0, 1) = FastBlue(FastPoint(image_info, x - 1, y))
      EndIf
      
      If x < image_info\imgWidth - 1
        matrix(0, 2, 1) = FastRed(FastPoint(image_info, x + 1, y))
        matrix(1, 2, 1) = FastGreen(FastPoint(image_info, x + 1, y))
        matrix(2, 2, 1) = FastBlue(FastPoint(image_info, x + 1, y))
      EndIf 
      
      If x > 0 And y < image_info\imgHeight - 1
        matrix(0, 0, 2) = FastRed(FastPoint(image_info, x - 1, y + 1))
        matrix(1, 0, 2) = FastGreen(FastPoint(image_info, x - 1, y + 1))
        matrix(2, 0, 2) = FastBlue(FastPoint(image_info, x - 1, y + 1))
      EndIf 
      
      If y < image_info\imgHeight - 1
        matrix(0, 1, 2) = FastRed(FastPoint(image_info, x, y + 1))
        matrix(1, 1, 2) = FastGreen(FastPoint(image_info, x, y + 1))
        matrix(2, 1, 2) = FastBlue(FastPoint(image_info, x, y + 1))
      EndIf 
      
      If x < image_info\imgWidth - 1 And y < image_info\imgHeight - 1
        matrix(0, 2, 2) = FastRed(FastPoint(image_info, x + 1, y + 1))
        matrix(1, 2, 2) = FastGreen(FastPoint(image_info, x + 1, y + 1))
        matrix(2, 2, 2) = FastBlue(FastPoint(image_info, x + 1, y + 1))
      EndIf 
      
      For i = 0 To 2
        color1(i) = - matrix(i, 0, 0) + matrix(i, 2, 0) - matrix(i, 0, 1) << 1 + matrix(i, 2, 1) << 1 - matrix(i, 0, 2) + matrix(i, 2, 2)
        color2(i) = matrix(i, 0, 0) + matrix(i, 1, 0) << 1 + matrix(i, 2, 0) - matrix(i, 0, 2) - matrix(i, 1, 2) << 1 - matrix(i, 2, 2)
      Next
      
      r = Abs(color1(0)) + Abs(color2(0))
      g = Abs(color1(1)) + Abs(color2(1))
      b = Abs(color1(2)) + Abs(color2(2))
      
      If r > threshold Or g > threshold Or b > threshold
        FastPlot(image_info2, x, y, 0)
      ElseIf outline
        FastPlot(image_info2, x, y, $FFFFFF)
      Else
        FastPlot(image_info2, x, y, FastPoint(image_info, x, y))
      EndIf
      
    Next
  Next
  CopyMemoryToImage(*mem2, image_no)
  FreeMemory(*mem)
  FreeMemory(*mem2)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l RotateImage180(image_no.l)
  
  ; ***************************************************************************
  ;
  ; Function: Rotates an image by 180 degrees
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l, temp.l
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size >> 1 - 1 Step 4
    temp = PeekL(*mem + mem_size - mem_pos - 4)
    PokeL(*mem + mem_size - mem_pos - 4, PeekL(*mem + mem_pos))
    PokeL(*mem + mem_pos, temp)
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l RotateImage90(image_no.l, direction.l = #RotateImageLeft)
  
  ; ***************************************************************************
  ;
  ; Function: Rotates an image by 90 degrees either left or right
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem_source.l, *mem_target.l, mem_size.l
  Protected target.l, width.l, height.l, x.l, y.l
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  If direction <> #RotateImageLeft And direction <> #RotateImageRight
    ProcedureReturn 0
  EndIf
  
  width = ImageWidth(image_no)
  height = ImageHeight(image_no)
  
  mem_size = width * height << 2
  *mem_source = AllocateMemory(mem_size)
  If *mem_source = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem_source)
  FreeImage(image_no)
  
  *mem_target = AllocateMemory(mem_size)
  If *mem_target = 0
    
    ; Attempt to restore source image when memory allocation fails
    
    If CreateImage(image_no, width, height, 32)
      CopyMemoryToImage(*mem_source, image_no)
    EndIf
    FreeMemory(*mem_source)
    ProcedureReturn 0
  EndIf
  
  For y = 0 To height - 1
    For x = 0 To width - 1
      Select direction
        Case #RotateImageLeft
          target = (y + ((width - x - 1) * height)) << 2
        Case #RotateImageRight
          target = ((height - y - 1) + (x * height)) << 2
      EndSelect
      PokeL(*mem_target + target, PeekL(*mem_source + (y * width + x) << 2))
    Next
  Next
  
  FreeMemory(*mem_source)
  
  If CreateImage(image_no, height, width, 32) = 0
    FreeMemory(*mem_target)
    ProcedureReturn 0
  EndIf
  
  CopyMemoryToImage(*mem_target, image_no)
  FreeMemory(*mem_target)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l FlipImage(image_no.l, direction.l = #FlipImageHorizontal)
  
  ; ***************************************************************************
  ;
  ; Function: Flips an image either horizontally or vertically
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, temp.l
  Protected source.l, target.l, width.l, height.l, x.l, y.l
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  If direction <> #FlipImageHorizontal And direction <> #FlipImageVertical
    ProcedureReturn 0
  EndIf
  
  width = ImageWidth(image_no)
  height = ImageHeight(image_no)
  
  mem_size = width * height << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  Select direction
    Case #FlipImageHorizontal
      For y = 0 To height - 1
        For x = 0 To width >> 1 - 1
          source = (y * width + x) << 2
          target = ((width - x) + (y * width - 1)) << 2
          temp = PeekL(*mem + target)
          PokeL(*mem + target, PeekL(*mem + source))
          PokeL(*mem + source, temp)
        Next
      Next
    Case #FlipImageVertical
      For y = 0 To height >> 1 - 1
        For x = 0 To width - 1
          source = (y * width + x) << 2
          target = ((height - y - 1) * width + x) << 2
          temp = PeekL(*mem + target)
          PokeL(*mem + target, PeekL(*mem + source))
          PokeL(*mem + source, temp)
        Next
      Next
  EndSelect
  
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l GrayscaleImage(image_no.l, method.l = #GrayscaleImage_Weighted)
  
  ; ***************************************************************************
  ;
  ; Function: Converts an image to grayscale
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l
  Protected color.l, r.l, g.l, b.l
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    r = FastRed(color)
    g = FastGreen(color)
    b = FastBlue(color)
    Select method
      Case #GrayscaleImage_Mean
        color = (r + g + b) / 3
      Case #GrayscaleImage_Weighted
        color = 0.299 * r + 0.587 * g + 0.114 * b
      Case #GrayscaleImage_Weighted2
        color = 0.3086 * r + 0.6094 * g + 0.0820 * b
      Default
        ProcedureReturn 0
    EndSelect
    PokeL(*mem + mem_pos, FastRGB(color, color, color))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l InvertImage(image_no.l)
  
  ; ***************************************************************************
  ;
  ; Function: Inverts the color of an image
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem, mem_size, mem_pos
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    PokeL(*mem + mem_pos, ~PeekL(*mem + mem_pos))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l SolarizeImage(image_no.l, lower_threshold.l = 0, upper_threshold.l = 128)
  
  ; ***************************************************************************
  ;
  ; Function: Produces a solarize effect of an image
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem, mem_size, mem_pos
  Protected color, r.c, g.c, b.c
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  If lower_threshold < 0 Or lower_threshold > upper_threshold Or upper_threshold > 255
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    r = FastRed(color)
    g = FastGreen(color)
    b = FastBlue(color)
    If r >= lower_threshold And r <= upper_threshold
      r = ~r
    EndIf
    If g >= lower_threshold And g <= upper_threshold
      g = ~g
    EndIf
    If b >= lower_threshold And b <= upper_threshold
      b = ~b
    EndIf
    PokeL(*mem + mem_pos, FastRGB(r, g, b))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l EqualizeImage(image_no.l)
  
  ; ***************************************************************************
  ;
  ; Function: Equalizes the histogram of an image
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l
  Protected color.l, r.l, g.l, b.l, count.l, i.l, j.l
  Protected Dim f_r.l(255)
  Protected Dim f_g.l(255)
  Protected Dim f_b.l(255)
  Protected Dim cuf_r.l(255)
  Protected Dim cuf_g.l(255)
  Protected Dim cuf_b.l(255)
  Protected Dim feq.l(255)
  Protected Dim cufeq.l(255)
  Protected nearest_value.l, nearest_intensity.l
  Protected Dim output_r.l(255)
  Protected Dim output_g.l(255)
  Protected Dim output_b.l(255)
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  
  ; Calculate frequency of intensities
  
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    f_r(FastRed(color)) + 1
    f_g(FastGreen(color)) + 1
    f_b(FastBlue(color)) + 1
  Next
  
  ; Calculate cumulative frequency distribution
  
  cuf_r(0) = f_r(0)
  cuf_g(0) = f_g(0)
  cuf_b(0) = f_b(0)
  
  For i = 1 To 255
    cuf_r(i) = cuf_r(i - 1) + f_r(i)
    cuf_g(i) = cuf_g(i - 1) + f_g(i)
    cuf_b(i) = cuf_b(i - 1) + f_b(i)
  Next
  
  ; Calculate equalized frequency distribution
  
  For i = 0 To 255
    feq(i) = mem_size >> 10
  Next
  
  For i = 0 To mem_size >> 2 - mem_size >> 10 << 8 - 1
    feq(i) + 1
  Next
  
  ; Calculate equalized cumulative frequency distribution
  
  cufeq(0) = feq(0)
  
  For i = 1 To 255
    cufeq(i) = cufeq(i - 1) + feq(i)
  Next
  
  ; Map the insensities
  
  i = 0
  Repeat
    nearest_value = cuf_r(255)
    j = 0
    Repeat
      If Abs(cuf_r(i) - cufeq(j)) < nearest_value
        nearest_value = Abs(cuf_r(i) - cufeq(j))
        nearest_intensity = j
      EndIf
      j + 1
    Until j > 255
    output_r(i) = nearest_intensity
    i + 1
  Until i > 255
  
  i = 0
  Repeat
    nearest_value = cuf_g(255)
    j = 0
    Repeat
      If Abs(cuf_g(i) - cufeq(j)) < nearest_value
        nearest_value = Abs(cuf_g(i) - cufeq(j))
        nearest_intensity = j
      EndIf
      j + 1
    Until j > 255
    output_g(i) = nearest_intensity
    i + 1
  Until i > 255
  
  i = 0
  Repeat
    nearest_value = cuf_b(255)
    j = 0
    Repeat
      If Abs(cuf_b(i) - cufeq(j)) < nearest_value
        nearest_value = Abs(cuf_b(i) - cufeq(j))
        nearest_intensity = j
      EndIf
      j + 1
    Until j > 255
    output_b(i) = nearest_intensity
    i + 1
  Until i > 255
  
  ; Transform the image
  
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    r = output_r(FastRed(color))
    g = output_g(FastGreen(color))
    b = output_b(FastBlue(color))
    PokeL(*mem + mem_pos, FastRGB(r, g, b))
  Next
  
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l ContrastStretchImage(image_no.l, lower_threshold.f = 0.5, upper_threshold.f = 0.5)
  
  ; ***************************************************************************
  ;
  ; Function: Performs contrast stretching on an image
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l
  Protected color.l, r.l, g.l, b.l, count.l
  Protected r_min.l = 256, r_max.l = 0
  Protected g_min.l = 256, g_max.l = 0
  Protected b_min.l = 256, b_max.l = 0
  Protected Dim r_histogram.l(255)
  Protected Dim g_histogram.l(255)
  Protected Dim b_histogram.l(255)
  Protected scale.f, lower_target.l, upper_target.l
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    r_histogram(FastRed(color)) + 1
    g_histogram(FastGreen(color)) + 1
    b_histogram(FastBlue(color)) + 1
  Next
  
  lower_target = ImageWidth(image_no) * ImageHeight(image_no) * (lower_threshold / 100)
  upper_target = ImageWidth(image_no) * ImageHeight(image_no) * (upper_threshold / 100)
  
  ContrastStretch_CalculateThresholds(r_histogram, r_min, r_max)
  ContrastStretch_CalculateThresholds(g_histogram, g_min, g_max)
  ContrastStretch_CalculateThresholds(b_histogram, b_min, b_max)
  
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    r = 255 * (FastRed(color) - r_min) / (r_max - r_min)
    g = 255 * (FastGreen(color) - g_min) / (g_max - g_min)
    b = 255 * (FastBlue(color) - b_min) / (b_max - b_min)
    NormalizeRGB(r, g, b)
    PokeL(*mem + mem_pos, FastRGB(r, g, b))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l NormalizeImage(image_no.l)
  
  Protected result.l
  
  result = ContrastStretchImage(image_no, 0.02, 0.01)
  
  ProcedureReturn result
  
EndProcedure

Procedure.l PosterizeImage(image_no.l, levels.l = 256)
  
  ; ***************************************************************************
  ;
  ; Function: Produces a posterize effect of an image
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l
  Protected color.l, r.l, g.l, b.l
  Protected factor.f, correction.f
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  If levels < 2 Or levels > 256
    ProcedureReturn 0
  EndIf
  
  factor = 256 / levels
  correction = 255 / (levels - 1)
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    r = FastRed(color)
    g = FastGreen(color)
    b = FastBlue(color)
    r = Int(r / factor) * correction
    g = Int(g / factor) * correction
    b = Int(b / factor) * correction
    PokeL(*mem + mem_pos, FastRGB(r, g, b))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure RGBToHSV(color, *colorspace.hsv)
  
  ; ***************************************************************************
  ;
  ; Function: Converts an RGB color space to HSV
  ;
  ; Returns:  A structure containing the HSV values
  ;
  ; ***************************************************************************
  
  Protected r.f, g.f, b.f
  Protected r_temp.l, g_temp.l, b_temp.l
  Protected delta.f, min.f
  
  r_temp = FastRed(color)
  g_temp = FastGreen(color)
  b_temp = FastBlue(color)
  
  r = r_temp / 255
  g = g_temp / 255
  b = b_temp / 255
  
  If r < g
    min = r
  Else
    min = g
  EndIf
  If b < min
    b = min
  EndIf
  
  If r > g
    *colorspace\v = r
  Else
    *colorspace\v = g
  EndIf
  If b > *colorspace\v
    *colorspace\v = b
  EndIf
  
  delta = *colorspace\v - min
  
  If *colorspace\v = 0
    *colorspace\s = 0
  Else
    *colorspace\s = delta / *colorspace\v
  EndIf
  
  If *colorspace\s = 0
    *colorspace\h = 0
  Else
    If r = *colorspace\v
      *colorspace\h = 60 * (g - b) / delta
    ElseIf g = *colorspace\v
      *colorspace\h = 120 + 60 * (b - r) / delta
    ElseIf b = *colorspace\v
      *colorspace\h = 240 + 60 * (r - g) / delta
    EndIf
    If *colorspace\h < 0
      *colorspace\h + 360
    EndIf
  EndIf
  
EndProcedure

Procedure.l HSLToRGB(*colorspace.hsl)
  
  ; ***************************************************************************
  ;
  ; Function: Converts HSL color space to RGB
  ;
  ; Returns:  The value of RGB
  ;
  ; ***************************************************************************
  
  Protected r.f, g.f, b.f
  Protected temp1.f, temp2.f
  Protected r_temp.f, g_temp.f, b_temp.f
  Protected h_temp.f
  
  If *colorspace\s = 0
    r = *colorspace\l
    g = *colorspace\l
    b = *colorspace\l
  Else
    If *colorspace\l < 0.5
      temp2 = *colorspace\l * (1 + *colorspace\s)
    Else
      temp2 = *colorspace\l + *colorspace\s - *colorspace\l * *colorspace\s
    EndIf
    
    temp1 = 2 * *colorspace\l - temp2
    
    h_temp = *colorspace\h / 360
    
    r_temp = h_temp + 1 / 3
    g_temp = h_temp
    b_temp = h_temp - 1 / 3
    
    If r_temp < 0
      r_temp + 1
    ElseIf r_temp > 1
      r_temp - 1
    EndIf
    
    If g_temp < 0
      g_temp + 1
    ElseIf g_temp > 1
      g_temp - 1
    EndIf
    
    If b_temp < 0
      b_temp + 1
    ElseIf b_temp > 1
      b_temp - 1
    EndIf
    
    If 6 * r_temp < 1
      r = temp1 + (temp2 - temp1) * 6 * r_temp
    ElseIf 2 * r_temp < 1
      r = temp2
    ElseIf 3 * r_temp < 2
      r = temp1 + (temp2 - temp1) * ((2 / 3) - r_temp) * 6
    Else
      r = temp1
    EndIf
    
    If 6 * g_temp < 1
      g = temp1 + (temp2 - temp1) * 6 * g_temp
    ElseIf 2 * g_temp < 1
      g = temp2
    ElseIf 3 * g_temp < 2
      g = temp1 + (temp2 - temp1) * ((2 / 3) - g_temp) * 6
    Else
      g = temp1
    EndIf
    
    If 6 * b_temp < 1
      b = temp1 + (temp2 - temp1) * 6 * b_temp
    ElseIf 2 * b_temp < 1
      b = temp2
    ElseIf 3 * b_temp < 2
      b = temp1 + (temp2 - temp1) * ((2 / 3) - b_temp) * 6
    Else
      b = temp1
    EndIf
  EndIf
  
  ProcedureReturn FastRGB(Int(r * 255), Int(g * 255), Int(b * 255))
  
EndProcedure

Procedure.l HSVToRGB(*colorspace.hsv)
  
  ; ***************************************************************************
  ;
  ; Function: Converts HSV color space to RGB
  ;
  ; Returns:  The value of RGB
  ;
  ; ***************************************************************************
  
  Protected f.f, i.l, aa.f, bb.f, cc.f
  Protected r.f, g.f, b.f
  Protected h_temp.f
  
  If *colorspace\s = 0
    r = *colorspace\v
    g = *colorspace\v
    b = *colorspace\v
  Else
    If *colorspace\h = 360
      *colorspace\h = 0
    EndIf
    
    h_temp = *colorspace\h / 60
    i = Int(h_temp)
    f = h_temp - i
    
    aa = *colorspace\v * (1 - *colorspace\s)
    bb = *colorspace\v * (1 - (*colorspace\s * f))
    cc = *colorspace\v * (1 - (*colorspace\s * (1 - f)))
    
    Select i
      Case 0
        r = *colorspace\v
        g = cc
        b = aa
      Case 1
        r = bb
        g = *colorspace\v
        b = aa
      Case 2
        r = aa
        g = *colorspace\v
        b = cc
      Case 3
        r = aa
        g = bb
        b = *colorspace\v
      Case 4
        r = cc
        g = aa
        b = *colorspace\v
      Case 5
        r = *colorspace\v
        g = aa
        b = bb
    EndSelect
  EndIf
  
  ProcedureReturn FastRGB(Int(r * 255), Int(g * 255), Int(b * 255))
  
EndProcedure

Procedure.l AdjustImageHue(image_no.l, value.l = 0)
  
  ; ***************************************************************************
  ;
  ; Function: Adjusts the hue of an image
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; Notes:    Hue value can be between -180 and 180
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l
  Protected color.l, r.l, g.l, b.l
  Protected colorspace.HSV
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  If value < -180 Or value > 180
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    RGBToHSV(color, @colorspace)
    colorspace\h + value
    If colorspace\h > 360
      colorspace\h - 360
    ElseIf colorspace\h < 0
      colorspace\h + 360
    EndIf
    PokeL(*mem + mem_pos, HSVToRGB(colorspace))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l ColorizeImage(image_no.l, *colorspace.hsl)
  
  ; ***************************************************************************
  ;
  ; Function: Colorizes an image to a particular hue
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l
  Protected color.l, r.l, g.l, b.l, hsl.hsl
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  hsl\h = *colorspace\h
  hsl\s = *colorspace\s
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    
    r = FastRed(color)
    g = FastGreen(color)
    b = FastBlue(color)
    
    color = 0.299 * r + 0.587 * g + 0.114 * b
    
    hsl\l = *colorspace\l * 2 - 1
    
    If hsl\l < 0
      hsl\l = color / 255 * (hsl\l + 1)
    Else
      hsl\l = color / 255 * (1 - hsl\l) + hsl\l
    EndIf
    
    PokeL(*mem + mem_pos, HSLToRGB(hsl))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

Procedure.l TintImage(image_no.l, tint_color.l, tint_amount.f)
  
  ; ***************************************************************************
  ;
  ; Function: Tints an image to a particular color
  ;
  ; Returns:  '1' if successful, otherwise '0'
  ;
  ; ***************************************************************************
  
  Protected *mem.l, mem_size.l, mem_pos.l
  Protected color.l, r.l, g.l, b.l, r_tint.l, g_tint.l, b_tint.l
  
  If IsImage(image_no) = 0
    ProcedureReturn 0
  EndIf
  
  If tint_amount < 0 Or tint_amount > 100
    ProcedureReturn 0
  EndIf
  
  mem_size = ImageWidth(image_no) * ImageHeight(image_no) << 2
  *mem = AllocateMemory(mem_size)
  If *mem = 0
    ProcedureReturn 0
  EndIf
  
  r_tint = FastRed(tint_color)
  g_tint = FastGreen(tint_color)
  b_tint = FastBlue(tint_color)
  tint_amount / 100
  
  CopyImageToMemory(image_no, *mem)
  For mem_pos = 0 To mem_size - 1 Step 4
    color = PeekL(*mem + mem_pos)
    
    r = FastRed(color)
    g = FastGreen(color)
    b = FastBlue(color)
    
    r * (1 - tint_amount) + r_tint * tint_amount
    g * (1 - tint_amount) + g_tint * tint_amount
    b * (1 - tint_amount) + b_tint * tint_amount
    
    PokeL(*mem + mem_pos, FastRGB(r, g, b))
  Next
  CopyMemoryToImage(*mem, image_no)
  FreeMemory(*mem)
  
  ProcedureReturn 1
  
EndProcedure

;=============================================================================

If OpenWindow(0, 0, 0, 900, 600, "ImageGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  TrackBarGadget(2, 810, 10, 20, 170, 0, 510, #PB_TrackBar_Vertical)
  SetGadgetState(2, 255)
  
  Filtre$ = "bmp (*.bmp)|*.bmp;*.jpeg|Tous les fichiers (*.*)|*.*"
  Filtre  = 0    ; utiliser  par défaut le premier des trois filtres possibles
  Fichier$ = OpenFileRequester("Choisissez une image", "", Filtre$, Filtre)
  If  Not Fichier$
    End
  EndIf 
  
  If LoadImage(0, Fichier$) 
    ImageGadget(0,  0, 0, 800, 600, ImageID(0)) 
  EndIf
  
  Repeat
    Event = WaitWindowEvent()
    If Event = #PB_Event_Gadget
      Select EventGadget()
          
        Case 2 ; trackbar luminosité
          ; Procedure.l AdjustImageBrightness(image_no.l, brightness.l = 0, r_brightness.l = 0, g_brightness.l = 0, b_brightness.l = 0)
          
          ; ***************************************************************************
          ;
          ; Function: Adjusts the brightness of an image
          ;
          ; Returns:  '1' if successful, otherwise '0'
          ;
          ; Notes:    Brightness values can be between -255 and 255 
          
          luminosite=GetGadgetState(2)-255
          AdjustImageBrightness(0,  luminosite, 0, 0, 0)
          SetGadgetState(0, ImageID(0))
          
          Debug luminosite
          
      EndSelect
    EndIf
    
    ;     If Event =#PB_Event_Repaint
    ;       SetGadgetState(0, ImageID(0))
    ;     EndIf
  Until Event = #PB_Event_CloseWindow
EndIf

Mesa.
dayvid
Messages : 1242
Inscription : mer. 11/nov./2009 18:17
Localisation : Poitiers (Vienne)

Re: Luminosité Image

Message par dayvid »

Tous ça pour changer la luminositer d'une image 8O
Ya pas plus simple :?:
La vie, C'est comme, Une boitte, De startis, On en voie, De toutes, Les couleurs !

Mon forum http://purebasic.forumphp3.com/index.php
Avatar de l’utilisateur
blendman
Messages : 2017
Inscription : sam. 19/févr./2011 12:46

Re: Luminosité Image

Message par blendman »

houlà...

Essayes ça pour voir si ça te convient ;)

Code : Tout sélectionner

; German forum: http://www.purebasic.fr/german/viewtopic.php?t=2126&highlight= 
; Author: sverson (updated for PB 4.00 by Andre + Helle) 
; Date: 19. February 2005 
; OS: Windows 
; Demo: No 


; Brightness control for system colors 
; System- (oder auch andere Farben) noch heller oder dunkler machen 

;/ RGB farbhelligkeit korrigieren  PB 3.92 / ASM 
;/ Eine schnelle ASM-Routine zur "on the fly" Korrektur der RGB Farbhelligkeit 
;/ BrightnessRGB(RGB_Color.l, Delta.w) Delta -255...255 - andere Werte sind sinnlos 
;/ 02/2005 sverson 

Enumeration 
  #DemoWindow 
  #DemoImage 
  #DemoImageGeaget 
  #ColorTrackBar 
  #BrightnesTrackBar 
EndEnumeration 

Structure SYSCOLORS 
  ColorConst.s 
  ColorNumber.l 
EndStructure 
Global NewList ColorList.SYSCOLORS() 

Procedure InitColorList() ;/ Systemfarben 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_3DDKSHADOW" : ColorList()\ColorNumber = GetSysColor_(#COLOR_3DDKSHADOW) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_3DFACE = #COLOR_BTNFACE" : ColorList()\ColorNumber = GetSysColor_(#COLOR_3DFACE) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_3DHILIGHT = #COLOR_BTNHIGHLIGHT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_3DHILIGHT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_3DHIGHLIGHT = #COLOR_BTNHIGHLIGHT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_3DHIGHLIGHT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_3DLIGHT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_3DLIGHT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_3DSHADOW = #COLOR_BTNSHADOW" : ColorList()\ColorNumber = GetSysColor_(#COLOR_3DSHADOW) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_ACTIVEBORDER" : ColorList()\ColorNumber = GetSysColor_(#COLOR_ACTIVEBORDER) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_ACTIVECAPTION" : ColorList()\ColorNumber = GetSysColor_(#COLOR_ACTIVECAPTION) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_APPWORKSPACE" : ColorList()\ColorNumber = GetSysColor_(#COLOR_APPWORKSPACE) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_BACKGROUND" : ColorList()\ColorNumber = GetSysColor_(#COLOR_BACKGROUND) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_BTNFACE" : ColorList()\ColorNumber = GetSysColor_(#COLOR_BTNFACE) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_BTNHIGHLIGHT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_BTNHIGHLIGHT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_BTNHILIGHT = #COLOR_BTNHIGHLIGHT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_BTNHILIGHT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_BTNSHADOW" : ColorList()\ColorNumber = GetSysColor_(#COLOR_BTNSHADOW) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_BTNTEXT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_BTNTEXT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_CAPTIONTEXT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_CAPTIONTEXT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_DESKTOP = #COLOR_BACKGROUND" : ColorList()\ColorNumber = GetSysColor_(#COLOR_DESKTOP) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_GRAYTEXT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_GRAYTEXT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_HIGHLIGHT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_HIGHLIGHT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_HIGHLIGHTTEXT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_HIGHLIGHTTEXT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_INACTIVEBORDER" : ColorList()\ColorNumber = GetSysColor_(#COLOR_INACTIVEBORDER) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_INACTIVECAPTION" : ColorList()\ColorNumber = GetSysColor_(#COLOR_INACTIVECAPTION) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_INACTIVECAPTIONTEXT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_INACTIVECAPTIONTEXT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_INFOBK" : ColorList()\ColorNumber = GetSysColor_(#COLOR_INFOBK) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_INFOTEXT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_INFOTEXT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_MENU" : ColorList()\ColorNumber = GetSysColor_(#COLOR_MENU) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_MENUTEXT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_MENUTEXT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_SCROLLBAR" : ColorList()\ColorNumber = GetSysColor_(#COLOR_SCROLLBAR) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_WINDOW" : ColorList()\ColorNumber = GetSysColor_(#COLOR_WINDOW) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_WINDOWFRAME" : ColorList()\ColorNumber = GetSysColor_(#COLOR_WINDOWFRAME) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLOR_WINDOWTEXT" : ColorList()\ColorNumber = GetSysColor_(#COLOR_WINDOWTEXT) 
  AddElement(ColorList()) : ColorList()\ColorConst = "#COLORONCOLOR" : ColorList()\ColorNumber = GetSysColor_(#COLORONCOLOR) 
  ;/ + 3 Demofarben 
  AddElement(ColorList()) : ColorList()\ColorConst = "Demo Blue" : ColorList()\ColorNumber = RGB(0,0,128) 
  AddElement(ColorList()) : ColorList()\ColorConst = "Demo Green" : ColorList()\ColorNumber = RGB(0,128,0) 
  AddElement(ColorList()) : ColorList()\ColorConst = "Demo Red" : ColorList()\ColorNumber = RGB(128,0,0) 
EndProcedure 

Procedure BrightnessRGB(RGB_Color.l, Delta.w);- RGB farbhelligkeit korrigieren 
  !XOR Edx, Edx         ;/ EDX-Register löschen 
  !XOR Ebx, Ebx         ;/ EBX-Register löschen 
  !XOR Ecx, Ecx         ;/ ECX-Register löschen 
  !MOV BX, Word [p.v_Delta] ;/ Delta-Wert in BX einlesen 
  !MOV Eax, dWord [p.v_RGB_Color] ;/ RGB-Farbwert in EAX einlesen 
  !MOV DL, AL           ;/ R-Wert nach DL 
  !CALL .adddelta       ;/--> DELTA ZU DL (R) ADDIEREN ++ 
  !MOV CL, DL           ;/ R-Wert in CL zwischenspeichern 
  !MOV DL, AH           ;/ G-Wert nach DL 
  !CALL .adddelta       ;/--> DELTA ZU DL (G) ADDIEREN ++ 
  !MOV CH, DL           ;/ G-Wert in CH zwischenspeichern 
  !BSWAP Eax            ;/ B-Wert via BYTESWAP in AH zugänglich machen 
  !MOV DL, AH           ;/ G-Wert nach DL 
  !CALL .adddelta       ;/--> DELTA ZU DL (B) ADDIEREN ++ 
  !MOV AH, DL           ;/ G-Wert nach AH zurückschreiben 
  !BSWAP Eax            ;/ G-Wert via BYTESWAP wieder an richtige Position bringen 
  !MOV AX, CX           ;/ R und G Wert aus Zwischenspeicher CX wieder in AX schreiben 
  !JMP .ready           ;/==> FARBKORREKTUR BEENDET ++ 
  !.adddelta:           ;/ ++ DELTA ZU DL ADDIEREN ++ 
  !ADD DX, BX           ;/ Delta aus BX zu DX addieren 
  !BT DX, 15            ;/ auf Negativwert testen 
  !JC .negativ          ;/==> NEUER WERT KLEINER NULL ++ 
  !CMP DX, $FF          ;/ auf Maximalwert testen 
  !JBE .inrange         ;/==> NEUER ZWISCHEN 0 UND 255 ++ 
  !.bigger:             ;/ ++ NEUER WERT GRÖSSER 255 ++ 
  !MOV DX, $00FF        ;/ DX auf 255 begrenzen 
  !JMP .inrange         ;/==> WERT IN DEN GRENZEN ++ 
  !.negativ:            ;/ ++ NEUER WERT KLEINER NULL ++ 
  !XOR Edx, Edx         ;/ DX auf 0 begrenzen 
  !.inrange:            ;/ ++ WERT IN DEN GRENZEN ++ 
  !RET                  ;/ Rücksprung aus Makro 
  !.ready:              ;/ ++ FARBKORREKTUR BEENDET ++ 
  ProcedureReturn 
EndProcedure 

Procedure UpdateImage(ITitle$,IColor.l,iDelta.w);/ Image aktualisieren 
  StartDrawing(ImageOutput(#DemoImage)) 
  newColor = BrightnessRGB(IColor,iDelta) 
  Box(0,0,280,200,IColor) 
  Box(78,48,124,104,RGB(255,255,255)) 
  Box(79,49,122,102,RGB(0,0,0)) 
  Box(80,50,120,100,newColor) 
  DrawingMode(1) 
  FrontColor(RGB(255,255,255)) 
  DrawText(10, 10, ITitle$) 
  DrawText(90, 65, "R"+RSet(Str(Red(newColor)),3,"0")+"G"+RSet(Str(Green(newColor)),3,"0")+"b"+RSet(Str(Blue((newColor))),3,"0")) 
  DrawText(90, 80, "delta: "+Str(iDelta)) 
  FrontColor(RGB(0,0,0)) ; print the text to white ! 
  DrawText(90, 100, "delta: "+Str(iDelta)) 
  DrawText(90, 115, "R"+RSet(Str(Red(newColor)),3,"0")+"G"+RSet(Str(Green(newColor)),3,"0")+"b"+RSet(Str(Blue((newColor))),3,"0")) 
  DrawText(10, 175, ITitle$) 
  StopDrawing() 
EndProcedure 

If OpenWindow(#DemoWindow,0,0,320,240,"Helligkeitsregler",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) And CreateGadgetList(WindowID(#DemoWindow)) 
  If CreateImage(#DemoImage, 280, 200) 
    InitColorList() 
    LastElement(ColorList()) 
    UpdateImage(ColorList()\ColorConst,ColorList()\ColorNumber,0) 
    ImageGadget(#DemoImageGeaget,5,5,280,200,ImageID(#DemoImage),#PB_Image_Border) 
    TrackBarGadget(#BrightnesTrackBar, 5, 215, 280, 20,0,510) 
    SetGadgetState(#BrightnesTrackBar,255) 
    TrackBarGadget(#ColorTrackBar, 295, 5, 20, 200,1,CountList(ColorList()),#PB_TrackBar_Vertical) 
    SetGadgetState(#ColorTrackBar,CountList(ColorList())) 
    Repeat : 
      WinEvent = WaitWindowEvent() 
      Select WinEvent 
        Case #PB_Event_Gadget 
          SelectElement(ColorList(),GetGadgetState(#ColorTrackBar)-1) 
          UpdateImage(ColorList()\ColorConst,ColorList()\ColorNumber,GetGadgetState(#BrightnesTrackBar)-255) 
          SetGadgetState(#DemoImageGeaget,ImageID(#DemoImage)) 
      EndSelect 
    Until WinEvent = #PB_Event_CloseWindow 
  EndIf 
EndIf 
End 

; IDE Options = PureBasic v4.02 (Windows - x86)
; Folding = -
; EnableXP
ou ça (c'est un code de LSi il me semble à la base) :

Code : Tout sélectionner

; Code de LSI
; modifié par blendman
Enumeration 
  #img 
  #Barre 
  #trackbar 
EndEnumeration
#win = 0


; on charge l'image
UseJPEGImageDecoder()
LoadImage(#img, "1.jpg"); faut changer ici et mettre ton image à tester.

; récupère la dimension de l'image
ImageX = ImageWidth(#img)
ImageY = ImageHeight(#img)

; Couleur d'ajout
Couleur_Ajout = RGB(20, 255, 20)

Global event

If OpenWindow(#win, 0, 0, ImageX, ImageY + 40,"Luminosité", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ImageGadget(#img, 0, 0, ImageX, ImageY, ImageID(#img))
  ProgressBarGadget(#Barre, 0, ImageY + 2, ImageX, 18, 0, ImageX)
  TrackBarGadget(#trackbar,0,ImageY + 22,imagex,18,0,200)
  SetGadgetState(#trackbar,100)
  ; On récupère l'image
  Dim Pixel.l(ImageX, ImageY)
  StartDrawing(ImageOutput(#img))
  For Px = 0 To ImageX-1
    For Py = 0 To ImageY-1
      Pixel(Px, Py) = Point(Px, Py)
    Next
    ; on fait progresser la barre
    SetGadgetState(#Barre, Px)
  Next
  StopDrawing()
  
  ; On initialise le niveau de contraste
  Niveau.f = 0.1
  
  Repeat
    Event = WaitWindowEvent()
    
    Select Event 
        
      Case #PB_Event_Gadget
        
        Select EventGadget()
            
          Case #trackbar
           
            Niveau =-1+GetGadgetState(#trackbar)/100
            
            StartDrawing(ImageOutput(#img)) ; on dessine sur l'image
            
            x = 0 ; on se place en x=0 sur l'image            
            Repeat              
              y = 0 ; on se place en y=0 sur l'image              
              Repeat                
                ; on récupère la couleur du point en x et y
                Couleur = Pixel(x, y)
                Rouge.f = Red(couleur)
                Vert.f = Green(couleur)
                Bleu.f = Blue(couleur)
                
                ; On augmente la luminosité
                Rouge = Rouge * (Niveau + 1)
                If Rouge > 255 : Rouge = 255 : EndIf
                Vert = Vert * (Niveau + 1)
                If Vert > 255 : Vert = 255 : EndIf
                Bleu = Bleu * (Niveau + 1)
                If Bleu > 255 : Bleu = 255 : EndIf
                
                ; On recalcule la nouvelle couleur
                Couleur = RGB(Rouge, Vert, Bleu)
                
                ; si la taille du nouveau pixel est positive
                Plot(x, y, Couleur) ; on dessine un carré qui fait le nouveau pixel de la même couleur que celle récupéré en x et y
                
                ; on se déplace sur l'image en y de la taille d'un pixel
                y = y + 1
                
              Until y >= ImageY ; si on a finit la colonne de l'image placé en x
              
              ; on se déplace sur l'image en x de la taille d'un pixel
              x = x + 1
              ;**********************************************************************
              ; on fait progresser la barre
              SetGadgetState(#Barre, x)
              
            Until x >= ImageX ; si on a traité toutes les lignes de l'image            
            StopDrawing()
            
            ; on réaffiche l'image
            SetGadgetState(#img, ImageID(#img))
                 
        EndSelect        
    EndSelect
        
  Until Event = #WM_CLOSE ; on clique sur la croix, fin du prog
EndIf
Répondre