HiDPI confusion

I’m trying to update my homegrown HiDPI code with Xojo’s HiDPI stuff. But I’m getting totally confused. I’ve read the HiDPI guide but this is not much code. The docs also are pretty sparse. Additionally, I think having the same class “picture” contain different things (mutable or not) and that react different on different states is a really bad idea.

I’m trying to paint an icon in an “over” state deferred from the paint event:

Protected Sub drawOverState(g as graphics)
dim OverPicture as Picture = MakeDarker(ButtonPicture, 0.8)
g.DrawPicture(OverPicture, 0, 0)
End Sub

The problem is the MakeDarker function:

[code]Private Function MakeDarker(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 mutablePicture as new Picture(OriginalPicture.Width, OriginalPicture.Height, 32)
'mutablePicture = OriginalPicture.CopyColorChannels
'dim OriginalRGBS as RGBSurface = mutablePicture.RGBSurface
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.Mask = OriginalPicture.mask

Return ResultPicture
End Function[/code]

The docs tell me that I need to use CopyColorChannels for HiDPI. If I try to use this I get an UnsupporteFormatException “CopyColorChannels is not supported for multi-representation images”. So I take the code out and then I get a NOE for the OriginalRGBS because the docs tell me that an unmutable picture doesn’t have an RGBSurface. What am I doing wrong here?

Are there any better examples?

Xojo 2017r3, macOS 10.11 and .13

If OriginalPicture is HiDPI (RGBSurface=nil) then you have to take the local scale picture:
OriginalPicture.BestRepresentation(100, 100, Self.ScaleFactor) //self.ScaleFactor is needed to take the right scale

Then this picture will have the RGBSurface, it is still immutable but will work for your scope.

If you need to create an HiDPi Darker version you have to use:

Private Function MakeDarkerHiDPI(original as picture, amount as double) as Picture dim results() as Picture dim n as integer=original.count-1 for i as integer=0 to n result.append makeDarker(original.IndexedImage(i), amount) next return new Picture(original.width, original.height, results) end function

Ah, I was missing BestRepresentation. This works for the RGBSurface of the picture:

[code]Private Function MakeDarker(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.BestRepresentation(OriginalPicture.Width, OriginalPicture.Height, self.ScaleFactor).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, theColor.Alpha)
next
next

'ResultPicture.Mask = OriginalPicture.mask

Return ResultPicture
End Function[/code]

What about the Alpha value? In the original code I simply copied the mask. In the HiDPI version I added theColor.Alpha to the ResultRGBS. But no dice. What am I missing here?

The function MakeDarkerHiDPI does NOT work. picture is not an array.

ImageCount

Here is a better version:
this one works with HiDPI and not HiDPI images

Private Function MakeDarkerHiDPI(original as Picture, amout as double) as Picture Dim n As Integer=original.ImageCount If n=0 Then Return MakeDarker(original, amout) Else Dim pp() As Picture n=n-1 for i as integer=0 to n pp.Append MakeDarker(original.IndexedImage(i), amout) Next Return new Picture(original.Width, original.Height, pp) End If End Function

This is your MakeDarker with mask in any case:

[code]Private Function MakeDarker(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

//If you want, you can use the new constructor (without mask object)
//dim ResultPicture as new Picture(OriginalPicture.Width, OriginalPicture.Height, 32)
Dim ResultPicture As New Picture(OriginalPicture.Width, OriginalPicture.Height)
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
If OriginalPicture.Mask=Nil Then
//if you use the ,32 constructor set the mask
//ResultPicture.Mask=OriginalPicture.CopyMask
//otherwise apply it
ResultPicture.ApplyMask OriginalPicture.CopyMask
Else
//if you use the ,32 constructor set the mask
//ResultPicture.Mask = OriginalPicture.mask
//otherwise apply it
ResultPicture.ApplyMask OriginalPicture.Mask
End If
Return ResultPicture
End Function
[/code]

Thanks!