Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    BaseBitmap.CopyPartTo() with grayscale image

    Cinema 4D SDK
    python sdk
    3
    5
    806
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • oli_dO
      oli_d
      last edited by oli_d

      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

      1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand
        last edited by ferdinand

        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

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • oli_dO
          oli_d
          last edited by oli_d

          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

          1 Reply Last reply Reply Quote 0
          • M
            m_adam
            last edited by

            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.

            MAXON SDK Specialist

            Development Blog, MAXON Registered Developer

            1 Reply Last reply Reply Quote 0
            • oli_dO
              oli_d
              last edited by

              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

              1 Reply Last reply Reply Quote 1
              • First post
                Last post