Bitmap to GeClipMap
On 22/05/2013 at 23:59, xxxxxxxx wrote:
Cinema 4D Version: R14
Platform: Windows ;
Language(s) : C++ ;
how does one copy a BaseBitmap to a GeClipMap!?
I can't use Init as I'm wanting to access the SetOffset() in the GeClipMap. There are also other Bitmaps drawn that I'd like to place into the GeClipMap...
Is this not possible?
On 23/05/2013 at 00:30, xxxxxxxx wrote:
what you write about SetOffset() is a bit confusing, as it is just a method to offset drawing
operations (that doesn't even have a return value), but long story short, if you do not want/
can use Init() with a basebitmap you have to draw your content pixel by pixel.
On 23/05/2013 at 03:03, xxxxxxxx wrote:
Hi there LD,
the offset I use as you mention to offset drawing things. I was hoping I might be able to use it along with some sort of BaseBitmap->GeClipMap copy operation so I could add and position a small bitmap icon into the GeClipMap draw.
But it looks like I might have to do this the pixel by pixel way or using some layering of bitmaps... I'll play with it some more.
On 23/05/2013 at 03:16, xxxxxxxx wrote:
GeClipMap is a something of a 'helper' for grabbing rectangular sections of a bitmap. If you want to use it with mulitple bitmaps, then you might need to preprocess (somehow) the various clips from the various BaseBitmaps to get a size for Init() - even if an approximation. Init() is a required call. As the docs say:
"Be sure to call Init() methods before you attempt to use a newly allocated clip map."
This, I would assume, assures that the clipmap memory size is allocated to accept the image data being received. One cannot circumvent that and expect stability and avoid crashes. Most of this depends on whether or not you have all of the source bitmaps and the areas for the 'icons' beforehand or it is user-interactive (the latter being more fraught with peril).
On 23/05/2013 at 03:55, xxxxxxxx wrote:
thanks for your input. I had used the Init() call to start the GeClipMap, but I have some other BaseBitmap draws that I wanted to copy and position into the main GeClipMap draw. I was hoping to have a custom function that could do all of this so that it didn't clog my plugin's Draw() function up too much.
I'm hoping to make this bit user interactive but it won't need to change draw size thankfully (at this time anyway!).
So what I'm doing for the moment is just layering them up with DrawTexture() (the draw is being done from a SceneHook incidently). It's working this way, it just means I have to use a whole lot of DrawTexture() calls in the Draw function instead of calling a custom function a single time (and with one line of code!).
On 13/06/2013 at 06:57, xxxxxxxx wrote:
EDIT: a new post was created that focuses on the problems with Blit() mentioned afterwards (SDK Help / GeClipMap::Blit())
I'm trying to solve a similar task. I'm using a GeClipMap and preload it with a background image. Onto such background image I want to place additional images. So in principle the same as if you would work in Photoshop with many layers - having a background image in the lowest layer and stack additional images (partly transparent) on top of it.
From my understanding the Blit() method of GeClipMap would be the best choice for doing such task. You have a GeClipMap (=destination) and some additional GeClipMaps (sources). With GeClipMap::Blit() you can copy diverse sources into the destination. You can specify a destination position and a source rectangle, so you should be able to cut out fractions of a source and place it anywhere in the destination.
That's the theory - but now comes the bad part of the storry: Blit() doesn't seem to work - that's my experience (and maybe also from ScottA who had some tries last year (2012) trying to do some sprite animations). I'm using Cinema R13.061, C++, Windows 7.
Maybe Blit() works fine in your environment (other C4D release or in Python).
I use the following code snippets in my C++ Plugin:
In Plugin-Init() : doing the Alloc + Init of the GeClipMaps
cmp1 = GeClipMap::Alloc();
cmp_red = GeClipMap::Alloc();
cmp_green = GeClipMap::Alloc();
cmp_blue = GeClipMap::Alloc();
res = cmp1->Init("d:\\Background_240x240.png",0, &ismovie);
res = cmp_red->Init("d:\\Red_100x100.png",0, &ismovie);
res = cmp_green->Init("d:\\Green_100x100.png",0, &ismovie);
res = cmp_blue->Init("d:Blue_100x100.png",0, &ismovie);
In Plugin-Draw() :
cmp1->Blit(10,10,(const GeClipMap&)cmp_red, 10,10, 80,80, GE_CM_BLIT::GE_CM_BLIT_COL);
cmp1->Blit(10,10,(const GeClipMap&)cmp_green, 10,10, 80,80, GE_CM_BLIT::GE_CM_BLIT_COPY);
cmp1->Blit(10,10,(const GeClipMap&)cmp_blue, 10,10, 80,80, GE_CM_BLIT::GE_CM_BLIT_FG);
bd->DrawTexture(cmp1->GetBitmap(), padr, cadr, vnadr, uvadr, 4, DRAW_ALPHA::DRAW_ALPHA_FROM_IMAGE, DRAW_TEXTUREFLAGS_0);
So in my case cmp_red/green/blue are the source images and cmp1 is the destination image (initialized with the background image) which is finally drawn with BaseDraw::DrawTexture() into the editor view. I skipped the code for setting up the data structures padr+cadr+vnadr+uvadr (such code was already posted by ScottA in this forum and was very helpful for me - thanks ScottA). The only thing I see on the screen is the background image with a line from 0,0 to 100,100 and the "Hello" text. The red/green/blue images aren't shown (although I tried all possible BLIT-modes specified by the last parameter of Blit()). Also locating the Blit() calls after the TextAt() call didn't help.
When I draw the cmp_red/gree/blue via BaseDraw::DrawTexture(), I get them shown in the editor view, but DrawTexture doesn't provide the BLIT modes like Blit() and splitting all the drawing actions up by using two different classes (BaseDraw and GeClipMap) isn't nice.
It would be fine if this code is working for your task. Maybe you/someone else in this forum could give an answer if Blit() works generally fine (i.e. only I would have such problem, maybe caused by wrong usage) or if there's a known bug inside Blit().
PS: trying to get solved own problems over other persons posts is no good style. I hope this is ok, because the name of the topic fits perfectly and Blit() should be the right choice.
On 13/06/2013 at 07:25, xxxxxxxx wrote:
Hey there FrozenFritz,
I don't mind peeps hijacking my threads! If it adds another angle to the conversation and someone can benefit from it, by all means!
I must admit I've completely missed the Blit() method in GeClipMap. I'll have a play with that sometime and get back to the forum when I can. As mentioned I do have a draw that's working through DrawTexture() (just drawing DrawTextures() on top of each other) but it'd make things a bit cleaner and more organised having this in a GeClipMap. Might also make it faster - though that's not much of an issue for myself at the moment. If anything it also opens up further drawing options inside the code that BaseBitmap doesn't provide. I've noted it in my to-do list and I'll have a play when I can.
Thanks for bringing it up. Though one thing does spring to mind, if it's not working in R13, then it might make backwards compatibility a little more trixy-dixy...
On 13/06/2013 at 12:22, xxxxxxxx wrote:
Originally posted by xxxxxxxx
cmp1->Blit(10,10,(const GeClipMap&)cmp_red, 10,10, 80,80, GE_CM_BLIT::GE_CM_BLIT_COL); cmp1->Blit(10,10,(const GeClipMap&)cmp_green, 10,10, 80,80, GE_CM_BLIT::GE_CM_BLIT_COPY); cmp1->Blit(10,10,(const GeClipMap&)cmp_blue, 10,10, 80,80, GE_CM_BLIT::GE_CM_BLIT_FG);
...uhm, I think you are passing in GeClipMap _pointers_, cast incorrectly. Have you tried:
cmp1->Blit(10,10, *cmp_red, 10,10, 80,80, GE_CM_BLIT::GE_CM_BLIT_COL); cmp1->Blit(10,10, *cmp_green, 10,10, 80,80, GE_CM_BLIT::GE_CM_BLIT_COPY); cmp1->Blit(10,10, *cmp_blue, 10,10, 80,80, GE_CM_BLIT::GE_CM_BLIT_FG);
On 13/06/2013 at 13:35, xxxxxxxx wrote:
thanks for the reply. I created a new post for my problem with Blit(), because I don't want to missuse WickedPs post to discuss my problems and to lead his post/issue in a different direction.
The link to that post is https://plugincafe.maxon.net/topic/7263/8393_geclipmapblit
But anyway: your remark is good, but the cmp1 and cmp_red/green/blue are defined as pointers within the private section of my plugin class. Sorry for the confusion. The definition looks like that:
The cast operator was necessary because of the 'const'. My pointer definitions don't contain a 'const' and they shouldn't, because the pointers have to get initialized (=changed) via GeClipMap::Alloc() after my plugin (which is a tag) gets instantiated (=attached to an object in the scene manager). That Alloc() is done in the Init() function of the plugin (and vice versa Free() is called in the plugins Free()
On 13/06/2013 at 17:40, xxxxxxxx wrote:
You missed my point... I know that they are pointers - the problem is that the Blit() routine is NOT expecting pointers as input. Please try my example and see if it fixes your problem.
On 14/06/2013 at 04:40, xxxxxxxx wrote:
you're right. I tried your example and now it works. Many thanks !!
I didn't waste a thought that Blit() would need something else as the pointer
On 14/06/2013 at 12:16, xxxxxxxx wrote:
Why it doesn't just take a pointer is beyond me - that would have been the easiest and most logical thing to pass (since we have to Alloc() to use the GeClipMap class at all).
Glad you got it working.
On 23/06/2013 at 07:17, xxxxxxxx wrote:
just a note to anyone that may have been following this - as other threads have confirmed, this does indeed work as a 'layer' system. I've swapped my Bitmaps for GeClipMaps where I can and it's all working as expected.