Bodypaint Layer Bitmap [SOLVED]
-
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:
Hello,
to get the raw content of a bitmap layer use
GetPixelCnt()
[URL-REMOVED]. Then you can copy this data into a BaseBitmap withSetPixelCnt()
[URL-REMOVED]. You find examples how to use this functions in the painting examples in the C++ and Python SDK likeSculptPaintBrush
[URL-REMOVED].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()
[URL-REMOVED] should accept None as an argument for "insertafter". This is a bug. ID_PAINTBITMAP_PREVIEW returns aCUSTOMDATATYPE_BITMAPBUTTON
[URL-REMOVED] which is currently not supported in Python.Best wishes,
Sebastian
[URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.
-
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
[URL-REMOVED]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
[URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.
-
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.
Best wishes,
Sebastian -
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:
Hello,
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.Thanks in advance
Martin -
On 05/12/2014 at 05:42, xxxxxxxx wrote:
Hello,
PaintLayerBmp.GetPixelCnt()
[URL-REMOVED] andBaseBitmap.GetPixelCnt()
[URL-REMOVED] 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
[URL-REMOVED] @maxon: This section contained a non-resolving link which has been removed.