diff --git a/include/mitsuba/core/bitmap.h b/include/mitsuba/core/bitmap.h
index a0380fe1..a2516846 100644
--- a/include/mitsuba/core/bitmap.h
+++ b/include/mitsuba/core/bitmap.h
@@ -771,9 +771,58 @@ public:
*/
void applyMatrix(Float matrix[3][3]);
+ /**
+ * \brief Copy the contents of another bitmap into the
+ * region with the specified offset
+ *
+ * Out-of-bounds regions are ignored. It is assumed that
+ * bitmap != this.
+ *
+ * \remark This function throws an exception when the bitmaps
+ * use different component formats or channels, or when the
+ * component format is \ref EBitmask.
+ */
+ void copyFrom(const Bitmap *bitmap, Point2i sourceOffset,
+ Point2i targetOffset, Vector2i size);
+
+ /**
+ * \brief Copy the contents of another bitmap into the
+ * region with the specified offset
+ *
+ * This convenience function calls the main copyFrom()
+ * implementation with size set to bitmap->getSize()
+ * and sourceOffset set to zero. Out-of-bounds regions are
+ * ignored. It is assumed that bitmap != this.
+ *
+ * \remark This function throws an exception when the bitmaps
+ * use different component formats or channels, or when the
+ * component format is \ref EBitmask.
+ */
+ inline void copyFrom(const Bitmap *bitmap, Point2i targetOffset) {
+ copyFrom(bitmap, Point2i(0), targetOffset, bitmap->getSize());
+ }
+
+ /**
+ * \brief Copy the contents of another bitmap into the
+ * region with the specified offset
+ *
+ * This convenience function calls the main copyFrom()
+ * implementation with size set to bitmap->getSize()
+ * and sourceOffset and targetOffsettt> set to zero.
+ * Out-of-bounds regions are ignored. It is assumed
+ * that bitmap != this.
+ *
+ * \remark This function throws an exception when the bitmaps
+ * use different component formats or channels, or when the
+ * component format is \ref EBitmask.
+ */
+ inline void copyFrom(const Bitmap *bitmap) {
+ copyFrom(bitmap, Point2i(0), Point2i(0), bitmap->getSize());
+ }
+
/**
* \brief Accumulate the contents of another bitmap into the
- * region of the specified offset
+ * region with the specified offset
*
* Out-of-bounds regions are ignored. It is assumed that
* bitmap != this.
@@ -784,9 +833,10 @@ public:
*/
void accumulate(const Bitmap *bitmap, Point2i sourceOffset,
Point2i targetOffset, Vector2i size);
+
/**
* \brief Accumulate the contents of another bitmap into the
- * region of the specified offset
+ * region with the specified offset
*
* This convenience function calls the main accumulate()
* implementation with size set to bitmap->getSize()
@@ -803,7 +853,7 @@ public:
/**
* \brief Accumulate the contents of another bitmap into the
- * region of the specified offset
+ * region with the specified offset
*
* This convenience function calls the main accumulate()
* implementation with size set to bitmap->getSize()
diff --git a/src/libcore/bitmap.cpp b/src/libcore/bitmap.cpp
index bb88d531..5b69013b 100644
--- a/src/libcore/bitmap.cpp
+++ b/src/libcore/bitmap.cpp
@@ -514,6 +514,52 @@ ref Bitmap::rotateFlip(ERotateFlipType type) const {
return result;
}
+void Bitmap::copyFrom(const Bitmap *bitmap, Point2i sourceOffset,
+ Point2i targetOffset, Vector2i size) {
+
+ if (m_componentFormat == EBitmask)
+ Log(EError, "Bitmap::copy(): bitmasks are not supported!");
+
+ Assert(getPixelFormat() == bitmap->getPixelFormat() &&
+ getComponentFormat() == bitmap->getComponentFormat() &&
+ getChannelCount() == bitmap->getChannelCount());
+
+ Vector2i offsetIncrease(
+ std::max(0, std::max(-sourceOffset.x, -targetOffset.x)),
+ std::max(0, std::max(-sourceOffset.y, -targetOffset.y))
+ );
+
+ sourceOffset += offsetIncrease;
+ targetOffset += offsetIncrease;
+ size -= offsetIncrease;
+
+ Vector2i sizeDecrease(
+ std::max(0, std::max(sourceOffset.x + size.x - bitmap->getWidth(), targetOffset.x + size.x - getWidth())),
+ std::max(0, std::max(sourceOffset.y + size.y - bitmap->getHeight(), targetOffset.y + size.y - getHeight())));
+
+ size -= sizeDecrease;
+
+ if (size.x <= 0 || size.y <= 0)
+ return;
+
+ const size_t
+ pixelStride = getBytesPerPixel(),
+ sourceStride = bitmap->getWidth() * pixelStride,
+ targetStride = getWidth() * pixelStride;
+
+ const uint8_t *source = bitmap->getUInt8Data() +
+ (sourceOffset.x + sourceOffset.y * (size_t) bitmap->getWidth()) * pixelStride;
+
+ uint8_t *target = m_data +
+ (targetOffset.x + targetOffset.y * (size_t) m_size.x) * pixelStride;
+
+ for (int y = 0; y < size.y; ++y) {
+ memcpy(target, source, size.x * getBytesPerPixel());
+ source += sourceStride;
+ target += targetStride;
+ }
+}
+
void Bitmap::accumulate(const Bitmap *bitmap, Point2i sourceOffset,
Point2i targetOffset, Vector2i size) {
Assert(getPixelFormat() == bitmap->getPixelFormat() &&
diff --git a/src/libcore/platform_darwin.mm b/src/libcore/platform_darwin.mm
index bcda249d..118b2ec8 100644
--- a/src/libcore/platform_darwin.mm
+++ b/src/libcore/platform_darwin.mm
@@ -60,12 +60,17 @@ void __mts_init_cocoa() {
}
void __mts_set_appdefaults() {
+ if ([NSApp respondsToSelector:@selector(invalidateRestorableState)])
+ [NSApp invalidateRestorableState];
+#if 0
+
/* Disable annoying OSX synchronization feature. It's not supported by Qt in any case.. */
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if (![prefs boolForKey: @"ApplePersistenceIgnoreState"]) {
[prefs setBool: YES forKey: @"ApplePersistenceIgnoreState"];
[prefs synchronize];
}
+#endif
}
MTS_NAMESPACE_END
diff --git a/src/libpython/core.cpp b/src/libpython/core.cpp
index 5fbb6321..2459629d 100644
--- a/src/libpython/core.cpp
+++ b/src/libpython/core.cpp
@@ -1235,6 +1235,9 @@ void export_core() {
void (Bitmap::*accumulate_1)(const Bitmap *bitmap, Point2i sourceOffset, Point2i targetOffset, Vector2i size) = &Bitmap::accumulate;
void (Bitmap::*accumulate_2)(const Bitmap *bitmap, Point2i targetOffset) = &Bitmap::accumulate;
void (Bitmap::*accumulate_3)(const Bitmap *bitmap) = &Bitmap::accumulate;
+ void (Bitmap::*copyFrom_1)(const Bitmap *bitmap, Point2i sourceOffset, Point2i targetOffset, Vector2i size) = &Bitmap::copyFrom;
+ void (Bitmap::*copyFrom_2)(const Bitmap *bitmap, Point2i targetOffset) = &Bitmap::copyFrom;
+ void (Bitmap::*copyFrom_3)(const Bitmap *bitmap) = &Bitmap::copyFrom;
const Properties &(Bitmap::*get_metadata)() const = &Bitmap::getMetadata;
void (Bitmap::*resample_1)(const ReconstructionFilter *,
@@ -1283,6 +1286,9 @@ void export_core() {
.def("accumulate", accumulate_1)
.def("accumulate", accumulate_2)
.def("accumulate", accumulate_3)
+ .def("copyFrom", copyFrom_1)
+ .def("copyFrom", copyFrom_2)
+ .def("copyFrom", copyFrom_3)
.def("convolve", &Bitmap::convolve)
.def("arithmeticOperation", &Bitmap::arithmeticOperation, BP_RETURN_VALUE)
.def("resample", resample_1)