Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
On 04/12/2014 at 02:16, xxxxxxxx wrote:
Hello,
I hope someone can help me with this! I can´t find an easy way to get a Bitmap out of a Bodypaint layer. I want to show those Layers on an Userarea, how can I do this? Additionally it seems to me that some bodypaint features are not available in Python? (at the bottom of the thread)
What I´ve found out so far:
if there is an active BB texture;
tex = bodypaint.PaintTexture.GetSelectedTexture() texturename = tex.GetFilename() actlay = tex.GetActive()
if one have to load a new BB texture;
#loaddialog texturename = c4d.storage.LoadDialog(type= c4d.FILESELECTTYPE_IMAGES, title="Load Hdr", flags=c4d.FILESELECT_LOAD) #pass it to BB and make itself and the first layer active settings = c4d.BaseContainer() settings.SetFilename(c4d.LOADTEXTURE_FILENAME, texturename) tex = bodypaint.SendPainterCommand(c4d.PAINTER_LOADTEXTURE, doc=doc, tex=None, bc=settings) if not tex:return lay = tex.GetFirstLayer() tex.SetActiveLayer(lay, activatetexture=True, show=True) #get the active layer actlay = tex.GetActive() print actlay, "layer" #read layerdimensions res = actlay.GetBoundingBox() xres = res['x2'] yres = res['y2'] #check attributes print actlay[c4d.ID_BASELIST_NAME] print actlay[c4d.ID_PAINTBITMAP_PREVIEW] print actlay[c4d.ID_PAINTLAYER_BLEND] print actlay[c4d.ID_PAINTLAYER_OPACITY] print actlay[c4d.ID_PAINTLAYER_SHOW] #add a new layer print tex.AddLayerBmp(insertafter=ActLay, useundo=True, activate=True) ###################################################################### #save the whole texture and pass it to the userarea is not what I want ###################################################################### #orig = bitmaps.BaseBitmap() #orig.InitWith(texturename) #bitmaps.ShowBitmap(orig) ######################################################################
-How to add a new layer on top of the last one? Why only insertafter? -[c4d.ID_PAINTBITMAP_PREVIEW]is always None?
Thanks in advance Martin
On 04/12/2014 at 06:26, xxxxxxxx wrote:
to get the raw content of a bitmap layer use GetPixelCnt(). Then you can copy this data into a BaseBitmap with SetPixelCnt(). You find examples how to use this functions in the painting examples in the C++ and Python SDK like SculptPaintBrush.
if actlay.IsInstanceOf(c4d.OBJECT_PAINTLAYERBMP) == True: bmp = actlay.ToPaintLayerBmp() xres = bmp.GetBw() yres = bmp.GetBh() size = xres * yres if size == 0: return colorMode = bmp.GetColorMode() # prepare storage sq = storage.ByteSeq(None, size*c4d.COLORBYTES_RGB) inc = 3 # read data for row in xrange(yres) : offset = sq.GetOffset(row*(xres*inc)) bmp.GetPixelCnt(0, row, xres, offset, colorMode, c4d.PIXELCNT_0) # prepare bitmap baseBitmap = bitmaps.BaseBitmap() baseBitmap.Init(xres,yres,) # write data for row in xrange(yres) : offset = sq.GetOffset(row*(xres*inc)) baseBitmap.SetPixelCnt(0, row, xres, offset, inc,colorMode, c4d.PIXELCNT_0) # save filename = c4d.storage.SaveDialog(title="Save preview") baseBitmap.Save(filename,c4d.FILTER_TIF)
AddLayerBmp() should accept None as an argument for "insertafter". This is a bug. ID_PAINTBITMAP_PREVIEW returns a CUSTOMDATATYPE_BITMAPBUTTON which is currently not supported in Python.
Best wishes, Sebastian
On 04/12/2014 at 07:00, xxxxxxxx wrote:
Hello Sebastian,
Thank you very much! Tremendous help as always! Just two hours ago I started with storage and bytesequence, but could´nt get it to work. I tried it with the new R16 function PaintLayerBmp.GetPixelCnt
PaintLayerBmp.GetPixelCnt
sq = storage.ByteSeq(None, xres*yres*inc) ActLay.GetPixelCnt(0, 0, cnt, sq , dstmode= c4d.COLORMODE_RGB, flags= c4d.PIXELCNT_0)
But no luck! Do you have a working example ?
AddLayerBmp() does not accept None. the resulting errormessage: TypeError: argument 1 must be c4d.modules.bodypaint.PaintLayer, not None Could you please give it a try?
Thanks again Martin
On 04/12/2014 at 07:43, xxxxxxxx wrote:
Hi Martin,
Here a script that read a bitmap file, converts it to spherical and writes it back.
import c4d, math from c4d import bitmaps, gui, storage from c4d import plugins # # spherical projection # y=y, x=x*cos(y) # BUTTON_ID_SELECT = 1001 MY_PATH = 1003 MY_FILEDIMENSIONS = 1007 MY_GOBUTTON = 100014 MY_LINKBOX = 100015 #global variables width = 0 height = 0 orig = 0 path = None Tolerance = 0.0000001 masterRadius = 1 derivedRadius = math.pi/2 class YourDialog(gui.GeDialog) : def CreateLayout(self) : self.SetTitle("Spherical Projection.") self.GroupBegin(id=8000, flags=c4d.BFH_LEFT, cols=2) #, rows=1) self.GroupBorderSpace(10, 10, 10, 20) self.AddButton(BUTTON_ID_SELECT, flags=c4d.BFH_LEFT, initw=145, inith=30, name="Select Input file") self.element = self.AddStaticText(id=MY_PATH, flags=c4d.BFH_MASK, initw=600, name=" ", borderstyle=c4d.BORDER_NONE) self.element = self.AddStaticText(id=11004, flags=c4d.BFH_MASK, name="File Dimensions ", borderstyle=c4d.BORDER_NONE) self.element = self.AddStaticText(id=MY_FILEDIMENSIONS, flags=c4d.BFH_MASK, initw=600, name=" ", borderstyle=c4d.BORDER_NONE) self.AddSeparatorH(inith=80) self.AddSeparatorH(inith=80) self.AddButton(MY_GOBUTTON, c4d.BFV_MASK, initw=145, name="Go!") self.GroupEnd() return True def Command(self, id, msg) : global width, height, orig, path, copy if (id == BUTTON_ID_SELECT) : path = storage.LoadDialog(type=c4d.FILESELECTTYPE_IMAGES, title="Please Choose a 32-bit Image:") print "Path: ", path if (path != None) : # Create and initialize selected image orig = bitmaps.BaseBitmap() if orig.InitWith(path)[0] != c4d.IMAGERESULT_OK: gui.MessageDialog("Cannot load image \"" + path + "\".") return # Get selected image infos width, height = orig.GetSize() #print "w+h: ", width, " - ", height bits = orig.GetBt() #print "bt: ", bits self.SetString(MY_PATH, path) self.SetString(MY_FILEDIMENSIONS, str(width)+"X"+str(height)+ " Bits: "+str(bits)) # Create the copy and initialize it copy = bitmaps.BaseBitmap() copy.Init(width, height, bits) #return True if (id == MY_GOBUTTON) : #c4d.EventAdd() #self.Close() #print "Gobutton path: ", path if (path == None) : gui.MessageDialog ("No Input File selected!") return -1 ret = SphericalProjection(self.GetString(MY_PATH)) #print "Showbitmaps orig + copy" bitmaps.ShowBitmap(orig) bitmaps.ShowBitmap(copy) return True def DestroyWindow(self) : #Use this method to toggle the switch back to it's original off state #obj[c4d.ID_USERDATA, 1]=0 c4d.EventAdd() def SphericalProjection(path) : global width,height,orig c4d.gui.SetMousePointer(c4d.MOUSE_BUSY) if not path: return height2 = height / 2 width2 = width / 2 for ix in range(width) : for iy in range(height) : ycos = math.sin(math.radians(90.0/height2)*iy) x = width2 + (width2-ix)*ycos r,g,b = orig.GetPixel(int(x), iy) copy.SetPixel(width-ix, iy, r, g, b) return True if __name__=='__main__': dlg = YourDialog() dlg.Open(dlgtype= c4d.DLG_TYPE_ASYNC, defaultw=400) #, xpos=600, ypos=500, defaultw=200, defaulth=200)
On 04/12/2014 at 08:53, xxxxxxxx wrote:
Hello Martin,
do you have any questions about the above example or the linked examples?
As stated above, it is a bug that AddLayerBmp() does not accept None.
On 04/12/2014 at 09:27, xxxxxxxx wrote:
@Sebastian ahh, I see, I assigned the bug statement to the bitmapbutton for whatever reason.Thanks.
The example is pretty clear. You just used the new GetPixelCnt method? Thanks!
For the Limit list on support site, should I write an email that it´s not possible in Python, or will this restrictions registered automatically?
@Pim Thanks!
Best wishes Martin
On 05/12/2014 at 01:50, xxxxxxxx wrote:
just in case someone needs to know. To avoid the layer insertion point bug, one can use GeListNode class commands like:
#add a new layer newlayer = tex.AddLayerBmp(insertafter=actlay, useundo=True, activate=True) # as (insertafter= None) does not work a workaround to paste the new layer on top of the list newlayer.InsertBefore(tex.GetFirstLayer()) #to avoid problems with previous loaded textures, set the first layer activ first = tex.GetFirstLayer() tex.SetActiveLayer(first, activatetexture=True, show=True)
@Sebastian could you please explain what´s the difference between GetPixelCnt with a Bitmap and a BodyPaint layer? I didn´t get it.
On 05/12/2014 at 05:42, xxxxxxxx wrote:
PaintLayerBmp.GetPixelCnt() and BaseBitmap.GetPixelCnt() are two different methods of two different classes. They are used pretty much the same way; the only difference is that BaseBitmap.GetPixelCnt() allows you to define a byte increment per pixel for the output buffer.
best wishes, Sebastian