BaseBitmap.CopyPartTo() with grayscale image
-
Hi,
I have a problem with the method BaseBitmap.CopyPartTo()
when the basic image is in grayscale it doesn't work ! (with RGB file it works fine)Tested with r21 and s22 on macos 10.13.6
-
Hi,
while I would not rule it out categorically that "it does not work with greyscale images", it seems very unlikely. You also forgot to tag your posting (I assume this is a Python question), to give us some example code for which the operation fails and to give us the precise symptoms of failing, i.e. the exact exception, an error code, etc.
However, this is the first thing I would check: Have you initialised your bitmap you want to copy to properly as a greyscale bitmap with a sufficient bit-depth via
BaseBitmap.Init
?Cheers,
zipit -
Thanks for the answer and sorry for the incomplete post ! You're absolutely right I should have put the code.
Here is an example:
import c4d def main(): fn = '/Users/donzeo/Documents/TEMP/ESRI_world_imagery-19.png' bmp = c4d.bitmaps.BaseBitmap() bmp.InitWith(fn) h,w = bmp.GetSize() mode = bmp.GetColorMode() if mode == c4d.COLORMODE_GRAY or mode == c4d.COLORMODE_AGRAY: flag = c4d.INITBITMAPFLAGS_GRAYSCALE else : flag = c4d.INITBITMAPFLAGS_NONE crop_bmp = c4d.bitmaps.BaseBitmap() if crop_bmp.Init(h/2,w/2,depth = bmp.GetBt(), flags = flag) == c4d.IMAGERESULT_OK: print bmp.CopyPartTo(crop_bmp, 10, 10, w/2, h/2) c4d.bitmaps.ShowBitmap(crop_bmp) if __name__=='__main__': main()
By the way it's the same with BaseBitmap.GetClonePart() (which is more simple !) :
import c4d def main(): fn = '/Users/donzeo/Documents/TEMP/ESRI_world_imagery-19.png' bmp = c4d.bitmaps.BaseBitmap() bmp.InitWith(fn) w,h = bmp.GetSize() part = bmp.GetClonePart(0,0,w/2,h/2) if part : c4d.bitmaps.ShowBitmap(part) else: print'error' if __name__=='__main__': main()
With rgb image there is no problem. With a grayscale image impossible to get anything. I tried psd, png, jpg ...
Am I doing something wrong?
Cheers
-
Hi, unfortunately as stated in the BaseBitmap Documentation some functions work only with 24bits and 32bits bitmap.
The only workaround is to use GetPixelCnt and SetPixelCnt. You can find an example (which is about a 32bit bitmap so you have to adapt for your bitmap bit count) in copy_32bits_image_r13.
Note due to
Python 3
[URL-REMOVED] SetPixelCnt and GetPixelCnt will be changed in R23.
And here is the previous example adapted with this new version:""" Copyright: MAXON Computer GmbH Description: - Copies the internal data of a 32 bit per-channel image to a new one. Note: - BaseBitmap.GetClone could be used for doing the exact same purpose, bu Class/method highlighted: - BaseBitmap.SetPixelCnt() - BaseBitmap.GetPixelCnt() Compatible: - Win / Mac - R23 """ import c4d def main(): # Opens a Dialog to choose a picture file path = c4d.storage.LoadDialog(type=c4d.FILESELECTTYPE_IMAGES, title="Please Choose a 32-bit Image:") # If the user cancels, leaves if not path: return # Creates a BaseBitmap that will be used for loading the selected picture orig = c4d.bitmaps.BaseBitmap() if orig is None: raise RuntimeError("Failed to create the bitmap.") # Initializes the BaseBitmap with the selected picture if orig.InitWith(path)[0] != c4d.IMAGERESULT_OK: raise RuntimeError("Cannot load image \"" + path + "\".") # Checks if channel depth is really 32 bit if orig.GetBt()/3 != 32: raise RuntimeError("The image \"" + path + "\" is not a 32 bit per-channel image.") # Gets selected image information width, height = orig.GetSize() bits = orig.GetBt() # Creates a BaseBitmap that will be ued for making a copy copy and initialize it copy = c4d.bitmaps.BaseBitmap() if copy is None: raise RuntimeError("Failed to create the bitmap.") copy.Init(width, height, bits) if orig.InitWith(path)[0] != c4d.IMAGERESULT_OK: raise RuntimeError("Cannot load image \"" + path + "\".") # Calculates the number of bytes per pixel # Each pixel has RGB bits, so we need an offset of 'inc' bytes per pixel # the image has 32 bits per-channel : (32*3)/8 = 12 bytes per pixel (1 byte = 8 bits) # the image has 3 channels per pixel (RGB) : 12/3 = 4 bytes per component = 1 float inc = orig.GetBt() // 8 bytesArray = bytearray(width * height * inc) memoryView = memoryview(bytesArray) for row in range(height): memoryViewSlice = memoryView[row*(width*inc):] orig.GetPixelCnt(0, row, width, memoryViewSlice, inc, c4d.COLORMODE_RGBf, c4d.PIXELCNT_0) for row in range(height): memoryViewSlice = memoryView[row * (width * inc):] copy.SetPixelCnt(0, row, width, memoryViewSlice, inc, c4d.COLORMODE_RGBf, c4d.PIXELCNT_0) # Show original and copied image in the picture viewer c4d.bitmaps.ShowBitmap(orig) c4d.bitmaps.ShowBitmap(copy) if __name__ == '__main__': main()
Cheers,
Maxime.
[URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.
-
Thank you very much Maxime for the reply.
I'm looking forward to the r23 and the python 3 with a lot of impatience.Cheers