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()