WebPicture/Picture conversion fail => NIL

The documentation states that one should be able to convert a WebPicture object to a Picture object by just assigning the reference. However, my Picture object remains NIL, the WebPicture object isn’t though (and it’s properties are correctly set in the debugger):

[code] try
Dim picFile As FolderItem = SpecialFolder.Desktop.Child(“TestPic.jpg”)
Dim webPic As New WebPicture(picFile)
Dim pic As Picture = webPic //pic is NIL

catch err As NilObjectException
Break
catch err As UnsupportedFormatException
Break
catch err As IOException
Break

end try[/code]

What’s wrong?

It would be nil if picfile=nil or picfile doesn’t exist…

You could also try

dim webpic as webpicture = picture.Open(picfile)

Picfile does exist and is not Nil, neither is webPic. However, “pic” is nil.

I’d suggest trying using picture.open and see if the framework is actually able to open that pic (just assign it to a Picture object). It could be that it’s failing there.

It works using Picture.Open(folderitem):

[code] try
Dim picFile As FolderItem = SpecialFolder.Desktop.Child(“TestPic.jpg”)
'Dim webPic As New WebPicture(picFile) // ← With that line, “webPic” is not NIL but “pic” remains NIL when assigning below
Dim webPic As WebPicture = Picture.Open(picFile) // ← WIth that line, neither “webPic” is NIL nor is “pic” when assigning below
Dim pic As Picture = webPic

break

catch err As NilObjectException
Break
catch err As UnsupportedFormatException
Break
catch err As IOException
Break

end try[/code]

Why would it fail with the original code then(commented line)?

webPic is not Nil, but the file might not exist. The proper way is to test for both:

If webPic <> Nil And webPic.Exists Then ...

[quote=219380:@Eli Ott]webPic is not Nil, but the file might not exist. The proper way is to test for both:

If webPic <> Nil And webPic.Exists Then ...[/quote]

WebPicture has no method “Exists” - however FolderItem does. So I added a few lines to test that:

[code] try
Dim picFile As FolderItem = SpecialFolder.Desktop.Child(“TestPic.jpg”)

If picFile.Exists = false Then
  break
End If

'Dim webPic As New WebPicture(picFile)  // <- With that line, "webPic" is not NIL but "pic" remains NIL when assigning below
Dim webPic As WebPicture = Picture.Open(picFile)  // <- WIth that line, neither "webPic" is NIL nor is "pic" when assigning below
Dim pic As Picture = webPic //pic is NIL

break

catch err As NilObjectException
Break
catch err As UnsupportedFormatException
Break
catch err As IOException
Break

end try[/code]

And it doesn’t break there. This is no surprise since Picture.Open probably wouldn’t work with a file that does not exist.

It’s puzzling that creating a WebPicture with a FolderItem in the Constructor returns a valid WebPicture object, the subsequent conversion to a Picture object however results in NIL. On the other hand, loading the image through Picture.Open(FolderItem) and assigning it to a WebPicture, which in turn is then assigned to a Picture variable, results in two valid object references.

Both ways should be legal according to the docs.

Sorry for that mistake.

We open the folder item using a BinaryStream and just read the raw data into a memoryblock. The default mime type is png. If it’s a jpeg file that you’re reading from, the conversion to a picture is probably failing. Try setting the mime type to “image/jpeg” after loading the file.

BTW this corresponds to <https://xojo.com/issue/41115>

Actually, the MIME Type is already set to “image/jpeg” automatically with no manual setting on my side.

As said, it was already “image/jpeg” – but I reset it o “image/jpeg” again and it didn’t work either - Pic is still NIL.

ShowURL(webPic.URL) is working fine, btw. Similarly, I can display it in an WebImageView with no issues.

Okay, I think I narrowed the bug down.

Most likely the Operator_Convert for the “WebPic to Pic” case is flawed (not the other way around). I guess it should actually be assigning the MemoryBlocks. Because when I do that manually, it works!

[code] Dim webPic As New WebPicture(picFile)
Dim pic As Picture = webPic

break // pic is still NIL

pic = Picture.FromData(webPic.Data) // both methods getter/setter for the MemoryBlock containing raw data

break // guess what, it worked! Pic is *not* NIL anymore but holds the correct picture
[/code]

I’ll update the Feedback case accordingly

it looks like you’re right. When you set a webpicture using anything other than a picture, you can’t get a picture out.

It’s still somewhat puzzling that Picture.Open(FolderItem) works though, because the .Open method returns a Picture object (AFAIK) and is then immediately converted to a WebPicture. So we’ll end up at the same point like we’d create the WebPicture with the constructor:

Dim webPic As New WebPicture(FolderItem) // This returns a valid WebPicture! Dim pic As Picture = WebPic // this doesn't work

Dim webPic As WebPicture = Picture.Open(FolderItem) // This returns a valid WebPicture too, but this was true for the constructor method above too! Dim pic As Picture = WebPic // now this works

So the bug might be not that obvious than I thought. Once the operator_convert works while in the other case it doesn’t. Except you would save the Picture object in the WebPicture somewhere in the background and assign that one when converting instead of the raw data?

EDIT: Picture.Open(FolderItem) apparently returns a PNG, while WebPicture(ForlderItem) loads the image in its orginial format JPEG. So the Operator_Convert (WebPicture > Picture) likely fails for WebImages other than PNG, although direct assignment of the MemoryBlocks works in either case.

EDIT 2: Cannot confirm. I replaced the JPEG image with a PNG formatted image and the first code block still doesn’t work with the constructor. Fascinating.

EDIT 3: Maybe this helps you in bug hunting - either method returns different MemoryBlocks:

[code] Dim picFile As FolderItem = SpecialFolder.Desktop.Child(“TestPic.png”) //now using PNG

If picFile.Exists = false Then
  break
End If

Dim webPic1 As New WebPicture(picFile)  //mData.Size = 155499
Dim pic1 As Picture = webPic1 //NIL

Dim webPic2 As WebPicture = Picture.Open(picFile)   //mData.Size = 155866
Dim pic2 As Picture = webPic2 //Not NIL

break[/code]

Apart from that (and some obvious ones like URL), all debugger variables are identical.

You can stop looking. I found the bug and it’s one that’s not evident to end users. Basically, there are four constructors for WebPicture and among them two different methods of storing the backing data. We’ll get these fixed in a future release.

For the time being, if the conversion from WebPicture to Picture fails, you can convert the Data property into a picture using this code:

Dim p as Picture = Picture.FromData(yourWebPicture.Data)

Excellent, thank you Greg! Your efforts are highly appreciated!
Bug hunting is somewhat fun, a little bit like Sherlock Holmes for bits and bytes :slight_smile: