| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "Image.h" |
| #include "Error.h" |
| #include "Convert.h" |
|
|
| |
| |
| |
|
|
| template <class T1, class T2> |
| extern void ScaleAndOffsetLine(T1* src, T2* dst, int n, |
| float scale, float offset, |
| T2 minVal, T2 maxVal) |
| { |
| |
| const bool scaleOffset = (scale != 1.0f) || (offset != 0.0f); |
| const bool clip = (minVal < maxVal); |
|
|
| if (scaleOffset) |
| for (int i = 0; i < n; i++) |
| { |
| float val = src[i] * scale + offset; |
| if (clip) |
| val = __min(__max(val, minVal), maxVal); |
| dst[i] = (T2) val; |
| } |
| else if (clip) |
| for (int i = 0; i < n; i++) |
| { |
| dst[i] = (T2) __min(__max(src[i], minVal), maxVal); |
| } |
| else if (typeid(T1) == typeid(T2)) |
| memcpy(dst, src, n*sizeof(T2)); |
| else |
| for (int i = 0; i < n; i++) |
| { |
| dst[i] = (T2) src[i]; |
| } |
| } |
|
|
| template <class T1, class T2> |
| extern void ScaleAndOffset(CImageOf<T1>& src, CImageOf<T2>& dst, float scale, float offset) |
| { |
| |
| |
| CShape sShape = src.Shape(); |
| CShape dShape = dst.Shape(); |
|
|
| |
| if (sShape != dShape) |
| dst.ReAllocate(sShape); |
|
|
| |
| T2 minVal = dst.MinVal(); |
| T2 maxVal = dst.MaxVal(); |
|
|
| |
| |
| |
| |
| |
| |
|
|
| |
| for (int y = 0; y < sShape.height; y++) |
| { |
| int n = sShape.width * sShape.nBands; |
| ScaleAndOffsetLine(&src.Pixel(0, y, 0), &dst.Pixel(0, y, 0), |
| n, scale, offset, minVal, maxVal); |
| } |
| } |
|
|
| template <class T> |
| extern CImageOf<T> ConvertToRGBA(CImageOf<T> src) |
| { |
| |
| CShape sShape = src.Shape(); |
| if (sShape.nBands == 4 && src.alphaChannel == 3) |
| return src; |
|
|
| |
| if (sShape.nBands != 1) |
| throw CError("ConvertToRGBA: can only convert from 1-band (gray) image"); |
|
|
| |
| CShape dShape(sShape.width, sShape.height, 4); |
| CImageOf<T> dst(dShape); |
|
|
| |
| int aC = dst.alphaChannel; |
| for (int y = 0; y < sShape.height; y++) |
| { |
| T* srcP = &src.Pixel(0, y, 0); |
| T* dstP = &dst.Pixel(0, y, 0); |
| for (int x = 0; x < sShape.width; x++, srcP++) |
| for (int b = 0; b < dShape.nBands; b++, dstP++) |
| *dstP = (b == aC) ? 255 : *srcP; |
| } |
| return dst; |
| } |
|
|
| template <class T> |
| extern CImageOf<T> ConvertToGray(CImageOf<T> src) |
| { |
| |
| CShape sShape = src.Shape(); |
| if (sShape.nBands == 1) |
| return src; |
|
|
| |
| if (sShape.nBands != 4 || src.alphaChannel != 3) |
| throw CError("ConvertToGray: can only convert from 4-band (RGBA) image"); |
|
|
| |
| CShape dShape(sShape.width, sShape.height, 1); |
| CImageOf<T> dst(dShape); |
|
|
| |
| T minVal = dst.MinVal(); |
| T maxVal = dst.MaxVal(); |
| for (int y = 0; y < sShape.height; y++) |
| { |
| T* srcP = &src.Pixel(0, y, 0); |
| T* dstP = &dst.Pixel(0, y, 0); |
| for (int x = 0; x < sShape.width; x++, srcP += 4, dstP++) |
| { |
| RGBA<T>& p = *(RGBA<T> *) srcP; |
| |
| |
| float Y = (float)(0.299 * p.R + 0.587 * p.G + 0.114 * p.B); |
| *dstP = (T) __min(maxVal, __max(minVal, Y)); |
| } |
| } |
| return dst; |
| } |
|
|
| template <class T> |
| extern void BandSelect(CImageOf<T>& src, CImageOf<T>& dst, int sBand, int dBand) |
| { |
| |
| CShape sShape = src.Shape(); |
| CShape dShape = dst.Shape(); |
|
|
| |
| if (! sShape.SameIgnoringNBands(dShape) || dShape.nBands == 0) |
| { |
| dShape.width = sShape.width; |
| dShape.height = sShape.height; |
| dShape.nBands = (dShape.nBands) ? dShape.nBands : 1; |
| dst.ReAllocate(dShape); |
| } |
|
|
| |
| int sB = sShape.nBands; |
| int dB = dShape.nBands; |
| if (sBand < 0 || sBand >= sB) |
| throw CError("BandSelect: source band %d is invalid", sBand); |
| if (dBand < 0 || dBand >= dB) |
| throw CError("BandSelect: destination band %d is invalid", dBand); |
|
|
| |
| for (int y = 0; y < sShape.height; y++) |
| { |
| T* srcP = &src.Pixel(0, y, 0); |
| T* dstP = &dst.Pixel(0, y, 0); |
| for (int x = 0; x < sShape.width; x++, srcP += sB, dstP += dB) |
| dstP[dBand] = srcP[sBand]; |
| } |
| } |
|
|
| |
| |
| |
|
|
| template <class T1> |
| void CopyPixelsInstantiate(CImageOf<T1> s1) |
| { |
| CByteImage b2; |
| CIntImage i2; |
| CFloatImage f2; |
| CopyPixels(s1, b2); |
| CopyPixels(s1, i2); |
| CopyPixels(s1, f2); |
| } |
|
|
| template <class T> |
| int InstantiateConvert(CImageOf<T> src) |
| { |
| CopyPixelsInstantiate(src); |
| CImageOf<T> r1 = ConvertToRGBA(src); |
| CImageOf<T> r2 = ConvertToGray(src); |
| BandSelect(r1, r2, 0, 0); |
| return (int)r1.Pixel(0, 0, 0); |
| } |
|
|
| void InstantiateAllConverts(void) |
| { |
| InstantiateConvert(CByteImage()); |
| InstantiateConvert(CIntImage()); |
| InstantiateConvert(CFloatImage()); |
| } |
|
|