Auto load folder of images to material [SOLVED]



  • On 29/05/2015 at 12:24, xxxxxxxx wrote:

    Hi everyone!

    I don't know python at all but I'm trying to figure out how to automate part of a process for a job I'm working on.

    My goal is to load images from the "tex" folder into the color channel of the material on my object, keyframe it, move to the next image, then next frame, keyframe, etc., until all images in that folder have a keyframe on the same material. I've been doing it by hand for this job for folders with 160 images and making mistakes, and now the job requires me to do that for folders much larger! ARgh!

    I know you can use the animate function on a material to pull a folder of images but it doesn't import the image path nor does it create an actual keyframe which I need for my project to work correctly.

    I've been pulling python code from various places and trying to toy around and get something to work but I just lack the knowledge and experience. Had I more time I could maybe flesh it out but as I don't have a ton of time I am turning to you :-)

    I found this code that loads an image from the desk top. It seems to work but I can't seem to change the path to, say, the tex folder in my job....but on top of that I need it to do more.

    import c4d
    import os

    def main() :

    fn = c4d.storage.GeGetC4DPath(c4d.C4D_PATH_DESKTOP) #Gets the desktop path
        pathToTexture = os.path.join(fn,'01.jpg')      #Gets the specific texture image on your desktop

    mat = doc.GetActiveMaterial()                       #Assign the active material a variable
        shdr_texture = c4d.BaseList2D(c4d.Xbitmap)          #Create a bitmap shader in memory
        shdr_texture[c4d.BITMAPSHADER_FILENAME] = pathToTexture #Assign the path to the texture image to your shader 
        mat[c4d.MATERIAL_COLOR_SHADER]= shdr_texture        #Assign the shader to the color channel in memory only
        mat.InsertShader(shdr_texture)                      #Insert the shader into the color channel
        mat.Update(True, True)                              #Re-calculate the thumbnails of the material

    if __name__=='__main__':
     main()

    I've also pulled some other code that might get the job done but I am not sure how to implement it.

    imageList = os.listdir(folder) # get folder contents
    
    frame = document.GetFrame() # determin the current frame
    
    offset = 0 # define frame offset
    
    frameOffset = frame+offset # calculate the offset
    
    material[c4d.imageSlot] = imagelist[frameOffset] # set image in material
    
    
    Any help would be greatly appreciated. 
    


  • On 29/05/2015 at 17:20, xxxxxxxx wrote:

    Hi and welcome ibycus!

    this code should answer your question.
    If something is nonspecific or you have other questions feel free to ask.

    Best wishes
    Martin

      
    import c4d, os  
    from c4d import gui, bitmaps  
      
      
    def main() :  
      #_________________________________________________  
      #assuming your scene was saved before  
      abspath= doc.GetDocumentPath()+"/"+"tex"  
      imageList = os.listdir(abspath)  
      if imageList == []:  
          return  
        
        
      #_________________________________________________  
      #validate pictures fast  
      #just check the extensions  
      #ensure that there is no hidden .DS_Store etc  
      ext = (".jpg", ".png", ".gif") #and so on   
      for f in imageList:  
          if not any(f.endswith(e) for e in ext) :  
              imageList.remove(f)  
        
      if imageList == []:  
          return  
        
        
      #_________________________________________________  
      #validate pictures slow  
      #initialize every picture with c4d  
      #""for i in imageList:  
          #""orig = bitmaps.BaseBitmap()  
          #""if orig.InitWith(abspath+"/"+i)[0] != c4d.IMAGERESULT_OK:  
              #""imageList.remove(i)  
                
      #""if imageList == []:  
          #""return  
        
        
                
      #_________________________________________________  
      #validate material and shader  
      mat = doc.GetActiveMaterial()   
      if not mat:  
          return  
      shader = mat[c4d.MATERIAL_COLOR_SHADER]  
        
      if not shader:  
          shader = c4d.BaseList2D(c4d.Xbitmap)  
          shader[c4d.BITMAPSHADER_FILENAME] = imageList[0]  
          mat[c4d.MATERIAL_COLOR_SHADER] = shader  
          mat.InsertShader(shader)  
            
      if shader.GetType() != c4d.Xbitmap:  
          print "No valid bitmapshader in the slot! Please remove the current shader."  
          return  
        
      #_________________________________________________  
      #validate animation track and curve      
      tracks = shader.GetCTracks()  
      track = []  
        
      if tracks != []: #if there is any track   
          for tr in tracks:  
              if tr.GetDescriptionID()[0].id == c4d.BITMAPSHADER_FILENAME and tr.GetObject() == shader :#check if there already exists a filetrack at the shader  
                  track = tr  
                  curve = track.GetCurve()  
          if not track:  #if not build it   
              descid = c4d.DescID(c4d.DescLevel(c4d.BITMAPSHADER_FILENAME,c4d.DTYPE_FILENAME))  
              track = c4d.CTrack(shader,descid)  
              shader.InsertTrackSorted(track)          
              curve = track.GetCurve()      
                    
      else: #if there is no track at all, build a file track  
          descid = c4d.DescID(c4d.DescLevel(c4d.BITMAPSHADER_FILENAME,c4d.DTYPE_FILENAME))  
          track = c4d.CTrack(shader,descid)  
          shader.InsertTrackSorted(track)          
          curve = track.GetCurve()   
      
      #_________________________________________________  
      #store current time and ensure the document takes long enough  
      lenList = len(imageList)  
      intime = doc.GetTime()  
      fps = doc.GetFps()  
      inframe = intime.GetFrame(fps)  
      maxtime = doc.GetMaxTime().GetFrame(fps)  
        
      if maxtime < lenList:  
          newtime =c4d.BaseTime(float(lenList)/fps)  
          doc.SetMaxTime(newtime)  
          doc.SetLoopMaxTime(newtime)  
            
      #_________________________________________________  
      #for every item in imagelist set a key to the shaders curve  
      for i in xrange(lenList) :  
        
          frame = i  
          keyTime = c4d.BaseTime(frame,fps) #set up the basetime object  
            
          addPicture = curve.AddKey(keyTime) #try to add a key to the curve  
          if addPicture:  
              shader[c4d.BITMAPSHADER_FILENAME] =imageList[i] #assign the image to the shader  
              keyPicture = addPicture["key"] #grab the key variable from the key dict  
              keyPicture.SetGeData(curve, imageList[i]) #assign imagedata to the key  
              track.FillKey(doc, shader, keyPicture) #fill the key on track  
        
      #_________________________________________________  
      #go to the stored frame and animate everything at this frame to update the scene  
      doc.SetTime(intime)  
      doc.ExecutePasses(None, True, False, False, 0)  
      c4d.EventAdd()    
        
                          
    if __name__=='__main__':  
      main()  
      
      
      
    


  • On 01/06/2015 at 07:55, xxxxxxxx wrote:

    Holy Moly!

    Thanks a lot! That was a little more involved than I thought it would be. Thanks so much for taking the time to look at this and leaving notes so I can see whats going.

    You have set up a "fast load" and a "slow load", the slow load is disabled. What exactly is the difference between the two? I couldn't get the slow load to do anything for me.

    Also, it seems to be loading the image list in a random order. Is there anyway to force is to load alphabetically?

    Thanks again,

    Ashly



  • On 01/06/2015 at 11:40, xxxxxxxx wrote:

    Hi Ashly,

    you´re welcome!

    Here everything works as expected.
    You might use some python sort routine to sort your list alphabetically.

      
     sorted(imageList, key=str.lower)  
    

    The slow load is way overdone, it initializes every bitmap in c4d.
    The fast load just checks if file endings match the types you defined in the extension list.
    They both should do the same with your imageList, if the extension list is well defined.
    But with the slow load you´ll be absolutely sure that c4d can handle your files.
    (There might be cases where your file has e.g. a .tif ending but is no picture at all.)
    Furthermore you can manipulate the bitmaps in c4d.

    Hope this helps!

    Best wishes
    Martin



  • On 02/06/2015 at 09:13, xxxxxxxx wrote:

    Thanks Martin!

    You are a gentlemen and a scholar.

    I ended up getting it to work with

    imageList.sort()


Log in to reply