/*
*
- * Copyright (C) 1998-2016, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#define DIYBRPXT_H
#include "dcmtk/config/osconfig.h"
+#include "dcmtk/ofstd/ofbmanip.h"
#include "dcmtk/dcmimage/dicopxt.h"
#include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */
// use the number of input pixels derived from the length of the 'PixelData'
// attribute), but not more than the size of the intermediate buffer
const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count;
- if (rgb) /* convert to RGB model */
+ // make sure that there is sufficient input data (for planar pixel data)
+ if (!this->PlanarConfiguration || (count >= planeSize * 3 /* number of planes */))
{
- T2 *r = this->Data[0];
- T2 *g = this->Data[1];
- T2 *b = this->Data[2];
- const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits));
- DiPixelRepresentationTemplate<T1> rep;
- if (bits == 8 && !rep.isSigned()) // only for unsigned 8 bit
+ if (rgb) /* convert to RGB model */
{
- Sint16 rcr_tab[256];
- Sint16 gcb_tab[256];
- Sint16 gcr_tab[256];
- Sint16 bcb_tab[256];
- const double r_const = 0.7010 * OFstatic_cast(double, maxvalue);
- const double g_const = 0.5291 * OFstatic_cast(double, maxvalue);
- const double b_const = 0.8859 * OFstatic_cast(double, maxvalue);
- unsigned long l;
- for (l = 0; l < 256; ++l)
+ T2 *r = this->Data[0];
+ T2 *g = this->Data[1];
+ T2 *b = this->Data[2];
+ const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits));
+ DiPixelRepresentationTemplate<T1> rep;
+ if (bits == 8 && !rep.isSigned()) // only for unsigned 8 bit
{
- rcr_tab[l] = OFstatic_cast(Sint16, 1.4020 * OFstatic_cast(double, l) - r_const);
- gcb_tab[l] = OFstatic_cast(Sint16, 0.3441 * OFstatic_cast(double, l));
- gcr_tab[l] = OFstatic_cast(Sint16, 0.7141 * OFstatic_cast(double, l) - g_const);
- bcb_tab[l] = OFstatic_cast(Sint16, 1.7720 * OFstatic_cast(double, l) - b_const);
- }
- Sint32 sr;
- Sint32 sg;
- Sint32 sb;
- if (this->PlanarConfiguration)
- {
-/*
- const T1 *y = pixel;
- const T1 *cb = y + this->InputCount;
- const T1 *cr = cb + this->InputCount;
- for (i = count; i != 0; --i, ++y, ++cb, ++cr)
+ Sint16 rcr_tab[256];
+ Sint16 gcb_tab[256];
+ Sint16 gcr_tab[256];
+ Sint16 bcb_tab[256];
+ const double r_const = 0.7010 * OFstatic_cast(double, maxvalue);
+ const double g_const = 0.5291 * OFstatic_cast(double, maxvalue);
+ const double b_const = 0.8859 * OFstatic_cast(double, maxvalue);
+ unsigned long l;
+ for (l = 0; l < 256; ++l)
{
- sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[*cr]);
- sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[*cb]) - OFstatic_cast(Sint32, gcr_tab[*cr]);
- sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[*cb]);
- *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
- *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
- *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
+ rcr_tab[l] = OFstatic_cast(Sint16, 1.4020 * OFstatic_cast(double, l) - r_const);
+ gcb_tab[l] = OFstatic_cast(Sint16, 0.3441 * OFstatic_cast(double, l));
+ gcr_tab[l] = OFstatic_cast(Sint16, 0.7141 * OFstatic_cast(double, l) - g_const);
+ bcb_tab[l] = OFstatic_cast(Sint16, 1.7720 * OFstatic_cast(double, l) - b_const);
}
+ Sint32 sr;
+ Sint32 sg;
+ Sint32 sb;
+ if (this->PlanarConfiguration)
+ {
+/*
+ const T1 *y = pixel;
+ const T1 *cb = y + this->InputCount;
+ const T1 *cr = cb + this->InputCount;
+ for (i = count; i != 0; --i, ++y, ++cb, ++cr)
+ {
+ sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[*cr]);
+ sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[*cb]) - OFstatic_cast(Sint32, gcr_tab[*cr]);
+ sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[*cb]);
+ *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
+ *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
+ *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
+ }
*/
- const T1 *y = pixel;
- const T1 *cb = y + planeSize;
- const T1 *cr = cb + planeSize;
- unsigned long i = count;
- while (i != 0)
+ const T1 *y = pixel;
+ const T1 *cb = y + planeSize;
+ const T1 *cr = cb + planeSize;
+ unsigned long i = count;
+ while (i != 0)
+ {
+ /* convert a single frame */
+ for (l = planeSize; (l != 0) && (i != 0); --l, --i, ++y, ++cb, ++cr)
+ {
+ sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[*cr]);
+ sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[*cb]) - OFstatic_cast(Sint32, gcr_tab[*cr]);
+ sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[*cb]);
+ *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
+ *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
+ *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
+ }
+ /* jump to next frame start (skip 2 planes) */
+ y += 2 * planeSize;
+ cb += 2 * planeSize;
+ cr += 2 * planeSize;
+ }
+ }
+ else
{
- /* convert a single frame */
- for (l = planeSize; (l != 0) && (i != 0); --l, --i, ++y, ++cb, ++cr)
+ const T1 *p = pixel;
+ T1 y;
+ T1 cb;
+ T1 cr;
+ unsigned long i;
+ for (i = count; i != 0; --i)
{
- sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[OFstatic_cast(Uint32, *cr)]);
- sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[OFstatic_cast(Uint32, *cb)]) - OFstatic_cast(Sint32, gcr_tab[OFstatic_cast(Uint32, *cr)]);
- sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[OFstatic_cast(Uint32, *cb)]);
+ y = *(p++);
+ cb = *(p++);
+ cr = *(p++);
+ sr = OFstatic_cast(Sint32, y) + OFstatic_cast(Sint32, rcr_tab[cr]);
+ sg = OFstatic_cast(Sint32, y) - OFstatic_cast(Sint32, gcb_tab[cb]) - OFstatic_cast(Sint32, gcr_tab[cr]);
+ sb = OFstatic_cast(Sint32, y) + OFstatic_cast(Sint32, bcb_tab[cb]);
*(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
*(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
*(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
}
- /* jump to next frame start (skip 2 planes) */
- y += 2 * planeSize;
- cb += 2 * planeSize;
- cr += 2 * planeSize;
}
}
else
{
- const T1 *p = pixel;
- T1 y;
- T1 cb;
- T1 cr;
- unsigned long i;
- for (i = count; i != 0; --i)
+ if (this->PlanarConfiguration)
+ {
+/*
+ const T1 *y = pixel;
+ const T1 *cb = y + this->InputCount;
+ const T1 *cr = cb + this->InputCount;
+ for (i = count; i != 0; --i)
+ convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset),
+ removeSign(*(cr++), offset), maxvalue);
+*/
+ unsigned long l;
+ unsigned long i = count;
+ const T1 *y = pixel;
+ const T1 *cb = y + planeSize;
+ const T1 *cr = cb + planeSize;
+ while (i != 0)
+ {
+ /* convert a single frame */
+ for (l = planeSize; (l != 0) && (i != 0); --l, --i)
+ {
+ convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset),
+ removeSign(*(cr++), offset), maxvalue);
+ }
+ /* jump to next frame start (skip 2 planes) */
+ y += 2 * planeSize;
+ cb += 2 * planeSize;
+ cr += 2 * planeSize;
+ }
+ }
+ else
{
- y = *(p++);
- cb = *(p++);
- cr = *(p++);
- sr = OFstatic_cast(Sint32, y) + OFstatic_cast(Sint32, rcr_tab[OFstatic_cast(Uint32, cr)]);
- sg = OFstatic_cast(Sint32, y) - OFstatic_cast(Sint32, gcb_tab[OFstatic_cast(Uint32, cb)]) - OFstatic_cast(Sint32, gcr_tab[OFstatic_cast(Uint32, cr)]);
- sb = OFstatic_cast(Sint32, y) + OFstatic_cast(Sint32, bcb_tab[OFstatic_cast(Uint32, cb)]);
- *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
- *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
- *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
+ const T1 *p = pixel;
+ T2 y;
+ T2 cb;
+ T2 cr;
+ unsigned long i;
+ for (i = count; i != 0; --i)
+ {
+ y = removeSign(*(p++), offset);
+ cb = removeSign(*(p++), offset);
+ cr = removeSign(*(p++), offset);
+ convertValue(*(r++), *(g++), *(b++), y, cb, cr, maxvalue);
+ }
}
}
- }
- else
- {
+ } else { /* retain YCbCr model */
+ const T1 *p = pixel;
if (this->PlanarConfiguration)
{
-/*
- const T1 *y = pixel;
- const T1 *cb = y + this->InputCount;
- const T1 *cr = cb + this->InputCount;
- for (i = count; i != 0; --i)
- convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset),
- removeSign(*(cr++), offset), maxvalue);
-*/
+ /*
+ T2 *q;
+ // number of pixels to be skipped (only applicable if 'PixelData' contains more
+ // pixels than expected)
+ const unsigned long skip = (this->InputCount > this->Count) ? (this->InputCount - this->Count) : 0;
+ for (int j = 0; j < 3; ++j)
+ {
+ q = this->Data[j];
+ for (i = count; i != 0; --i)
+ *(q++) = removeSign(*(p++), offset);
+ // skip to beginning of next plane
+ p += skip;
+ }
+ */
unsigned long l;
- unsigned long i = count;
- const T1 *y = pixel;
- const T1 *cb = y + planeSize;
- const T1 *cr = cb + planeSize;
- while (i != 0)
+ unsigned long i = 0;
+ while (i < count)
{
- /* convert a single frame */
- for (l = planeSize; (l != 0) && (i != 0); --l, --i)
+ /* store current pixel index */
+ const unsigned long iStart = i;
+ for (int j = 0; j < 3; ++j)
{
- convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset),
- removeSign(*(cr++), offset), maxvalue);
+ /* convert a single plane */
+ for (l = planeSize, i = iStart; (l != 0) && (i < count); --l, ++i)
+ this->Data[j][i] = removeSign(*(p++), offset);
}
- /* jump to next frame start (skip 2 planes) */
- y += 2 * planeSize;
- cb += 2 * planeSize;
- cr += 2 * planeSize;
}
}
else
{
- const T1 *p = pixel;
- T2 y;
- T2 cb;
- T2 cr;
+ int j;
unsigned long i;
- for (i = count; i != 0; --i)
- {
- y = removeSign(*(p++), offset);
- cb = removeSign(*(p++), offset);
- cr = removeSign(*(p++), offset);
- convertValue(*(r++), *(g++), *(b++), y, cb, cr, maxvalue);
- }
+ for (i = 0; i < count; ++i) /* for all pixel ... */
+ for (j = 0; j < 3; ++j)
+ this->Data[j][i] = removeSign(*(p++), offset); /* ... copy planes */
}
}
- } else { /* retain YCbCr model */
- const T1 *p = pixel;
- if (this->PlanarConfiguration)
- {
-/*
- T2 *q;
- // number of pixels to be skipped (only applicable if 'PixelData' contains more
- // pixels than expected)
- const unsigned long skip = (this->InputCount > this->Count) ? (this->InputCount - this->Count) : 0;
- for (int j = 0; j < 3; ++j)
- {
- q = this->Data[j];
- for (i = count; i != 0; --i)
- *(q++) = removeSign(*(p++), offset);
- // skip to beginning of next plane
- p += skip;
- }
-*/
- unsigned long l;
- unsigned long i = 0;
- while (i < count)
- {
- /* store current pixel index */
- const unsigned long iStart = i;
- for (int j = 0; j < 3; ++j)
- {
- /* convert a single plane */
- for (l = planeSize, i = iStart; (l != 0) && (i < count); --l, ++i)
- this->Data[j][i] = removeSign(*(p++), offset);
- }
- }
- }
- else
- {
- int j;
- unsigned long i;
- for (i = 0; i < count; ++i) /* for all pixel ... */
- for (j = 0; j < 3; ++j)
- this->Data[j][i] = removeSign(*(p++), offset); /* ... copy planes */
- }
+ } else {
+ // do not process the input data, as it is too short
+ DCMIMAGE_WARN("input data is too short, filling the complete image with black pixels");
+ // erase empty part of the buffer (that has not been "blackened" yet)
+ for (int j = 0; j < 3; ++j)
+ OFBitmanipTemplate<T2>::zeroMem(this->Data[j], count);
}
}
}