Open Search

    About

    MultipassBitmap is a subclass of BaseBitmap that provides support for multiple folders and layers. Such a folder or layer is represented as another MultipassBitmap.

    Warning
    For MAXON API image classes see Images Manual. For MAXON API media input and output see Media Sessions Manual.
    // This example creates a new MultipassBitmap with a custom layer.
    // The bitmap is saved as a multi layer TIFF file.
    const Int32 width = 1920;
    const Int32 height = 1080;
    const COLORMODE colorMode = COLORMODE::RGBf;
    // create MultipassBitmap with the given dimensions and color mode
    MultipassBitmap* multipassBitmap = MultipassBitmap::Alloc(width, height, colorMode);
    if (multipassBitmap == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    // add a new layer
    MultipassBitmap* const layer = multipassBitmap->AddLayer(nullptr, colorMode);
    if (layer)
    {
    layer->SetParameter(MPBTYPE::NAME, "Custom Layer");
    // fill layer
    const Int32 bufferSize = width * 3; // rgb
    ifnoerr (PIX_F * lineBuffer = NewMemClear(PIX_F, bufferSize))
    {
    for (Int32 y = 0; y < height; ++y)
    {
    const Float32 red = Float32(y) / Float32(height);
    Int32 offset = 0;
    for (Int32 x = 0; x < width; ++x)
    {
    const Float32 green = Float32(x) / Float32(width);
    // fill line buffer
    lineBuffer[offset] = red;
    lineBuffer[offset + 1] = green;
    lineBuffer[offset + 2] = 0;
    offset = offset + 3;
    }
    // fill line
    layer->SetPixelCnt(0, y, width, (UChar*)lineBuffer, COLORBYTES_RGBf, colorMode, PIXELCNT::NONE);
    }
    DeleteMem(lineBuffer);
    }
    }
    // save to file
    Filename imageFileName;
    // select a file name
    if (imageFileName.FileSelect(FILESELECTTYPE::IMAGES, FILESELECT::SAVE, "Save Image File"_s))
    {
    imageFileName = GeFilterSetSuffix(imageFileName, FILTER_TIF);
    // save as multi layer 32-bit TIF
    const IMAGERESULT res = multipassBitmap->Save(imageFileName, FILTER_TIF, nullptr, bits);
    ApplicationOutput("Error saving image.");
    }
    // destroy MultipassBitmap
    MultipassBitmap::Free(multipassBitmap);
    Filename GeFilterSetSuffix(const Filename &name, Int32 id)
    IMAGERESULT Save(const Filename &name, Int32 format, BaseContainer *data, SAVEBIT savebits) const
    Bool SetPixelCnt(Int32 x, Int32 y, Int32 cnt, UChar *buffer, Int32 inc, COLORMODE srcmode, PIXELCNT flags)
    Definition: c4d_basebitmap.h:774
    static BaseBitmap * Alloc()
    Manages file and path names.
    Definition: c4d_file.h:94
    Bool FileSelect(FILESELECTTYPE type, FILESELECT flags, const maxon::String &title, const maxon::String &force_suffix=maxon::String())
    Definition: c4d_basebitmap.h:975
    Bool SetParameter(MPBTYPE id, const GeData &par)
    Definition: c4d_basebitmap.h:1142
    static void Free(MultipassBitmap *&bm)
    MultipassBitmap * AddLayer(MultipassBitmap *insertafter, COLORMODE colormode, Bool hidden=false)
    Definition: c4d_basebitmap.h:1067
    PyObject * x
    Definition: bytesobject.h:38
    Py_UCS4 * res
    Definition: unicodeobject.h:1113
    #define NewMemClear(T, cnt)
    Definition: defaultallocator.h:204
    Float32 PIX_F
    32-bit float pixel type.
    Definition: ge_math.h:34
    maxon::UChar UChar
    Definition: ge_sys_math.h:57
    maxon::Float32 Float32
    Definition: ge_sys_math.h:68
    maxon::Int32 Int32
    Definition: ge_sys_math.h:60
    #define COLORBYTES_RGBf
    Floating point RGB.
    Definition: c4d_basebitmap.h:93
    COLORMODE
    Definition: ge_prepass.h:460
    @ RGBf
    32-bit floating point RGB channels.
    @ SAVE
    Save dialog.
    @ IMAGES
    Image files.
    #define FILTER_TIF
    TIFF.
    Definition: ge_prepass.h:186
    IMAGERESULT
    Definition: ge_prepass.h:3887
    @ OK
    Image loaded/created.
    @ NAME
    String Get/Set. The layer name.
    @ NONE
    None.
    SAVEBIT
    Definition: ge_prepass.h:276
    @ USE32BITCHANNELS
    Use 32-bit channels.
    @ MULTILAYER
    Save multiple layers.
    #define MAXON_SOURCE_LOCATION
    Definition: memoryallocationbase.h:67
    #define ApplicationOutput(formatString,...)
    Definition: debugdiagnostics.h:210
    #define ifnoerr(...)
    The opposite of iferr.
    Definition: errorbase.h:393
    void DeleteMem(T *&p)
    Definition: defaultallocator.h:257
    unsigned long Py_ssize_t width
    Definition: pycore_traceback.h:88

    Access

    A MultipassBitmap can be cast into a VPBuffer and vice versa in the rendering pipeline. If a given BaseBitmap pointer refers to a MultipassBitmap can be checked with BaseBitmap::IsMultipassBitmap().

    Allocation/Deallocation

    A MultipassBitmap can be created with the usual tools:

    // This example creates a new MultipassBitmap.
    const Int32 width = 1920;
    const Int32 height = 1080;
    const COLORMODE colorMode = COLORMODE::RGB;
    // allocate MultipassBitmap with the given settings
    MultipassBitmap* multipassBitmap = MultipassBitmap::Alloc(width, height, colorMode);
    if (multipassBitmap == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    // use MultipassBitmap
    // destroy MultipassBitmap
    MultipassBitmap::Free(multipassBitmap);
    @ RGB
    8-bit RGB channels.

    A multi-layer image file can also be loaded into a MultipassBitmap using BaseBitmap::Init():

    // This example lets the user select an image file that will be loaded.
    // If the loaded image contains layers the layout count is printed.
    Filename selectedImageFile;
    // select image file
    if (!selectedImageFile.FileSelect(FILESELECTTYPE::IMAGES, FILESELECT::LOAD, "Select Image"_s))
    return maxon::OK;
    // load image file
    BaseBitmap* bitmap = nullptr;
    const IMAGERESULT result = BaseBitmap::Init(bitmap, selectedImageFile);
    // check success
    return maxon::IoError(MAXON_SOURCE_LOCATION, MaxonConvert(selectedImageFile, MAXONCONVERTMODE::NONE), "Could not load image file."_s);
    // check if it is a MultipassBitmap
    if (bitmap->IsMultipassBitmap())
    {
    MultipassBitmap* const multipassBitmap = static_cast<MultipassBitmap*>(bitmap);
    // get layer count
    const Int32 layerCount = multipassBitmap->GetLayerCount();
    ApplicationOutput("Layer Count: " + String::IntToString(layerCount));
    }
    else
    {
    // no MultipassBitmap, no layers
    ApplicationOutput("No layers");
    }
    maxon::Url MaxonConvert(const Filename &fn, MAXONCONVERTMODE convertMode)
    @ NONE
    No check if file exists under case-sensitive drives.
    Definition: c4d_basebitmap.h:435
    static IMAGERESULT Init(BaseBitmap *&res, const Filename &name, Int32 frame=-1, Bool *ismovie=nullptr, BitmapLoaderPlugin **loaderplugin=nullptr, const maxon::Delegate< void(Float progress)> &progressCallback=nullptr)
    static void Free(BaseBitmap *&bm)
    Bool IsMultipassBitmap() const
    Int32 GetLayerCount() const
    Definition: c4d_basebitmap.h:1019
    static String IntToString(Int32 v)
    Definition: c4d_string.h:495
    PyObject PyObject * result
    Definition: abstract.h:43
    return OK
    Definition: apibase.h:2747
    @ LOAD
    Load dialog.

    The image data stored in the layers can easily be deleted with:

    Properties

    Parameters

    Multiple parameters can be set to define the behaviour of a given layer:

    Note
    Since a MultipassBitmap is used within the rendering pipeline some of these parameters are only relevant in that context.

    The parameter IDs are:

    Some of these parameters can be directly accessed with these convenience functions:

    // This example adds and configures a new MultipassBitmap layer.
    // add a new layer
    MultipassBitmap* const layer = multipassBitmap->AddLayer(nullptr, colorMode);
    if (layer)
    {
    // configure new layer
    layer->SetName("New Layer"_s);
    layer->SetParameter(MPBTYPE::SHOW, true);
    layer->SetParameter(MPBTYPE::SAVE, false);
    }
    // show bitmap in Picture Viewer
    ShowBitmap(multipassBitmap);
    @ LAYER_ADD
    Definition: bplayer.h:40
    Bool ShowBitmap(const Filename &fn)
    void SetName(const maxon::String &name)
    @ BLENDMODE
    Int32 Get/Set. The blend mode (LAYER_NORMAL, LAYER_DISSOLVE etc. from bplayer.h).
    @ SHOW
    Bool Get/Set. Determines if the layer will be shown in the external render window....
    @ SAVE
    Bool Get/Set. Determines if the layer is saved with the image or not if SAVEBIT::USESELECTEDLAYERS is...

    Layers

    A MultipassBitmap can contain default layers, alpha layers and hidden layers:

    These layers are accessed with:

    // This example loops through all layers of
    // the given MultipassBitmap.
    // get layer count
    const Int32 layerCount = multipassBitmap->GetLayerCount();
    // loop through all layers
    for (Int32 layerIndex = 0; layerIndex < layerCount; ++layerIndex)
    {
    MultipassBitmap* const layer = multipassBitmap->GetLayerNum(layerIndex);
    if (layer)
    {
    // access and print layer name
    const String layerName = layer->GetParameter(MPBTYPE::NAME).GetString();
    ApplicationOutput("Layer: " + layerName);
    }
    }
    const String & GetString() const
    Definition: c4d_gedata.h:498
    MultipassBitmap * GetLayerNum(Int32 num)
    Definition: c4d_basebitmap.h:1044
    GeData GetParameter(MPBTYPE id) const
    Definition: c4d_basebitmap.h:1134
    Definition: c4d_string.h:39

    Layers, folders and alpha layers are added with:

    Further layer related functions are:

    // This example adds a new folder with two layers
    // to the given MultipassBitmap.
    // add a new folder
    MultipassBitmap* const folder = multipassBitmap->AddFolder(nullptr);
    if (folder)
    {
    folder->SetName("Folder"_s);
    // add a new layer
    MultipassBitmap* const layerA = folder->AddLayer(nullptr, colorMode);
    if (layerA)
    {
    // configure new layer
    layerA->SetName("Layer A"_s);
    layerA->SetParameter(MPBTYPE::SHOW, true);
    layerA->SetParameter(MPBTYPE::SAVE, true);
    }
    // add a new layer
    MultipassBitmap* const layerB = folder->AddLayer(nullptr, colorMode);
    if (layerB)
    {
    // configure new layer
    layerB->SetName("Layer B"_s);
    layerB->SetParameter(MPBTYPE::SHOW, true);
    layerB->SetParameter(MPBTYPE::SAVE, true);
    }
    }
    MultipassBitmap * AddFolder(MultipassBitmap *insertafter, Bool hidden=false)
    Definition: c4d_basebitmap.h:1075

    Convert

    The content of a MultipassBitmap can also be represented as a BodyPaint PaintBitmap:

    // This example accesses the PaintBitmap representation of the
    // given MultipassBitmap. The functions of the PaintBitmap class
    // are used to merge the layers into one BaseBitmap.
    AutoAlloc<BaseBitmap> mergedBitmap;
    if (mergedBitmap == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    // get PaintBitmap representation
    PaintBitmap* const paintBitmap = multipassBitmap->GetPaintBitmap();
    if (paintBitmap == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    // use PaintBitmap functionality to merge layers
    const Int32 width = multipassBitmap->GetBw();
    const Int32 height = multipassBitmap->GetBh();
    const Int32 calcFlags = RECALC_NOGRID | RECALC_INITBMP;
    // merge layers into one BaseBitmap
    if (!paintBitmap->ReCalc(nullptr, 0, 0, width, height, mergedBitmap, calcFlags, 0))
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    ShowBitmap(mergedBitmap);
    Definition: ge_autoptr.h:37
    Int32 GetBw() const
    Definition: c4d_basebitmap.h:574
    Int32 GetBh() const
    Definition: c4d_basebitmap.h:580
    PaintBitmap * GetPaintBitmap()
    Definition: c4d_basebitmap.h:1166
    The base class of all paint classes. Can be a texture, material, layer or mask.
    Definition: c4d_painter.h:435
    Bool ReCalc(BaseThread *thread, Int32 x1, Int32 y1, Int32 x2, Int32 y2, BaseBitmap *bmp, Int32 flags, UInt32 showbit)
    Definition: c4d_painter.h:574
    #define RECALC_NOGRID
    If set the checkered background grid will not be evaluated.
    Definition: c4d_painter.h:578
    #define RECALC_INITBMP
    Initialize the BaseBitmap of the bmp parameter.
    Definition: c4d_painter.h:579

    Further Reading