35 #pragma clang diagnostic push
36 #pragma clang diagnostic ignored "-Wunused-variable"
37 #pragma clang diagnostic pop
38 #include "boost/format.hpp"
39 #include "boost/filesystem/path.hpp"
41 #include "boost/functional/hash.hpp"
61 template <
typename MaskPixelT>
62 void Mask<MaskPixelT>::_initializePlanes(
MaskPlaneDict const& planeDefs) {
63 LOGL_DEBUG(
"afw.image.Mask",
"Number of mask planes: %d", getNumPlanesMax());
68 template <
typename MaskPixelT>
71 _initializePlanes(planeDefs);
75 template <
typename MaskPixelT>
79 _initializePlanes(planeDefs);
83 template <
typename MaskPixelT>
86 _initializePlanes(planeDefs);
90 template <
typename MaskPixelT>
94 _initializePlanes(planeDefs);
98 template <
typename MaskPixelT>
101 _initializePlanes(planeDefs);
105 template <
typename MaskPixelT>
108 _initializePlanes(planeDefs);
109 *
this = initialValue;
112 template <
typename MaskPixelT>
115 :
ImageBase<MaskPixelT>(rhs,
bbox, origin, deep), _maskDict(rhs._maskDict) {}
117 template <
typename MaskPixelT>
119 :
ImageBase<MaskPixelT>(rhs, deep), _maskDict(rhs._maskDict) {}
121 template <
typename MaskPixelT>
124 template <
typename MaskPixelT>
127 template <
typename MaskPixelT>
130 :
image::
ImageBase<MaskPixelT>(array, deep, xy0), _maskDict(detail::MaskDict::getDefault()) {}
132 template <
typename PixelT>
137 swap(_maskDict, rhs._maskDict);
140 template <
typename PixelT>
145 template <
typename MaskPixelT>
153 template <
typename MaskPixelT>
158 template <
typename MaskPixelT>
160 fill_pixels(_getRawView(), rhs);
165 #ifndef DOXYGEN // doc for this section is already in header
167 template <
typename MaskPixelT>
170 :
ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::getDefault()) {
172 *
this = reader.read<MaskPixelT>(
bbox, origin, conformMasks, allowUnsafe);
174 metadata->combine(reader.readMetadata());
178 template <
typename MaskPixelT>
181 ImageOrigin origin,
bool conformMasks,
bool allowUnsafe)
182 : ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::getDefault()) {
184 *
this = reader.read<MaskPixelT>(
bbox, origin, conformMasks, allowUnsafe);
186 metadata->combine(reader.readMetadata());
190 template <
typename MaskPixelT>
194 : ImageBase<MaskPixelT>(), _maskDict(detail::MaskDict::getDefault()) {
196 *
this = reader.read<MaskPixelT>(
bbox, origin, conformMasks, allowUnsafe);
198 metadata->combine(reader.readMetadata());
202 template <
typename MaskPixelT>
207 writeFits(fitsfile, metadata_i);
210 template <
typename MaskPixelT>
215 writeFits(fitsfile, metadata_i);
218 template <
typename MaskPixelT>
221 writeFits(fitsfile, fits::ImageWriteOptions(*
this), metadata);
224 template <
typename MaskPixelT>
229 writeFits(fitsfile, options, header);
232 template <
typename MaskPixelT>
237 writeFits(fitsfile, options, header);
240 template <
typename MaskPixelT>
244 header ? header->deepCopy() : std::make_shared<dafBase::PropertySet>();
245 addMaskPlanesToMetadata(useHeader);
251 template <
typename MaskPixelT>
256 if (value & getBitMask(
iter->second)) {
266 template <
typename MaskPixelT>
268 int id = getMaskPlaneNoThrow(
name);
271 id = _maskPlaneDict()->getUnusedPlane();
276 if (
id >= getNumPlanesMax()) {
278 str(
boost::format(
"Max number of planes (%1%) already used") % getNumPlanesMax()));
286 template <
typename MaskPixelT>
288 if (planeId < 0 || planeId >= getNumPlanesMax()) {
291 str(
boost::format(
"mask plane ID must be between 0 and %1%") % (getNumPlanesMax() - 1)));
294 _maskPlaneDict()->add(
name, planeId);
299 template <
typename MaskPixelT>
301 return _maskDict->getMaskPlaneDict();
304 template <
typename MaskPixelT>
312 _maskPlaneDict()->erase(
name);
315 template <
typename MaskPixelT>
319 clearMaskPlane(getMaskPlane(
name));
324 _maskDict = _maskDict->clone();
327 _maskDict->erase(
name);
330 removeMaskPlane(
name);
334 template <
typename MaskPixelT>
336 return (planeId >= 0 && planeId < getNumPlanesMax()) ? (1 << planeId) : 0;
339 template <
typename MaskPixelT>
341 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
343 for (MaskPlaneDict::const_iterator i = mpd.begin(); i != mpd.end(); ++i) {
344 if (planeId == i->second) {
345 MaskPixelT
const bitmask = getBitMaskNoThrow(planeId);
356 template <
typename MaskPixelT>
358 int const plane = getMaskPlaneNoThrow(
name);
368 template <
typename MaskPixelT>
373 template <
typename MaskPixelT>
375 return getBitMask(getMaskPlane(
name));
378 template <
typename MaskPixelT>
380 MaskPixelT mpix = 0x0;
382 mpix |= getBitMask(getMaskPlane(*it));
387 template <
typename MaskPixelT>
389 return _maskPlaneDict()->size();
392 template <
typename MaskPixelT>
394 _maskPlaneDict()->clear();
397 template <
typename MaskPixelT>
402 template <
typename MaskPixelT>
404 *
this &= ~getBitMask(planeId);
407 template <
typename MaskPixelT>
411 if (*_maskDict == *currentMD) {
419 MaskPixelT keepBitmask = 0;
420 MaskPixelT canonicalMask[
sizeof(MaskPixelT) * 8];
421 MaskPixelT currentMask[
sizeof(MaskPixelT) * 8];
424 for (MaskPlaneDict::const_iterator i = currentPlaneDict.
begin(); i != currentPlaneDict.
end(); i++) {
426 int const currentPlaneNumber = i->second;
427 int canonicalPlaneNumber = getMaskPlaneNoThrow(
name);
429 if (canonicalPlaneNumber < 0) {
430 canonicalPlaneNumber = addMaskPlane(
name);
433 if (canonicalPlaneNumber == currentPlaneNumber) {
434 keepBitmask |= getBitMask(canonicalPlaneNumber);
436 canonicalMask[numReMap] = getBitMask(canonicalPlaneNumber);
437 currentMask[numReMap] = getBitMaskNoThrow(currentPlaneNumber);
444 for (
int r = 0; r != this->getHeight(); ++r) {
449 MaskPixelT newPixel =
pixel & keepBitmask;
450 for (
int i = 0; i < numReMap; i++) {
451 if (
pixel & currentMask[i]) newPixel |= canonicalMask[i];
463 template <
typename MaskPixelT>
468 template <
typename MaskPixelT>
474 template <
typename MaskPixelT>
479 template <
typename MaskPixelT>
485 template <
typename MaskPixelT>
491 template <
typename MaskPixelT>
497 template <
typename MaskPixelT>
499 if (*_maskDict != *
other._maskDict) {
504 template <
typename MaskPixelT>
506 transform_pixels(_getRawView(), _getRawView(),
507 [&
val](MaskPixelT
const& l) -> MaskPixelT {
return l |
val; });
511 template <
typename MaskPixelT>
513 checkMaskDictionaries(rhs);
517 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
520 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
521 [](MaskPixelT
const& l, MaskPixelT
const& r) -> MaskPixelT {
return l | r; });
525 template <
typename MaskPixelT>
527 transform_pixels(_getRawView(), _getRawView(), [&
val](MaskPixelT
const& l) {
return l &
val; });
531 template <
typename MaskPixelT>
533 checkMaskDictionaries(rhs);
537 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
540 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
541 [](MaskPixelT
const& l, MaskPixelT
const& r) -> MaskPixelT {
return l & r; });
545 template <
typename MaskPixelT>
547 transform_pixels(_getRawView(), _getRawView(),
548 [&
val](MaskPixelT
const& l) -> MaskPixelT {
return l ^
val; });
552 template <
typename MaskPixelT>
554 checkMaskDictionaries(rhs);
558 str(
boost::format(
"Images are of different size, %dx%d v %dx%d") %
561 transform_pixels(_getRawView(), rhs.
_getRawView(), _getRawView(),
562 [](MaskPixelT
const& l, MaskPixelT
const& r) -> MaskPixelT {
return l ^ r; });
566 template <
typename MaskPixelT>
568 MaskPixelT
const bitMask = getBitMask(planeId);
570 for (
int x = x0;
x <= x1;
x++) {
571 operator()(
x,
y) = operator()(
x,
y) | bitMask;
575 template <
typename MaskPixelT>
583 NameList paramNames = metadata->
paramNames(
false);
584 for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) {
585 if (i->compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) {
590 MaskPlaneDict const& mpd = _maskPlaneDict()->getMaskPlaneDict();
593 for (MaskPlaneDict::const_iterator i = mpd.
begin(); i != mpd.
end(); ++i) {
595 int const planeNumber = i->second;
597 if (planeName !=
"") {
598 metadata->
add(maskPlanePrefix + planeName, planeNumber);
603 template <
typename MaskPixelT>
610 NameList paramNames = metadata->
paramNames(
false);
611 int numPlanesUsed = 0;
614 for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) {
615 if (i->compare(0, maskPlanePrefix.size(), maskPlanePrefix) == 0) {
618 int const planeId = metadata->
getAsInt(*i);
620 MaskPlaneDict::const_iterator plane = newDict.
find(planeName);
621 if (plane != newDict.
end() && planeId != plane->second) {
624 for (MaskPlaneDict::const_iterator j = newDict.
begin(); j != newDict.
end(); ++j) {
625 if (planeId == j->second) {
627 str(
boost::format(
"File specifies plane %s has same value (%d) as %s") %
628 planeName % planeId % j->first));
632 if (numPlanesUsed >= getNumPlanesMax()) {
636 str(
boost::format(
"Max number of planes (%1%) already used") % getNumPlanesMax()));
638 newDict[planeName] = planeId;
644 template <
typename MaskPixelT>
652 template <
typename MaskPixelT>
655 template <
typename MaskPixelT>
663 template class Mask<MaskPixel>;