Picture going missing

Ever since DarkMode I’ve had the 2 functions below to make pictures darker or lighter. There is one (!) instance where the function makes a very strange NOE.

The debugger shows me that MakeDarkerInner gives a picture back. But when making a new picture out of pp I can see that both pictures in pp are nil.

Xojo 2020r2.1, tested on Mojave and BS. The same code works fine in 2019r3.

Does anyone have an idea what I’m doing wrong?

Protected Function MakeDarker(original as Picture, amount as double) as Picture
Dim n As Integer=original.ImageCount
If n=0 Then
Return MakeDarkerInner(original, amount)
Else
Dim pp() As Picture
n=n-1
for i as integer=0 to n
pp.Add MakeDarkerInner(original.ImageAt(i), amount)
Next
Return new Picture(original.Width, original.Height, pp)
End If

End Function

Private Function MakeDarkerInner(OriginalPicture as Picture, theAmount as Double) as Picture
  'change the value (lighter or darker) for the Original Picture
  
  Dim OriginalHeight As Integer = OriginalPicture.height
  Dim OriginalWidth As Integer = OriginalPicture.width
  
  Dim OriginalRGBS As RGBSurface = OriginalPicture.RGBSurface
  dim ResultPicture as new Picture(OriginalPicture.Width, OriginalPicture.Height, 32)
  dim ResultRGBS as RGBSurface = ResultPicture.RGBSurface
  
  for currentX as Integer = 0 to OriginalWidth
    for currentY as Integer = 0 to OriginalHeight
      dim theColor as Color = OriginalRGBS.Pixel(currentX, currentY)
      ResultRGBS.Pixel(currentX, CurrentY) = HSV(theColor.Hue, theColor.Saturation, theColor.Value * theAmount)
    next
  next
  
  ResultPicture.ApplyMask OriginalPicture.CopyMask
  
End Function

Change

 dim ResultPicture as new Picture(OriginalPicture.Width, OriginalPicture.Height, 32)

to

 dim ResultPicture as new Picture(OriginalPicture.Width, OriginalPicture.Height)

You’re not returning Result Picture

Also include the alpha value in HSV, then you don’t need to applyMask.

Maynot be relevant, but:

When doing x,y loops over a picture, I often run into a difference between Mac and Windows.
cant recall which, but one allows

0 to picturewidth

while the other generates an exception, and actually needs

0 to picturewidth-1

Also, if all you are doing is darkening the image, would drawing a black rectangle on it at a certain level of transparency do the job faster?

Either an image with a grey mask, or .fillrectangle using a black color that had an alpha level?

@Sam Rowlands: no change

@Jeff_Tullin: I’m using the code all over the place for buttons and similar. A black rectangle wouldn’t work.

The debugger for the MakeDarkerInner shows a picture:


And when making a new picture the 2 inner pictures are nil:

I’m going to make new artwork and I’ll try to reproduce the problem in an example.

At the end of the function, are you returning the picture?

@Sam Rowlands: yup. Otherwise, I wouldn’t see anything.

  • Jeff is right, you have a bad OBOE (off by one error).

  • you should always iterate Y first, and then X on the inner loop - this takes advantage of the fact that X pixels are next to each other in memory. Depending on picture size, this can provide a good speedup

  • #pragma DisableBackgroundTasks // always good for tight loops

Here is corrected code:

#pragma DisableBackgroundTasks // this will give you a 2x-10x speedup
  for currentY as Integer = 0 to OriginalHeight-1
    for currentX as Integer = 0 to OriginalWidth-1
      dim theColor as Color = OriginalRGBS.Pixel(currentX, currentY)
      ResultRGBS.Pixel(currentX, CurrentY) = HSV(theColor.Hue, theColor.Saturation, theColor.Value * theAmount, theColor.Alpha)
    next
  next

I suspect what’s happening is that with some picture sizes, the OBOE is causing a silent internal fault, but with some picture sizes it’s OK?

1 Like

Thanks for making me aware of the problem with the OBOE (great word). But why has the code worked for years? And I still get the NOE.

I’ve never used PIctures with multiple images so I don’t know, but I suspect Sam’s comment about not mixing the old style New Picture(w,h,32) and new style New Picture(w,h) constructors could be relevant. Did you make that change?

Yup, tried that. Also didn’t make a difference.

Here are screenshots made with Xojo 2019r3. There is a background and the original header in LightMode:

In DarkMode there is a different background. But for the header I used the MakeDarker function:

Also perhaps…
have you looked into Transform?

for x = 0 to 255
  rmap(x) = x * 0.7
next


mypic.rgbsurface.transform rmap(),rmap(),rmap()
1 Like