ShowBitmap() from website URL
-
Hi! plugincafe~
I try to get an image from website, And ShowBitmap() in C4D python.
This is my simple code:import c4d from c4d import gui, bitmaps def main(): img = "https://images.pexels.com/photos/10204089/pexels-photo-10204089.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" bmp = bitmaps.BaseBitmap() a,b = bmp.InitWith(img) print(a,b) if a == c4d.IMAGERESULT_OK: bitmaps.ShowBitmap(bmp) bmp.FlushAll() # Execute main() if __name__=='__main__': main()
Sometimes it can ShowBitmap() correctly like this:
Sometimes it's can show bitmap but the image is not loaded correctly:
And sometimes it's faild! And the InitWith() result is -6
Is there have some right way to show an image from the URL? -
Hello @gheyret,
Thank you for reaching out to us. The reason why this is failing for you is due to you not caching the content you want to put into the
BaseBitmap
or alternatively not using a high-level-enough interface.You can download the content of the image at your URL into either a temporary cache file or an in-memory file or use
LoadFile
and let Cinema 4D handle the rest. Find a simple example for each approach at the end of my posting.When you are still running into problems, you should first try to see if you can access the whole file in principle. For example, with
urllib3
which I am using in the code below.Cheers,
FerdinandThe result:
The code:
"""Simple example for displaying three different images, referenced by an HTTP scheme url each, in the Picture Viewer. """ import c4d import urllib3 def main(): """Shows three approaches for how to display an image in the picture viewer that has a http(s) url scheme. """ # Your image url, make sure to escape paths properly or to use raw strings # as I do here. url = (r"https://images.pexels.com/photos/10204089/pexels-photo" + r"-10204089.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500") # Your and my forum avatar as png images. urlGheyret = (r"https://developers.maxon.net/forum/assets/uploads/profile/" + r"256-profileavatar-1631789551927.png") urlFerdinand = (r"https://developers.maxon.net/forum/assets/uploads/profile/" + r"1024-profileavatar.png") # The interface to make requests with in urllib3. poolManger = urllib3.PoolManager() # Approach I: # Attempt to connect to the url. response = poolManger.request('GET', url) if response.status != 200: raise RuntimeError( f"Could not access {url} with the code: {response.status}.") # Write the image to a local file. tempFile = "e:\\cache.tmp" with open(tempFile,"wb") as f: f.write(response.data) # Load the file as a BaseBitmap into the PictureViewer. bmp = c4d.bitmaps.BaseBitmap() result, isMoviev = bmp.InitWith(tempFile) if result != c4d.IMAGERESULT_OK: raise RuntimeError( "Could not initialize BaseBitmap with downloaded content.") # Show the bitmap. c4d.bitmaps.ShowBitmap(bmp) # We do not need to flush any bitmaps here, since the bitmap is being # deallocated by scope and #ShowBitmap() makes a copy anyways. # Approach II: # Get your forum avatar. response = poolManger.request('GET', urlGheyret) if response.status != 200: raise RuntimeError( f"Could not access {url} with the code: {response.status}.") # Load the data from the response into a MemoryFileStruct and try to # initialize a bitmap with it. byteArray = bytearray(response.data) memFile = c4d.storage.MemoryFileStruct() memFile.SetMemoryReadMode(byteArray, len(byteArray)) bmp = c4d.bitmaps.BaseBitmap() result, isMoviev = bmp.InitWith(memFile) if result != c4d.IMAGERESULT_OK: raise RuntimeError( "Could not initialize BaseBitmap with downloaded content.") # Show the bitmap. c4d.bitmaps.ShowBitmap(bmp) # Approach III: # Approach is a bit of an overstatement here, but internally, i.e., in # C++, we use the maxon API for such stuff, specifically the maxon:Url # type, which hides most of these downloading shenanigans away. And # while maxon::UrlInterface has already been exposed to Python as # maxon.UrlInterface, some tidbits are still missing, to make a more # low-level use of it. But we can call a high-level interface with a # url string (or Filename in terms of the classic API) and let the # core do its thing. In this case it simply means calling LoadFile(). This # will however not expose the BaseBitmap, and instead just load the image # into the picture viewer. You will also get GUI events in some cases, as # for example when you attempt to load the same url twice, as Cinema 4D # will ask you then if you really want to do that. # Load the image at #urlFerdinand into Cinema 4D, which will reflect as # it being loaded into the Picture Viewer. c4d.documents.LoadFile(urlFerdinand) if __name__ == '__main__': main()
-
@ferdinand
Wow! you perfectly solved my problem!
Thank you!