#include "operatingsystem.h" #include "c4d_basebitmap.h" #include "c4d_memory.h" #include "c4d_file.h" #include "c4d_general.h" #include "c4d_basecontainer.h" #include "c4d_filterplugin.h" #include "lib_iconcollection.h" #include "c4d_gui.h" #define BmCall(fnc) (this->*C4DOS.Bm->fnc) BaseBitmapLink* BaseBitmapLink::Alloc(void) { return C4DOS.Bm->BBL_Alloc(); } void BaseBitmapLink::Free(BaseBitmapLink*& bll) { C4DOS.Bm->BBL_Free(bll); bll = nullptr; } BaseBitmap* BaseBitmapLink::Get() const { return C4DOS.Bm->BBL_Get((BaseBitmapLink*)this); } void BaseBitmapLink::Set(BaseBitmap* bmp) { C4DOS.Bm->BBL_Set(this, bmp); } BaseBitmap* BaseBitmap::Alloc(void) { return C4DOS.Bm->Alloc(); } void BaseBitmap::Free(BaseBitmap*& bm) { C4DOS.Bm->Free(bm); bm = nullptr; } void MultipassBitmap::Free(MultipassBitmap*& bm) { C4DOS.Bm->Free(bm); bm = nullptr; } COLORMODE BaseBitmap::GetColorMode(void) const { return (COLORMODE)C4DOS.Bm->MPB_GetParameter((const MultipassBitmap*)this, MPBTYPE_COLORMODE).GetInt32(); } BaseBitmap* BaseBitmap::GetClone(void) const { return C4DOS.Bm->GetClone(this); } Bool BaseBitmap::CopyTo(BaseBitmap* dst) const { return C4DOS.Bm->CopyTo(this, dst); } Bool BaseBitmap::CopyPartTo(BaseBitmap* dst, Int32 x, Int32 y, Int32 w, Int32 h) const { return C4DOS.Bm->CopyPartTo(this, dst, x, y, w, h); } BaseBitmap* BaseBitmap::GetClonePart(Int32 x, Int32 y, Int32 w, Int32 h) const { return C4DOS.Bm->GetClonePart(this, x, y, w, h); } void BaseBitmap::FlushAll(void) { C4DOS.Bm->FlushAll(this); } IMAGERESULT BaseBitmap::Init(Int32 x, Int32 y, Int32 depth, INITBITMAPFLAGS flags) { return C4DOS.Bm->Init1(this, x, y, depth, flags); } IMAGERESULT BaseBitmap::Init(const Filename& name, Int32 frame, Bool* ismovie) { return C4DOS.Bm->Init2(this, &name, frame, ismovie); } IMAGERESULT BaseBitmap::Init(BaseBitmap*& res, const Filename& name, Int32 frame, Bool* ismovie, BitmapLoaderPlugin** loaderplugin) { return C4DOS.Bm->Init3(res, name, frame, ismovie, loaderplugin); } IMAGERESULT BaseBitmap::Save(const Filename& name, Int32 format, BaseContainer* data, SAVEBIT savebits) const { return BmCall(Save) (name, format, data, savebits); } Bool MultipassBitmap::SetTempColorProfile(const ColorProfile* profile, Bool dithering) { return BmCall(SetTempColorProfile) (profile, dithering); } Int32 MultipassBitmap::GetUserID(void) const { return BmCall(GetUserID) (); } void MultipassBitmap::SetUserID(Int32 id) { BmCall(SetUserID) (id); } void MultipassBitmap::SetUserSubID(Int32 subid) { BmCall(SetUserSubID) (subid); } void MultipassBitmap::SetSave(Bool save) { BmCall(SetSave) (save); } void MultipassBitmap::SetBlendMode(Int32 mode) { BmCall(SetBlendMode) (mode); } void MultipassBitmap::SetName(const String& name) { BmCall(SetName) (name); } void MultipassBitmap::SetColorMode(COLORMODE mode) { BmCall(SetColorMode) (mode); } void MultipassBitmap::SetComponent(Int32 c) { BmCall(SetComponent) (c); } void MultipassBitmap::SetDpi(Int32 dpi) { BmCall(SetDpi) (dpi); } void BaseBitmap::SetCMAP(Int32 i, Int32 r, Int32 g, Int32 b) { C4DOS.Bm->SetCMAP(this, i, r, g, b); } void BaseBitmap::ScaleBicubic(BaseBitmap* dest, Int32 src_xmin, Int32 src_ymin, Int32 src_xmax, Int32 src_ymax, Int32 dst_xmin, Int32 dst_ymin, Int32 dst_xmax, Int32 dst_ymax) const { C4DOS.Bm->ScaleBicubic(this, dest, src_xmin, src_ymin, src_xmax, src_ymax, dst_xmin, dst_ymin, dst_xmax, dst_ymax); } void BaseBitmap::ScaleIt(BaseBitmap* dst, Int32 intens, Bool sample, Bool nprop) const { C4DOS.Bm->ScaleIt(this, dst, intens, sample, nprop); } void BaseBitmap::Clear(Int32 r, Int32 g, Int32 b) { C4DOS.Bm->Clear(this, 0, 0, GetBw() - 1, GetBh() - 1, r, g, b); } void BaseBitmap::Clear(Int32 x1, Int32 y1, Int32 x2, Int32 y2, Int32 r, Int32 g, Int32 b) { C4DOS.Bm->Clear(this, x1, y1, x2, y2, r, g, b); } BaseBitmap* BaseBitmap::AddChannel(Bool internal, Bool straight) { return C4DOS.Bm->AddChannel(this, internal, straight); } void BaseBitmap::RemoveChannel(BaseBitmap* channel) { C4DOS.Bm->RemoveChannel(this, channel); } const BaseBitmap* BaseBitmap::GetInternalChannel(void) const { return C4DOS.Bm->GetInternalChannel(((BaseBitmap*)this)); } BaseBitmap* BaseBitmap::GetInternalChannel(void) { return C4DOS.Bm->GetInternalChannel(this); } Int32 BaseBitmap::GetChannelCount(void) const { return C4DOS.Bm->GetChannelCount(this); } BaseBitmap* BaseBitmap::GetChannelNum(Int32 num) { return C4DOS.Bm->GetChannelNum(this, num); } const BaseBitmap* BaseBitmap::GetChannelNum(Int32 num) const { return C4DOS.Bm->GetChannelNum(((BaseBitmap*)this), num); } Bool BaseBitmap::SetData(Int32 id, const GeData& data) { return C4DOS.Bm->SetBaseBitmapData(this, id, data); } GeData BaseBitmap::GetData(Int32 id, const GeData& t_default) const { return C4DOS.Bm->GetBaseBitmapData(this, id, t_default); } Bool BaseBitmap::IsMultipassBitmap(void) const { return C4DOS.Bm->IsMultipassBitmap(this); } MovieLoader* MovieLoader::Alloc(void) { return NewObjClear(MovieLoader); } void MovieLoader::Free(MovieLoader*& ml) { DeleteObj(ml); } MovieLoader::MovieLoader(void) { InitData(); } MovieLoader::~MovieLoader(void) { FreeData(); } void MovieLoader::InitData(void) { plugin = nullptr; bm = nullptr; is_movie = false; frame_cnt = 0; fps = 0.0; frame_idx = -2; result = IMAGERESULT_OK; } void MovieLoader::FreeData(void) { if (plugin) { plugin->BmLoadAnimated(&plugin_data, BITMAPLOADERACTION_FREE, nullptr, 0); plugin = nullptr; } if (bm) BaseBitmap::Free(bm); } IMAGERESULT MovieLoader::Open(const Filename& fn) { #ifdef _DEBUG if (plugin) CriticalStop(); // call Close() before reusing a MovieLoader if (bm) CriticalStop(); FreeData(); // release a previously used bitmap/plugin InitData(); // back to start #endif result = BaseBitmap::Init(bm, fn, frame_idx, &is_movie, &plugin); if ((result != IMAGERESULT_OK) || (plugin == nullptr)) { if ((plugin == nullptr) && (result == IMAGERESULT_OK)) // this shouldn't happen result = IMAGERESULT_WRONGTYPE; plugin = nullptr; BaseBitmap::Free(bm); return result; } if (is_movie) { if (GeGetMovieInfo(fn, &frame_cnt, &fps) == false) { frame_cnt = 0; fps = 0.0; CriticalStop(); // don't return an error here - examine the problem } plugin_data.moviename = fn; result = plugin->BmLoadAnimated(&plugin_data, BITMAPLOADERACTION_INIT, nullptr, 0); if (result != IMAGERESULT_OK) { FreeData(); return result; } frame_idx = -2; // nothing loaded yet } return result; } void MovieLoader::Close(void) { FreeData(); InitData(); // back to start } //---------------------------------------------------------------------------------------- // Read a frame and return the bitmap pointer // Function result: BaseBitmap (MovieLoader is the owner) or nullptr (check _result) // new_frame_idx: frame index // _result: used to return the result code (IMAGERESULT_OK or error code), can be nullptr //---------------------------------------------------------------------------------------- BaseBitmap* MovieLoader::Read(Int32 new_frame_idx, Int32* _result) { if (is_movie == false) return bm; // always return the image initally loaded at the init call if (new_frame_idx == frame_idx) // frame already loaded? return bm; result = plugin->BmLoadAnimated(&plugin_data, BITMAPLOADERACTION_LOAD, bm, new_frame_idx); // read the requested frame if (result == IMAGERESULT_OK) { frame_idx = new_frame_idx; if (_result) *_result = IMAGERESULT_OK; return bm; } frame_idx = -2; // loading a new frame failed, content of bm is unknown if (_result) *_result = result; return nullptr; } //---------------------------------------------------------------------------------------- // Get movie/bitmap info // Function result: number of frames (0: Open failed) // _fps: used to return frame rate //---------------------------------------------------------------------------------------- Int32 MovieLoader::GetInfo(Float* _fps) { if (_fps) *_fps = fps; if (is_movie) return frame_cnt; if (result == IMAGERESULT_OK) return 1; return 0; // Open failed } MovieSaver* MovieSaver::Alloc(void) { return C4DOS.Ms->Alloc(); } void MovieSaver::Free(MovieSaver*& ms) { C4DOS.Ms->Free(ms); ms = nullptr; } IMAGERESULT MovieSaver::Open(const Filename& name, BaseBitmap* bm, Int32 fps, Int32 id, BaseContainer* data, SAVEBIT savebits, BaseSound* sound) { return C4DOS.Ms->Open(this, &name, bm, fps, id, data, savebits, sound); } IMAGERESULT MovieSaver::Write(BaseBitmap* bm) { return C4DOS.Ms->Write(this, bm); } void MovieSaver::Close(void) { C4DOS.Ms->Close(this); } Bool MovieSaver::Choose(Int32 id, BaseContainer* bc) { return C4DOS.Ms->Choose(this, id, bc); } #define CallBmLoader(fnc) (((BitmapLoaderData*)(((BITMAPLOADERPLUGIN*)GetPluginStructure())->adr))->*((BITMAPLOADERPLUGIN*)GetPluginStructure())->fnc) #define CallBmSaver(fnc) (((BitmapSaverData*)(((BITMAPSAVERPLUGIN*)GetPluginStructure())->adr))->*((BITMAPSAVERPLUGIN*)GetPluginStructure())->fnc) Bool BitmapLoaderPlugin::BmIdentify(const Filename& name, UChar* probe, Int32 size) { return CallBmLoader(Identify) (name, probe, size); } IMAGERESULT BitmapLoaderPlugin::BmLoad(const Filename& name, BaseBitmap* bm, Int32 frame) { return CallBmLoader(Load) (name, bm, frame); } Int32 BitmapLoaderPlugin::BmGetSaver(void) { if (!((BITMAPLOADERPLUGIN*)GetPluginStructure())->GetSaver) return 0; return CallBmLoader(GetSaver) (); } Bool BitmapLoaderPlugin::BmGetInformation(const Filename& name, Int32* frames, Float* fps) { if (!((BITMAPLOADERPLUGIN*)GetPluginStructure())->GetInformation) return false; return CallBmLoader(GetInformation) (name, frames, fps); } IMAGERESULT BitmapLoaderPlugin::BmLoadAnimated(BitmapLoaderAnimatedData* bd, BITMAPLOADERACTION action, BaseBitmap* bm, Int32 frame) { if (!((BITMAPLOADERPLUGIN*)GetPluginStructure())->LoadAnimated) return IMAGERESULT_NOTEXISTING; return CallBmLoader(LoadAnimated) (bd, action, bm, frame); } IMAGERESULT BitmapLoaderPlugin::BmExtractSound(BitmapLoaderAnimatedData* bd, BaseSound* snd) { if (!((BITMAPLOADERPLUGIN*)GetPluginStructure())->ExtractSound) return IMAGERESULT_NOTEXISTING; return CallBmLoader(ExtractSound) (bd, snd); } IMAGERESULT BitmapLoaderPlugin::BmHasSound(BitmapLoaderAnimatedData* bd) { if (!((BITMAPLOADERPLUGIN*)GetPluginStructure())->HasSound) return IMAGERESULT_NOTEXISTING; return CallBmLoader(HasSound) (bd); } void BitmapSaverPlugin::BmGetDetails(Int32* alpha, String* suffix) { if (alpha) { BaseContainer bc; *alpha = CallBmSaver(GetMaxAlphas) (&bc); } if (suffix) { *suffix = String(); String* str = ((BITMAPSAVERPLUGIN*)GetPluginStructure())->suffix; if (str) *suffix = *str; } } Int32 BitmapSaverPlugin::BmGetMaxResolution(Bool layers) { if (!((BITMAPSAVERPLUGIN*)GetPluginStructure())->GetMaxResolution) return 32000; return CallBmSaver(GetMaxResolution) (layers); } Bool BitmapSaverPlugin::BmEdit(BaseContainer* data) { return CallBmSaver(Edit) (data); } IMAGERESULT BitmapSaverPlugin::BmSave(const Filename& name, BaseBitmap* bm, BaseContainer* data, SAVEBIT savebits) { Int32 maxres = BmGetMaxResolution((savebits & SAVEBIT_MULTILAYER) != SAVEBIT_0); if (bm->GetBw() > maxres || bm->GetBh() > maxres) return IMAGERESULT_PARAM_ERROR; return CallBmSaver(Save) (name, bm, data, savebits); } IMAGERESULT BitmapSaverPlugin::BmOpen(PluginMovieData*& md, const Filename& name, BaseBitmap* bm, BaseContainer* data, SAVEBIT savebits, Int32 fps) { if (!((BITMAPSAVERPLUGIN*)GetPluginStructure())->Open) return IMAGERESULT_OUTOFMEMORY; return CallBmSaver(Open) (md, name, bm, data, savebits, fps); } IMAGERESULT BitmapSaverPlugin::BmWrite(PluginMovieData* md, BaseBitmap* bm) { if (!((BITMAPSAVERPLUGIN*)GetPluginStructure())->Write) return IMAGERESULT_OUTOFMEMORY; return CallBmSaver(Write) (md, bm); } void BitmapSaverPlugin::BmClose(PluginMovieData*& md) { if (!((BITMAPSAVERPLUGIN*)GetPluginStructure())->Close) return; CallBmSaver(Close) (md); } IconData InitResourceIcon(Int32 resource_id) { IconData dat; if (!GetIcon(resource_id, &dat) || !dat.bmp) return IconData(); return dat; } BaseBitmap* InitResourceBitmap(Int32 resource_id) { IconData dat; if (!GetIcon(resource_id, &dat) || !dat.bmp) return nullptr; return dat.GetClonePart(); } Bool MultipassBitmap::GetLayers(maxon::BaseArray& list, MPB_GETLAYERS flags) { list.Flush(); if (!IsMultipassBitmap()) { // must never happen. if this is the case the pointer is not a multipassbmp the call must be catched outside! CriticalStop(); return false; } Int32 count; BaseBitmap** arr = nullptr; if (!C4DOS.Bm->MPB_GetLayers(this, flags, arr, count)) return false; Int32 i; for (i = 0; i < count; i++) { if (!arr[i]) continue; list.Append(arr[i]); } DeleteMem(arr); return true; } Bool MultipassBitmap::GetLayers(maxon::BaseArray& list, MPB_GETLAYERS flags) { list.Flush(); if (!IsMultipassBitmap()) { // must never happen. if this is the case the pointer is not a multipassbmp the call must be catched outside! CriticalStop(); return false; } Int32 count; BaseBitmap** arr = nullptr; if (!C4DOS.Bm->MPB_GetLayers(this, flags, arr, count)) return false; if (!arr) return false; Int32 i; for (i = 0; i < count; i++) { if (!arr[i] || !arr[i]->IsMultipassBitmap()) continue; list.Append((MultipassBitmap*)arr[i]); } DeleteMem(arr); return true; } // ColorProfile Stuff starts here ColorProfile* ColorProfile::Alloc(void) { return C4DOS.Bm->ProfileAlloc(); } void ColorProfile::Free(ColorProfile*& profile) { C4DOS.Bm->ProfileFree(profile); profile = nullptr; } ColorProfile& ColorProfile::operator = (const ColorProfile& src) { C4DOS.Bm->ProfileCopy(&src, this); return *this; } Bool ColorProfile::operator == (const ColorProfile& src) const { return C4DOS.Bm->ProfileEqual(&src, this); } Bool ColorProfile::operator != (const ColorProfile& src) const { return !C4DOS.Bm->ProfileEqual(&src, this); } const ColorProfile* ColorProfile::GetDefaultSRGB() { return C4DOS.Bm->ProfileSRGB(); } const ColorProfile* ColorProfile::GetDefaultLinearRGB() { return C4DOS.Bm->ProfileLinearRGB(); } const ColorProfile* ColorProfile::GetDefaultSGray() { return C4DOS.Bm->ProfileSGray(); } const ColorProfile* ColorProfile::GetDefaultLinearGray() { return C4DOS.Bm->ProfileLinearGray(); } Bool ColorProfile::CreateDefaultWindow(GeDialog* dlg) { return C4DOS.Bm->ProfileWindow(this, dlg ? dlg->Get() : nullptr); } Bool ColorProfile::OpenProfileFromFile(const Filename& fn) { return C4DOS.Bm->ProfileFromFile(this, fn); } Bool ColorProfile::OpenProfileFromMemory(const void* mem, Int64 memsize) { return C4DOS.Bm->ProfileFromMemory(this, mem, memsize); } Bool ColorProfile::WriteProfileToMemory(void*& mem, Int64& memsize) const { return C4DOS.Bm->ProfileToMemory(this, mem, memsize); } Bool ColorProfile::WriteProfileToFile(const Filename& fn) const { return C4DOS.Bm->ProfileToFile(this, fn); } String ColorProfile::GetInfo(COLORPROFILEINFO info) const { return C4DOS.Bm->ProfileInfo(this, info); } Bool ColorProfile::HasProfile() const { return C4DOS.Bm->ProfileHasProfile(this); } Bool ColorProfile::CheckColorMode(COLORMODE colormode) const { return C4DOS.Bm->ProfileCheckColorMode(this, colormode); } Bool ColorProfile::IsMonitorProfileMode() const { return C4DOS.Bm->ProfileIsMonitorMode(this); } Bool ColorProfile::SetMonitorProfileMode(Bool on) { return C4DOS.Bm->ProfileSetMonitorMode(this, on); } ColorProfileConvert* ColorProfileConvert::Alloc(void) { return C4DOS.Bm->ProfileConvAlloc(); } void ColorProfileConvert::Free(ColorProfileConvert*& convert) { C4DOS.Bm->ProfileConvFree(convert); convert = nullptr; } Bool ColorProfileConvert::PrepareTransform(COLORMODE srccolormode, const ColorProfile* srcprofile, COLORMODE dstcolormode, const ColorProfile* dstprofile, Bool bgr) { return C4DOS.Bm->ProfileConvTransform(this, srccolormode, srcprofile, dstcolormode, dstprofile, bgr); } void ColorProfileConvert::Convert(const PIX* src, PIX* dst, Int32 cnt, Int32 SkipInputComponents, Int32 SkipOutputComponents) const { return C4DOS.Bm->ProfileConvConvert(this, src, dst, cnt, SkipInputComponents, SkipOutputComponents); } #ifndef __API_INTERN__ AutoBitmap::AutoBitmap(const String& str, Float pixelRatio) { bmp = BaseBitmap::Alloc(); if (!bmp) return; if (bmp->Init(GeGetPluginPath() + String("res") + str) != IMAGERESULT_OK) { BaseBitmap::Free(bmp); return; } bmp->SetData(BASEBITMAP_DATA_GUIPIXELRATIO, pixelRatio); } AutoBitmap::AutoBitmap(Int32 id) { bmp = InitResourceBitmap(id); } AutoBitmap::~AutoBitmap() { BaseBitmap::Free(bmp); } #endif