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 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.



  • 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


Log in to reply