1 /*****************************************************************************
5 ** Purpose: Imagefile classes
6 ** Programmer: Kevin Rosenberg
7 ** Date Started: June 2000
9 ** This is part of the CTSim program
10 ** Copyright (c) 1983-2001 Kevin Rosenberg
12 ** $Id: imagefile.cpp,v 1.44 2001/03/30 22:09:09 kevin Exp $
14 ** This program is free software; you can redistribute it and/or modify
15 ** it under the terms of the GNU General Public License (version 2) as
16 ** published by the Free Software Foundation.
18 ** This program is distributed in the hope that it will be useful,
19 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ** GNU General Public License for more details.
23 ** You should have received a copy of the GNU General Public License
24 ** along with this program; if not, write to the Free Software
25 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 ******************************************************************************/
33 const double ImageFile::s_dRedGrayscaleFactor = 0.299;
34 const double ImageFile::s_dGreenGrayscaleFactor = 0.587;
35 const double ImageFile::s_dBlueGrayscaleFactor = 0.114;
38 const int ImageFile::EXPORT_FORMAT_INVALID = -1;
39 const int ImageFile::EXPORT_FORMAT_TEXT = 0;
40 const int ImageFile::EXPORT_FORMAT_PGM = 1;
41 const int ImageFile::EXPORT_FORMAT_PGMASCII = 2;
43 const int ImageFile::EXPORT_FORMAT_PNG = 3;
44 const int ImageFile::EXPORT_FORMAT_PNG16 = 4;
47 const int ImageFile::EXPORT_FORMAT_DICOM = 5;
50 const char* ImageFile::s_aszExportFormatName[] =
64 const char* ImageFile::s_aszExportFormatTitle[] =
75 const int ImageFile::s_iExportFormatCount = sizeof(s_aszExportFormatName) / sizeof(const char*);
78 const int ImageFile::IMPORT_FORMAT_INVALID = -1;
79 const int ImageFile::IMPORT_FORMAT_PPM = 0;
81 const int ImageFile::IMPORT_FORMAT_PNG = 1;
84 const int ImageFile::IMPORT_FORMAT_DICOM = 2;
88 const char* ImageFile::s_aszImportFormatName[] =
99 const char* ImageFile::s_aszImportFormatTitle[] =
103 #ifdef HAVE_CTN_DICOM
107 const int ImageFile::s_iImportFormatCount = sizeof(s_aszImportFormatName) / sizeof(const char*);
111 F32Image::F32Image (int nx, int ny, int dataType)
112 : Array2dFile (nx, ny, sizeof(kfloat32), Array2dFile::PIXEL_FLOAT32, dataType)
116 F32Image::F32Image (void)
119 setPixelFormat (Array2dFile::PIXEL_FLOAT32);
120 setPixelSize (sizeof(kfloat32));
121 setDataType (Array2dFile::DATA_TYPE_REAL);
124 F64Image::F64Image (int nx, int ny, int dataType)
125 : Array2dFile (nx, ny, sizeof(kfloat64), Array2dFile::PIXEL_FLOAT64, dataType)
129 F64Image::F64Image (void)
132 setPixelFormat (PIXEL_FLOAT64);
133 setPixelSize (sizeof(kfloat64));
134 setDataType (Array2dFile::DATA_TYPE_REAL);
138 ImageFile::getCenterCoordinates (unsigned int& iXCenter, unsigned int& iYCenter)
143 iXCenter = (m_nx - 1) / 2;
148 iYCenter = (m_ny - 1) / 2;
153 ImageFile::filterResponse (const char* const domainName, double bw, const char* const filterName,
154 double filt_param, double dInputScale, double dOutputScale)
156 ImageFileArray v = getArray();
157 SignalFilter filter (filterName, domainName, bw, filt_param);
159 unsigned int iXCenter, iYCenter;
160 getCenterCoordinates (iXCenter, iYCenter);
162 for (unsigned int ix = 0; ix < m_nx; ix++)
163 for (unsigned int iy = 0; iy < m_ny; iy++) {
164 long lD2 = ((ix - iXCenter) * (ix - iXCenter)) + ((iy - iYCenter) * (iy - iYCenter));
165 double r = ::sqrt (static_cast<double>(lD2)) * dInputScale;
166 v[ix][iy] = filter.response (r) * dOutputScale;
171 // ImageFile::comparativeStatistics Calculate comparative stats
174 // d Normalized root mean squared distance measure
175 // r Normalized mean absolute distance measure
176 // e Worst case distance measure
179 // G.T. Herman, Image Reconstruction From Projections, 1980
182 ImageFile::comparativeStatistics (const ImageFile& imComp, double& d, double& r, double& e) const
184 if (imComp.nx() != m_nx && imComp.ny() != m_ny) {
185 sys_error (ERR_WARNING, "Image sizes differ [ImageFile::comparativeStatistics]");
188 ImageFileArrayConst v = getArray();
189 if (v == NULL || m_nx == 0 || m_ny == 0)
192 ImageFileArrayConst vComp = imComp.getArray();
195 for (unsigned int ix = 0; ix < m_nx; ix++) {
196 for (unsigned int iy = 0; iy < m_ny; iy++) {
200 myMean /= (m_nx * m_ny);
202 double sqErrorSum = 0.;
203 double absErrorSum = 0.;
204 double sqDiffFromMeanSum = 0.;
205 double absValueSum = 0.;
206 for (unsigned int ix2 = 0; ix2 < m_nx; ix2++) {
207 for (unsigned int iy = 0; iy < m_ny; iy++) {
208 double diff = v[ix2][iy] - vComp[ix2][iy];
209 sqErrorSum += diff * diff;
210 absErrorSum += fabs(diff);
211 double diffFromMean = v[ix2][iy] - myMean;
212 sqDiffFromMeanSum += diffFromMean * diffFromMean;
213 absValueSum += fabs(v[ix2][iy]);
217 d = ::sqrt (sqErrorSum / sqDiffFromMeanSum);
218 r = absErrorSum / absValueSum;
223 for (int ix3 = 0; ix3 < hx; ix3++) {
224 for (int iy = 0; iy < hy; iy++) {
225 double avgPixel = 0.25 * (v[2*ix3][2*iy] + v[2*ix3+1][2*iy] + v[2*ix3][2*iy+1] + v[2*ix3+1][2*iy+1]);
226 double avgPixelComp = 0.25 * (vComp[2*ix3][2*iy] + vComp[2*ix3+1][2*iy] + vComp[2*ix3][2*iy+1] + vComp[2*ix3+1][2*iy+1]);
227 double error = fabs (avgPixel - avgPixelComp);
240 ImageFile::printComparativeStatistics (const ImageFile& imComp, std::ostream& os) const
244 if (comparativeStatistics (imComp, d, r, e)) {
245 os << " Normalized root mean squared distance (d): " << d << std::endl;
246 os << " Normalized mean absolute distance (r): " << r << std::endl;
247 os << "Worst case distance (2x2 pixel average) (e): " << e << std::endl;
255 ImageFile::printStatistics (std::ostream& os) const
257 double min, max, mean, mode, median, stddev;
259 statistics (min, max, mean, mode, median, stddev);
261 os << "Real Component Statistics" << std::endl;
263 os << " min: " << min << std::endl;
264 os << " max: " << max << std::endl;
265 os << " mean: " << mean << std::endl;
266 os << " mode: " << mode << std::endl;
267 os << "median: " << median << std::endl;
268 os << "stddev: " << stddev << std::endl;
271 statistics (getImaginaryArray(), min, max, mean, mode, median, stddev);
272 os << std::endl << "Imaginary Component Statistics" << std::endl;
273 os << " min: " << min << std::endl;
274 os << " max: " << max << std::endl;
275 os << " mean: " << mean << std::endl;
276 os << " mode: " << mode << std::endl;
277 os << "median: " << median << std::endl;
278 os << "stddev: " << stddev << std::endl;
284 ImageFile::statistics (double& min, double& max, double& mean, double& mode, double& median, double& stddev) const
286 ImageFileArrayConst v = getArray();
287 statistics (v, min, max, mean, mode, median, stddev);
292 ImageFile::statistics (ImageFileArrayConst v, double& min, double& max, double& mean, double& mode, double& median, double& stddev) const
297 if (v == NULL || nx == 0 || ny == 0)
300 std::vector<double> vecImage;
302 vecImage.resize (nx * ny);
303 for (int ix = 0; ix < nx; ix++) {
304 for (int iy = 0; iy < ny; iy++)
305 vecImage[iVec++] = v[ix][iy];
308 vectorNumericStatistics (vecImage, nx * ny, min, max, mean, mode, median, stddev);
312 ImageFile::getMinMax (double& min, double& max) const
316 ImageFileArrayConst v = getArray();
318 if (v == NULL || nx == 0 || ny == 0)
323 for (int ix = 0; ix < nx; ix++) {
324 for (int iy = 0; iy < ny; iy++) {
334 ImageFile::convertRealToComplex ()
336 if (dataType() != Array2dFile::DATA_TYPE_REAL)
339 if (! reallocRealToComplex())
342 ImageFileArray vImag = getImaginaryArray();
343 for (unsigned int ix = 0; ix < m_nx; ix++) {
344 ImageFileColumn vCol = vImag[ix];
345 for (unsigned int iy = 0; iy < m_ny; iy++)
353 ImageFile::convertComplexToReal ()
355 if (dataType() != Array2dFile::DATA_TYPE_COMPLEX)
358 ImageFileArray vReal = getArray();
359 ImageFileArray vImag = getImaginaryArray();
360 for (unsigned int ix = 0; ix < m_nx; ix++) {
361 ImageFileColumn vRealCol = vReal[ix];
362 ImageFileColumn vImagCol = vImag[ix];
363 for (unsigned int iy = 0; iy < m_ny; iy++) {
364 CTSimComplex c (*vRealCol, *vImagCol);
365 *vRealCol++ = std::abs (c);
370 return reallocComplexToReal();
374 ImageFile::subtractImages (const ImageFile& rRHS, ImageFile& result) const
376 if (m_nx != rRHS.nx() || m_ny != rRHS.ny() || m_nx != result.nx() || m_ny != result.ny()) {
377 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::subtractImage]");
381 if (isComplex() || rRHS.isComplex() && ! result.isComplex())
382 result.convertRealToComplex();
384 ImageFileArrayConst vLHS = getArray();
385 ImageFileArrayConst vLHSImag = getImaginaryArray();
386 ImageFileArrayConst vRHS = rRHS.getArray();
387 ImageFileArrayConst vRHSImag = rRHS.getImaginaryArray();
388 ImageFileArray vResult = result.getArray();
389 ImageFileArray vResultImag = result.getImaginaryArray();
391 for (unsigned int ix = 0; ix < m_nx; ix++) {
392 for (unsigned int iy = 0; iy < m_ny; iy++) {
393 vResult[ix][iy] = vLHS[ix][iy] - vRHS[ix][iy];
394 if (result.isComplex()) {
395 vResultImag[ix][iy] = 0;
397 vResultImag[ix][iy] += vLHSImag[ix][iy];
398 if (rRHS.isComplex())
399 vResultImag[ix][iy] -= vRHSImag[ix][iy];
408 ImageFile::addImages (const ImageFile& rRHS, ImageFile& result) const
410 if (m_nx != rRHS.nx() || m_ny != rRHS.ny() || m_nx != result.nx() || m_ny != result.ny()) {
411 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::subtractImage]");
415 if (isComplex() || rRHS.isComplex() && ! result.isComplex())
416 result.convertRealToComplex();
418 ImageFileArrayConst vLHS = getArray();
419 ImageFileArrayConst vLHSImag = getImaginaryArray();
420 ImageFileArrayConst vRHS = rRHS.getArray();
421 ImageFileArrayConst vRHSImag = rRHS.getImaginaryArray();
422 ImageFileArray vResult = result.getArray();
423 ImageFileArray vResultImag = result.getImaginaryArray();
425 for (unsigned int ix = 0; ix < m_nx; ix++) {
426 for (unsigned int iy = 0; iy < m_ny; iy++) {
427 vResult[ix][iy] = vLHS[ix][iy] + vRHS[ix][iy];
428 if (result.isComplex()) {
429 vResultImag[ix][iy] = 0;
431 vResultImag[ix][iy] += vLHSImag[ix][iy];
432 if (rRHS.isComplex())
433 vResultImag[ix][iy] += vRHSImag[ix][iy];
442 ImageFile::multiplyImages (const ImageFile& rRHS, ImageFile& result) const
444 if (m_nx != rRHS.nx() || m_ny != rRHS.ny() || m_nx != result.nx() || m_ny != result.ny()) {
445 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::subtractImage]");
449 if (isComplex() || rRHS.isComplex() && ! result.isComplex())
450 result.convertRealToComplex();
452 ImageFileArrayConst vLHS = getArray();
453 ImageFileArrayConst vLHSImag = getImaginaryArray();
454 ImageFileArrayConst vRHS = rRHS.getArray();
455 ImageFileArrayConst vRHSImag = rRHS.getImaginaryArray();
456 ImageFileArray vResult = result.getArray();
457 ImageFileArray vResultImag = result.getImaginaryArray();
459 for (unsigned int ix = 0; ix < m_nx; ix++) {
460 for (unsigned int iy = 0; iy < m_ny; iy++) {
461 if (result.isComplex()) {
464 dImag = vLHSImag[ix][iy];
465 std::complex<double> cLHS (vLHS[ix][iy], dImag);
467 if (rRHS.isComplex())
468 dImag = vRHSImag[ix][iy];
469 std::complex<double> cRHS (vRHS[ix][iy], dImag);
470 std::complex<double> cResult = cLHS * cRHS;
471 vResult[ix][iy] = cResult.real();
472 vResultImag[ix][iy] = cResult.imag();
474 vResult[ix][iy] = vLHS[ix][iy] * vRHS[ix][iy];
483 ImageFile::divideImages (const ImageFile& rRHS, ImageFile& result) const
485 if (m_nx != rRHS.nx() || m_ny != rRHS.ny() || m_nx != result.nx() || m_ny != result.ny()) {
486 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::subtractImage]");
490 if (isComplex() || rRHS.isComplex() && ! result.isComplex())
491 result.convertRealToComplex();
493 ImageFileArrayConst vLHS = getArray();
494 ImageFileArrayConst vLHSImag = getImaginaryArray();
495 ImageFileArrayConst vRHS = rRHS.getArray();
496 ImageFileArrayConst vRHSImag = rRHS.getImaginaryArray();
497 ImageFileArray vResult = result.getArray();
498 ImageFileArray vResultImag = result.getImaginaryArray();
500 for (unsigned int ix = 0; ix < m_nx; ix++) {
501 for (unsigned int iy = 0; iy < m_ny; iy++) {
502 if (result.isComplex()) {
505 dImag = vLHSImag[ix][iy];
506 std::complex<double> cLHS (vLHS[ix][iy], dImag);
508 if (rRHS.isComplex())
509 dImag = vRHSImag[ix][iy];
510 std::complex<double> cRHS (vRHS[ix][iy], dImag);
511 std::complex<double> cResult = cLHS / cRHS;
512 vResult[ix][iy] = cResult.real();
513 vResultImag[ix][iy] = cResult.imag();
516 vResult[ix][iy] = vLHS[ix][iy] / vRHS[ix][iy];
528 ImageFile::invertPixelValues (ImageFile& result) const
530 if (m_nx != result.nx() || m_ny != result.ny()) {
531 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
535 if (isComplex() && ! result.isComplex())
536 result.convertRealToComplex();
538 ImageFileArrayConst vLHS = getArray();
539 ImageFileArray vResult = result.getArray();
541 for (unsigned int ix = 0; ix < m_nx; ix++) {
542 ImageFileColumnConst in = vLHS[ix];
543 ImageFileColumn out = vResult[ix];
544 for (unsigned int iy = 0; iy < m_ny; iy++)
552 ImageFile::sqrt (ImageFile& result) const
554 if (m_nx != result.nx() || m_ny != result.ny()) {
555 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
559 if (isComplex() && ! result.isComplex())
560 result.convertRealToComplex();
562 bool bComplexOutput = result.isComplex();
563 ImageFileArrayConst vLHS = getArray();
564 if (! bComplexOutput) // check if should convert to complex output
565 for (unsigned int ix = 0; ix < m_nx; ix++)
566 for (unsigned int iy = 0; iy < m_ny; iy++)
567 if (! bComplexOutput && vLHS[ix][iy] < 0) {
568 result.convertRealToComplex();
569 bComplexOutput = true;
573 ImageFileArrayConst vLHSImag = getImaginaryArray();
574 ImageFileArray vResult = result.getArray();
575 ImageFileArray vResultImag = result.getImaginaryArray();
577 for (unsigned int ix = 0; ix < m_nx; ix++) {
578 for (unsigned int iy = 0; iy < m_ny; iy++) {
579 if (result.isComplex()) {
582 dImag = vLHSImag[ix][iy];
583 std::complex<double> cLHS (vLHS[ix][iy], dImag);
584 std::complex<double> cResult = std::sqrt(cLHS);
585 vResult[ix][iy] = cResult.real();
586 vResultImag[ix][iy] = cResult.imag();
588 vResult[ix][iy] = ::sqrt (vLHS[ix][iy]);
597 ImageFile::log (ImageFile& result) const
599 if (m_nx != result.nx() || m_ny != result.ny()) {
600 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::log]");
604 if (isComplex() && ! result.isComplex())
605 result.convertRealToComplex();
607 ImageFileArrayConst vLHS = getArray();
608 ImageFileArrayConst vLHSImag = getImaginaryArray();
609 ImageFileArray vResult = result.getArray();
610 ImageFileArray vResultImag = result.getImaginaryArray();
612 for (unsigned int ix = 0; ix < m_nx; ix++) {
613 for (unsigned int iy = 0; iy < m_ny; iy++) {
614 if (result.isComplex()) {
617 dImag = vLHSImag[ix][iy];
618 std::complex<double> cLHS (vLHS[ix][iy], dImag);
619 std::complex<double> cResult = std::log (cLHS);
620 vResult[ix][iy] = cResult.real();
621 vResultImag[ix][iy] = cResult.imag();
623 if (vLHS[ix][iy] > 0)
624 vResult[ix][iy] = ::log (vLHS[ix][iy]);
636 ImageFile::exp (ImageFile& result) const
638 if (m_nx != result.nx() || m_ny != result.ny()) {
639 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
643 if (isComplex() && ! result.isComplex())
644 result.convertRealToComplex();
646 ImageFileArrayConst vLHS = getArray();
647 ImageFileArrayConst vLHSImag = getImaginaryArray();
648 ImageFileArray vResult = result.getArray();
649 ImageFileArray vResultImag = result.getImaginaryArray();
651 for (unsigned int ix = 0; ix < m_nx; ix++) {
652 for (unsigned int iy = 0; iy < m_ny; iy++) {
653 if (result.isComplex()) {
656 dImag = vLHSImag[ix][iy];
657 std::complex<double> cLHS (vLHS[ix][iy], dImag);
658 std::complex<double> cResult = std::exp (cLHS);
659 vResult[ix][iy] = cResult.real();
660 vResultImag[ix][iy] = cResult.imag();
662 vResult[ix][iy] = ::exp (vLHS[ix][iy]);
671 ImageFile::scaleImage (ImageFile& result) const
673 unsigned int nx = m_nx;
674 unsigned int ny = m_ny;
675 unsigned int newNX = result.nx();
676 unsigned int newNY = result.ny();
678 double dXScale = static_cast<double>(newNX) / static_cast<double>(nx);
679 double dYScale = static_cast<double>(newNY) / static_cast<double>(ny);
681 if (isComplex() && ! result.isComplex())
682 result.convertRealToComplex();
684 ImageFileArrayConst vReal = getArray();
685 ImageFileArrayConst vImag = getImaginaryArray();
686 ImageFileArray vResult = result.getArray();
687 ImageFileArray vResultImag = result.getImaginaryArray();
689 BilinearInterpolator<ImageFileValue> realInterp (vReal, nx, ny);
690 BilinearInterpolator<ImageFileValue> imagInterp (vImag, nx, ny);
692 for (unsigned int ix = 0; ix < newNX; ix++) {
693 for (unsigned int iy = 0; iy < newNY; iy++) {
694 double dXPos = ix / dXScale;
695 double dYPos = iy / dYScale;
696 vResult[ix][iy] = realInterp.interpolate (dXPos, dYPos);
697 if (result.isComplex())
699 vResultImag[ix][iy] = imagInterp.interpolate (dXPos, dYPos);
701 vResultImag[ix][iy] = 0;
710 ImageFile::fft (ImageFile& result) const
712 if (m_nx != result.nx() || m_ny != result.ny()) {
713 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
717 if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
718 if (! result.convertRealToComplex ())
722 fftw_complex* in = new fftw_complex [m_nx * m_ny];
724 ImageFileArrayConst vReal = getArray();
725 ImageFileArrayConst vImag = getImaginaryArray();
728 unsigned int iArray = 0;
729 for (ix = 0; ix < m_nx; ix++) {
730 for (iy = 0; iy < m_ny; iy++) {
731 in[iArray].re = vReal[ix][iy];
733 in[iArray].im = vImag[ix][iy];
740 fftwnd_plan plan = fftw2d_create_plan (m_nx, m_ny, FFTW_FORWARD, FFTW_IN_PLACE | FFTW_ESTIMATE | FFTW_USE_WISDOM);
741 fftwnd_one (plan, in, NULL);
743 ImageFileArray vRealResult = result.getArray();
744 ImageFileArray vImagResult = result.getImaginaryArray();
746 unsigned int iScale = m_nx * m_ny;
747 for (ix = 0; ix < m_nx; ix++) {
748 for (iy = 0; iy < m_ny; iy++) {
749 vRealResult[ix][iy] = in[iArray].re / iScale;
750 vImagResult[ix][iy] = in[iArray].im / iScale;
755 fftwnd_destroy_plan (plan);
757 Fourier::shuffleFourierToNaturalOrder (result);
764 ImageFile::ifft (ImageFile& result) const
766 if (m_nx != result.nx() || m_ny != result.ny()) {
767 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
771 if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
772 if (! result.convertRealToComplex ())
776 ImageFileArrayConst vReal = getArray();
777 ImageFileArrayConst vImag = getImaginaryArray();
778 ImageFileArray vRealResult = result.getArray();
779 ImageFileArray vImagResult = result.getImaginaryArray();
781 for (ix = 0; ix < m_nx; ix++) {
782 for (iy = 0; iy < m_ny; iy++) {
783 vRealResult[ix][iy] = vReal[ix][iy];
785 vImagResult[ix][iy] = vImag[ix][iy];
787 vImagResult[ix][iy] = 0;
791 Fourier::shuffleNaturalToFourierOrder (result);
793 fftw_complex* in = new fftw_complex [m_nx * m_ny];
795 unsigned int iArray = 0;
796 for (ix = 0; ix < m_nx; ix++) {
797 for (iy = 0; iy < m_ny; iy++) {
798 in[iArray].re = vRealResult[ix][iy];
799 in[iArray].im = vImagResult[ix][iy];
804 fftwnd_plan plan = fftw2d_create_plan (m_nx, m_ny, FFTW_BACKWARD, FFTW_IN_PLACE | FFTW_ESTIMATE | FFTW_USE_WISDOM);
806 fftwnd_one (plan, in, NULL);
809 for (ix = 0; ix < m_nx; ix++) {
810 for (iy = 0; iy < m_ny; iy++) {
811 vRealResult[ix][iy] = in[iArray].re;
812 vImagResult[ix][iy] = in[iArray].im;
816 fftwnd_destroy_plan (plan);
824 ImageFile::fftRows (ImageFile& result) const
826 if (m_nx != result.nx() || m_ny != result.ny()) {
827 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::fftRows]");
831 if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
832 if (! result.convertRealToComplex ())
836 ImageFileArrayConst vReal = getArray();
837 ImageFileArrayConst vImag = getImaginaryArray();
839 fftw_plan plan = fftw_create_plan (m_nx, FFTW_FORWARD, FFTW_IN_PLACE | FFTW_ESTIMATE | FFTW_USE_WISDOM);
841 fftw_complex* in = new fftw_complex [m_nx];
842 std::complex<double>* pcRow = new std::complex<double> [m_nx];
843 for (int iy = 0; iy < m_ny; iy++) {
845 for (ix = 0; ix < m_nx; ix++) {
846 in[ix].re = vReal[ix][iy];
848 in[ix].im = vImag[ix][iy];
853 fftw_one (plan, in, NULL);
855 for (ix = 0; ix < m_nx; ix++)
856 pcRow[ix] = std::complex<double>(in[ix].re, in[ix].im);
858 Fourier::shuffleFourierToNaturalOrder (pcRow, m_nx);
859 for (ix = 0; ix < m_nx; ix++) {
860 vReal[ix][iy] = pcRow[ix].real() / m_nx;
861 vImag[ix][iy] = pcRow[ix].imag() / m_nx;
866 fftw_destroy_plan (plan);
873 ImageFile::ifftRows (ImageFile& result) const
875 if (m_nx != result.nx() || m_ny != result.ny()) {
876 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::fftRows]");
880 if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
881 if (! result.convertRealToComplex ())
885 fftw_complex* in = new fftw_complex [m_nx];
887 ImageFileArrayConst vReal = getArray();
888 ImageFileArrayConst vImag = getImaginaryArray();
890 fftw_plan plan = fftw_create_plan (m_nx, FFTW_BACKWARD, FFTW_IN_PLACE | FFTW_ESTIMATE | FFTW_USE_WISDOM);
891 std::complex<double>* pcRow = new std::complex<double> [m_nx];
894 unsigned int iArray = 0;
895 for (iy = 0; iy < m_ny; iy++) {
896 for (ix = 0; ix < m_nx; ix++) {
899 dImag = vImag[ix][iy];
900 pcRow[ix] = std::complex<double> (vReal[ix][iy], dImag);
903 Fourier::shuffleNaturalToFourierOrder (pcRow, m_nx);
905 for (ix = 0; ix < m_nx; ix++) {
906 in[ix].re = pcRow[ix].real();
907 in[ix].im = pcRow[ix].imag();
910 fftw_one (plan, in, NULL);
912 for (ix = 0; ix < m_nx; ix++) {
913 vReal[ix][iy] = in[ix].re;
914 vImag[ix][iy] = in[ix].im;
919 fftw_destroy_plan (plan);
926 ImageFile::fftCols (ImageFile& result) const
928 if (m_nx != result.nx() || m_ny != result.ny()) {
929 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::fftRows]");
933 if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
934 if (! result.convertRealToComplex ())
938 ImageFileArrayConst vReal = getArray();
939 ImageFileArrayConst vImag = getImaginaryArray();
941 fftw_plan plan = fftw_create_plan (m_ny, FFTW_FORWARD, FFTW_IN_PLACE | FFTW_ESTIMATE | FFTW_USE_WISDOM);
943 std::complex<double>* pcCol = new std::complex<double> [m_ny];
944 fftw_complex* in = new fftw_complex [m_ny];
945 for (int ix = 0; ix < m_nx; ix++) {
947 for (iy = 0; iy < m_ny; iy++) {
948 in[iy].re = vReal[ix][iy];
950 in[iy].im = vImag[ix][iy];
955 fftw_one (plan, in, NULL);
957 for (iy = 0; iy < m_ny; iy++)
958 pcCol[iy] = std::complex<double>(in[iy].re, in[iy].im);
960 Fourier::shuffleFourierToNaturalOrder (pcCol, m_ny);
961 for (iy = 0; iy < m_ny; iy++) {
962 vReal[ix][iy] = pcCol[iy].real() / m_ny;
963 vImag[ix][iy] = pcCol[iy].imag() / m_ny;
968 fftw_destroy_plan (plan);
975 ImageFile::ifftCols (ImageFile& result) const
977 if (m_nx != result.nx() || m_ny != result.ny()) {
978 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::fftRows]");
982 if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
983 if (! result.convertRealToComplex ())
987 fftw_complex* in = new fftw_complex [m_ny];
989 ImageFileArrayConst vReal = getArray();
990 ImageFileArrayConst vImag = getImaginaryArray();
992 fftw_plan plan = fftw_create_plan (m_ny, FFTW_BACKWARD, FFTW_IN_PLACE | FFTW_ESTIMATE | FFTW_USE_WISDOM);
993 std::complex<double>* pcCol = new std::complex<double> [m_ny];
996 unsigned int iArray = 0;
997 for (ix = 0; ix < m_nx; ix++) {
998 for (iy = 0; iy < m_ny; iy++) {
1001 dImag = vImag[ix][iy];
1002 pcCol[iy] = std::complex<double> (vReal[ix][iy], dImag);
1005 Fourier::shuffleNaturalToFourierOrder (pcCol, m_ny);
1007 for (iy = 0; iy < m_ny; iy++) {
1008 in[iy].re = pcCol[iy].real();
1009 in[iy].im = pcCol[iy].imag();
1012 fftw_one (plan, in, NULL);
1014 for (iy = 0; iy < m_ny; iy++) {
1015 vReal[ix][iy] = in[iy].re;
1016 vImag[ix][iy] = in[iy].im;
1021 fftw_destroy_plan (plan);
1032 ImageFile::fourier (ImageFile& result) const
1034 if (m_nx != result.nx() || m_ny != result.ny()) {
1035 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
1039 if (! result.isComplex())
1040 if (! result.convertRealToComplex ())
1043 ImageFileArrayConst vLHS = getArray();
1044 ImageFileArrayConst vLHSImag = getImaginaryArray();
1045 ImageFileArray vRealResult = result.getArray();
1046 ImageFileArray vImagResult = result.getImaginaryArray();
1048 unsigned int ix, iy;
1050 // alloc output matrix
1051 CTSimComplex** complexOut = new CTSimComplex* [m_nx];
1052 for (ix = 0; ix < m_nx; ix++)
1053 complexOut[ix] = new CTSimComplex [m_ny];
1055 // fourier each x column
1056 CTSimComplex* pY = new CTSimComplex [m_ny];
1057 for (ix = 0; ix < m_nx; ix++) {
1058 for (iy = 0; iy < m_ny; iy++) {
1061 dImag = vLHSImag[ix][iy];
1062 pY[iy] = std::complex<double>(vLHS[ix][iy], dImag);
1064 ProcessSignal::finiteFourierTransform (pY, complexOut[ix], m_ny, ProcessSignal::FORWARD);
1068 // fourier each y row
1069 CTSimComplex* pX = new CTSimComplex [m_nx];
1070 CTSimComplex* complexOutRow = new CTSimComplex [m_nx];
1071 for (iy = 0; iy < m_ny; iy++) {
1072 for (ix = 0; ix < m_nx; ix++)
1073 pX[ix] = complexOut[ix][iy];
1074 ProcessSignal::finiteFourierTransform (pX, complexOutRow, m_nx, ProcessSignal::FORWARD);
1075 for (ix = 0; ix < m_nx; ix++)
1076 complexOut[ix][iy] = complexOutRow[ix];
1079 delete [] complexOutRow;
1081 for (ix = 0; ix < m_nx; ix++)
1082 for (iy = 0; iy < m_ny; iy++) {
1083 vRealResult[ix][iy] = complexOut[ix][iy].real();
1084 vImagResult[ix][iy] = complexOut[ix][iy].imag();
1087 Fourier::shuffleFourierToNaturalOrder (result);
1089 // delete complexOut matrix
1090 for (ix = 0; ix < m_nx; ix++)
1091 delete [] complexOut[ix];
1092 delete [] complexOut;
1098 ImageFile::inverseFourier (ImageFile& result) const
1100 if (m_nx != result.nx() || m_ny != result.ny()) {
1101 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
1105 if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
1106 if (! result.convertRealToComplex ())
1110 ImageFileArrayConst vLHSReal = getArray();
1111 ImageFileArrayConst vLHSImag = getImaginaryArray();
1112 ImageFileArray vRealResult = result.getArray();
1113 ImageFileArray vImagResult = result.getImaginaryArray();
1115 unsigned int ix, iy;
1116 // alloc 2d complex output matrix
1117 CTSimComplex** complexOut = new CTSimComplex* [m_nx];
1118 for (ix = 0; ix < m_nx; ix++)
1119 complexOut[ix] = new CTSimComplex [m_ny];
1121 // put input image into result
1122 for (ix = 0; ix < m_nx; ix++)
1123 for (iy = 0; iy < m_ny; iy++) {
1124 vRealResult[ix][iy] = vLHSReal[ix][iy];
1126 vImagResult[ix][iy] = vLHSImag[ix][iy];
1128 vImagResult[ix][iy] = 0;
1131 Fourier::shuffleNaturalToFourierOrder (result);
1133 // ifourier each x column
1134 CTSimComplex* pCol = new CTSimComplex [m_ny];
1135 for (ix = 0; ix < m_nx; ix++) {
1136 for (iy = 0; iy < m_ny; iy++) {
1137 pCol[iy] = std::complex<double> (vRealResult[ix][iy], vImagResult[ix][iy]);
1139 ProcessSignal::finiteFourierTransform (pCol, complexOut[ix], m_ny, ProcessSignal::BACKWARD);
1143 // ifourier each y row
1144 CTSimComplex* complexInRow = new CTSimComplex [m_nx];
1145 CTSimComplex* complexOutRow = new CTSimComplex [m_nx];
1146 for (iy = 0; iy < m_ny; iy++) {
1147 for (ix = 0; ix < m_nx; ix++)
1148 complexInRow[ix] = complexOut[ix][iy];
1149 ProcessSignal::finiteFourierTransform (complexInRow, complexOutRow, m_nx, ProcessSignal::BACKWARD);
1150 for (ix = 0; ix < m_nx; ix++)
1151 complexOut[ix][iy] = complexOutRow[ix];
1153 delete [] complexInRow;
1154 delete [] complexOutRow;
1156 for (ix = 0; ix < m_nx; ix++)
1157 for (iy = 0; iy < m_ny; iy++) {
1158 vRealResult[ix][iy] = complexOut[ix][iy].real();
1159 vImagResult[ix][iy] = complexOut[ix][iy].imag();
1162 // delete complexOut matrix
1163 for (ix = 0; ix < m_nx; ix++)
1164 delete [] complexOut[ix];
1165 delete [] complexOut;
1172 ImageFile::magnitude (ImageFile& result) const
1174 if (m_nx != result.nx() || m_ny != result.ny()) {
1175 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
1179 ImageFileArray vReal = getArray();
1180 ImageFileArray vImag = getImaginaryArray();
1181 ImageFileArray vRealResult = result.getArray();
1183 for (unsigned int ix = 0; ix < m_nx; ix++)
1184 for (unsigned int iy = 0; iy < m_ny; iy++) {
1186 vRealResult[ix][iy] = ::sqrt (vReal[ix][iy] * vReal[ix][iy] + vImag[ix][iy] * vImag[ix][iy]);
1188 vRealResult[ix][iy] = ::fabs(vReal[ix][iy]);
1191 if (result.isComplex())
1192 result.reallocComplexToReal();
1198 ImageFile::phase (ImageFile& result) const
1200 if (m_nx != result.nx() || m_ny != result.ny()) {
1201 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
1205 ImageFileArray vReal = getArray();
1206 ImageFileArray vImag = getImaginaryArray();
1207 ImageFileArray vRealResult = result.getArray();
1209 for (unsigned int ix = 0; ix < m_nx; ix++) {
1210 for (unsigned int iy = 0; iy < m_ny; iy++) {
1212 vRealResult[ix][iy] = ::atan2 (vImag[ix][iy], vReal[ix][iy]);
1214 vRealResult[ix][iy] = 0;
1217 if (result.isComplex())
1218 result.reallocComplexToReal();
1224 ImageFile::real (ImageFile& result) const
1226 if (m_nx != result.nx() || m_ny != result.ny()) {
1227 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
1231 ImageFileArray vReal = getArray();
1232 ImageFileArray vRealResult = result.getArray();
1234 for (unsigned int ix = 0; ix < m_nx; ix++) {
1235 for (unsigned int iy = 0; iy < m_ny; iy++) {
1236 vRealResult[ix][iy] = vReal[ix][iy];
1240 if (result.isComplex())
1241 result.reallocComplexToReal();
1247 ImageFile::imaginary (ImageFile& result) const
1249 if (m_nx != result.nx() || m_ny != result.ny()) {
1250 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
1254 ImageFileArray vImag = getArray();
1255 ImageFileArray vRealResult = result.getArray();
1257 for (unsigned int ix = 0; ix < m_nx; ix++) {
1258 for (unsigned int iy = 0; iy < m_ny; iy++) {
1260 vRealResult[ix][iy] = vImag[ix][iy];
1262 vRealResult[ix][iy] = 0;
1266 if (result.isComplex())
1267 result.reallocComplexToReal();
1273 ImageFile::square (ImageFile& result) const
1275 if (m_nx != result.nx() || m_ny != result.ny()) {
1276 sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
1280 if (isComplex() && ! result.isComplex())
1281 result.convertRealToComplex();
1283 ImageFileArrayConst vLHS = getArray();
1284 ImageFileArrayConst vLHSImag = getImaginaryArray();
1285 ImageFileArray vResult = result.getArray();
1286 ImageFileArray vResultImag = result.getImaginaryArray();
1288 for (unsigned int ix = 0; ix < m_nx; ix++) {
1289 for (unsigned int iy = 0; iy < m_ny; iy++) {
1290 if (result.isComplex()) {
1293 dImag = vLHSImag[ix][iy];
1294 std::complex<double> cLHS (vLHS[ix][iy], dImag);
1295 std::complex<double> cResult = cLHS * cLHS;
1296 vResult[ix][iy] = cResult.real();
1297 vResultImag[ix][iy] = cResult.imag();
1299 vResult[ix][iy] = vLHS[ix][iy] * vLHS[ix][iy];
1307 ImageFile::convertExportFormatNameToID (const char* const formatName)
1309 int formatID = EXPORT_FORMAT_INVALID;
1311 for (int i = 0; i < s_iExportFormatCount; i++)
1312 if (strcasecmp (formatName, s_aszExportFormatName[i]) == 0) {
1321 ImageFile::convertExportFormatIDToName (int formatID)
1323 static const char *formatName = "";
1325 if (formatID >= 0 && formatID < s_iExportFormatCount)
1326 return (s_aszExportFormatName[formatID]);
1328 return (formatName);
1332 ImageFile::convertExportFormatIDToTitle (const int formatID)
1334 static const char *formatTitle = "";
1336 if (formatID >= 0 && formatID < s_iExportFormatCount)
1337 return (s_aszExportFormatTitle[formatID]);
1339 return (formatTitle);
1343 ImageFile::convertImportFormatNameToID (const char* const formatName)
1345 int formatID = IMPORT_FORMAT_INVALID;
1347 for (int i = 0; i < s_iImportFormatCount; i++)
1348 if (strcasecmp (formatName, s_aszImportFormatName[i]) == 0) {
1357 ImageFile::convertImportFormatIDToName (int formatID)
1359 static const char *formatName = "";
1361 if (formatID >= 0 && formatID < s_iImportFormatCount)
1362 return (s_aszImportFormatName[formatID]);
1364 return (formatName);
1368 ImageFile::convertImportFormatIDToTitle (const int formatID)
1370 static const char *formatTitle = "";
1372 if (formatID >= 0 && formatID < s_iImportFormatCount)
1373 return (s_aszImportFormatTitle[formatID]);
1375 return (formatTitle);
1379 ImageFile::importImage (const char* const pszFormat, const char* const pszFilename)
1381 int iFormatID = convertImportFormatNameToID (pszFormat);
1383 if (iFormatID == IMPORT_FORMAT_PPM)
1384 return readImagePPM (pszFilename);
1386 else if (iFormatID == IMPORT_FORMAT_PNG)
1387 return readImagePNG (pszFilename);
1390 sys_error (ERR_SEVERE, "Invalid format %s [ImageFile::importImage]", pszFormat);
1395 ImageFile::skipSpacePPM (FILE* fp)
1398 while (isspace (c) || c == '#') {
1399 if (c == '#') { // comment until end of line
1401 while (c != 13 && c != 10)
1412 ImageFile::readImagePPM (const char* const pszFile)
1414 FILE* fp = fopen (pszFile, "r");
1415 if ((fp = fopen (pszFile, "r")) == NULL)
1417 char cSignature = toupper(fgetc(fp));
1418 if (cSignature != 'P') {
1422 cSignature = fgetc(fp);
1423 if (cSignature == '5' || cSignature == '6') { // binary modes
1425 fp = fopen(pszFile, "rb"); // reopen in binary mode
1428 } else if (cSignature != '2' && cSignature != '3') {
1433 int nRows, nCols, iMaxValue;
1435 if (fscanf (fp, "%d", &nCols) != 1) {
1440 if (fscanf (fp, "%d", &nRows) != 1) {
1445 if (fscanf (fp, "%d", &iMaxValue) != 1) {
1449 setArraySize (nRows, nCols);
1451 if (cSignature == '5' || cSignature == '6') { // binary modes
1455 if (c != 10) // read msdos 13-10 newline
1459 skipSpacePPM (fp); // ascii may have comments
1461 bool bMonochromeImage = false;
1462 double dMaxValue = iMaxValue;
1463 double dMaxValue3 = iMaxValue * 3;
1465 ImageFileArray v = getArray();
1466 for (int iy = nRows - 1; iy >= 0; iy--) {
1467 for (int ix = 0; ix < nCols; ix++) {
1468 int iGS, iR, iG, iB;
1470 switch (cSignature) {
1472 if (fscanf(fp, "%d ", &iGS) != 1) {
1476 v[ix][iy] = iGS / dMaxValue;
1484 v[ix][iy] = iGS / dMaxValue;
1487 if (fscanf (fp, "%d %d %d ", &iR, &iG, &iB) != 3) {
1491 if (ix == 0 && iy == 0 && (iR == iG && iG == iB))
1492 bMonochromeImage = true;
1493 if (bMonochromeImage)
1494 v[ix][iy] = (iR + iG + iB) / dMaxValue3;
1496 dR = iR / dMaxValue;
1497 dG = iG / dMaxValue;
1498 dB = iB / dMaxValue;
1499 v[ix][iy] = colorToGrayscale (dR, dG, dB);
1511 if (ix == 0 && iy == 0 && (iR == iG && iG == iB))
1512 bMonochromeImage = true;
1514 if (bMonochromeImage)
1515 v[ix][iy] = (iR + iG + iB) / dMaxValue3;
1517 dR = iR / dMaxValue;
1518 dG = iG / dMaxValue;
1519 dB = iB / dMaxValue;
1520 v[ix][iy] = colorToGrayscale (dR, dG, dB);
1533 ImageFile::readImagePNG (const char* const pszFile)
1535 FILE* fp = fopen(pszFile, "rb");
1538 unsigned char header[8];
1539 fread (header, 1, 8, fp);
1540 if (png_sig_cmp (header, 0, 8)) {
1545 png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1551 png_infop info_ptr = png_create_info_struct(png_ptr);
1553 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
1558 png_infop end_info = png_create_info_struct(png_ptr);
1560 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
1565 if (setjmp(png_ptr->jmpbuf)) {
1566 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1571 png_init_io(png_ptr, fp);
1572 png_set_sig_bytes(png_ptr, 8);
1573 png_read_info(png_ptr, info_ptr);
1575 int width = png_get_image_width (png_ptr, info_ptr);
1576 int height = png_get_image_height (png_ptr, info_ptr);
1577 int bit_depth = png_get_bit_depth (png_ptr, info_ptr);
1578 int color_type = png_get_color_type (png_ptr, info_ptr);
1580 if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8)
1581 png_set_expand(png_ptr);
1583 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
1584 png_set_expand(png_ptr);
1587 png_set_packing(png_ptr);
1589 if (color_type & PNG_COLOR_MASK_ALPHA)
1590 png_set_strip_alpha(png_ptr);
1592 if (bit_depth == 16)
1593 png_set_swap(png_ptr); // convert to little-endian format
1595 png_read_update_info(png_ptr, info_ptr); // update with transformations
1596 int rowbytes = png_get_rowbytes (png_ptr, info_ptr);
1597 bit_depth = png_get_bit_depth (png_ptr, info_ptr);
1598 color_type = png_get_color_type (png_ptr, info_ptr);
1600 png_bytep* row_pointers = new png_bytep [height];
1602 for (i = 0; i < height; i++)
1603 row_pointers[i] = new unsigned char [rowbytes];
1605 png_read_image(png_ptr, row_pointers);
1607 setArraySize (width, height);
1608 ImageFileArray v = getArray();
1609 for (int iy = 0; iy < height; iy++) {
1610 for (int ix = 0; ix < width; ix++) {
1612 if (color_type == PNG_COLOR_TYPE_GRAY) {
1614 dV = row_pointers[iy][ix] / 255.;
1615 else if (bit_depth == 16) {
1617 dV = (row_pointers[iy][iBase] + (row_pointers[iy][iBase+1] << 8)) / 65536.;
1619 } else if (color_type == PNG_COLOR_TYPE_RGB) {
1620 if (bit_depth == 8) {
1622 double dR = row_pointers[iy][iBase] / 255.;
1623 double dG = row_pointers[iy][iBase+1] / 255.;
1624 double dB = row_pointers[iy][iBase+2] / 255.;
1625 dV = colorToGrayscale (dR, dG, dR);
1628 v[ix][height-iy-1] = dV;
1632 png_read_end(png_ptr, end_info);
1633 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
1635 for (i = 0; i < height; i++)
1636 delete row_pointers[i];
1637 delete row_pointers;
1645 ImageFile::exportImage (const char* const pszFormat, const char* const pszFilename, int nxcell, int nycell, double densmin, double densmax)
1647 int iFormatID = convertExportFormatNameToID (pszFormat);
1649 if (iFormatID == EXPORT_FORMAT_PGM)
1650 return writeImagePGM (pszFilename, nxcell, nycell, densmin, densmax);
1651 else if (iFormatID == EXPORT_FORMAT_PGMASCII)
1652 return writeImagePGMASCII (pszFilename, nxcell, nycell, densmin, densmax);
1653 else if (iFormatID == EXPORT_FORMAT_TEXT)
1654 return writeImageText (pszFilename);
1656 else if (iFormatID == EXPORT_FORMAT_PNG)
1657 return writeImagePNG (pszFilename, 8, nxcell, nycell, densmin, densmax);
1658 else if (iFormatID == EXPORT_FORMAT_PNG16)
1659 return writeImagePNG (pszFilename, 16, nxcell, nycell, densmin, densmax);
1661 #ifdef HAVE_CTN_DICOM
1662 else if (iFormatID == EXPORT_FORMAT_DICOM) {
1663 DicomExporter dicomExport (this);
1664 bool bSuccess = dicomExport.writeFile (pszFilename);
1666 sys_error (ERR_SEVERE, dicomExport.failMessage().c_str());
1671 sys_error (ERR_SEVERE, "Invalid format %s [ImageFile::exportImage]", pszFormat);
1677 ImageFile::writeImagePGM (const char* const outfile, int nxcell, int nycell, double densmin, double densmax)
1682 ImageFileArray v = getArray();
1684 unsigned char* rowp = new unsigned char [nx * nxcell];
1686 if ((fp = fopen (outfile, "wb")) == NULL)
1689 fprintf(fp, "P5\n");
1690 fprintf(fp, "%d %d\n", nx, ny);
1691 fprintf(fp, "255\n");
1693 for (int irow = ny - 1; irow >= 0; irow--) {
1694 for (int icol = 0; icol < nx; icol++) {
1695 int pos = icol * nxcell;
1696 double dens = (v[icol][irow] - densmin) / (densmax - densmin);
1697 dens = clamp (dens, 0., 1.);
1698 for (int p = pos; p < pos + nxcell; p++) {
1699 rowp[p] = static_cast<unsigned int> (dens * 255.);
1702 for (int ir = 0; ir < nycell; ir++) {
1703 for (int ic = 0; ic < nx * nxcell; ic++)
1704 fputc( rowp[ic], fp );
1715 ImageFile::writeImagePGMASCII (const char* const outfile, int nxcell, int nycell, double densmin, double densmax)
1720 ImageFileArray v = getArray();
1722 unsigned char* rowp = new unsigned char [nx * nxcell];
1724 if ((fp = fopen (outfile, "wb")) == NULL)
1727 fprintf(fp, "P2\n");
1728 fprintf(fp, "%d %d\n", nx, ny);
1729 fprintf(fp, "255\n");
1731 for (int irow = ny - 1; irow >= 0; irow--) {
1732 for (int icol = 0; icol < nx; icol++) {
1733 int pos = icol * nxcell;
1734 double dens = (v[icol][irow] - densmin) / (densmax - densmin);
1735 dens = clamp (dens, 0., 1.);
1736 for (int p = pos; p < pos + nxcell; p++) {
1737 rowp[p] = static_cast<unsigned int> (dens * 255.);
1740 for (int ir = 0; ir < nycell; ir++) {
1741 for (int ic = 0; ic < nx * nxcell; ic++)
1742 fprintf(fp, "%d ", rowp[ic]);
1754 ImageFile::writeImageText (const char* const outfile)
1759 ImageFileArray v = getArray();
1760 ImageFileArray vImag = getImaginaryArray();
1762 if ((fp = fopen (outfile, "w")) == NULL)
1765 for (int irow = ny - 1; irow >= 0; irow--) {
1766 for (int icol = 0; icol < nx; icol++) {
1768 if (vImag[icol][irow] >= 0)
1769 fprintf (fp, "%.9g+%.9gi ", v[icol][irow], vImag[icol][irow]);
1771 fprintf (fp, "%.9g-%.9gi ", v[icol][irow], -vImag[icol][irow]);
1773 fprintf (fp, "%12.8g ", v[icol][irow]);
1786 ImageFile::writeImagePNG (const char* const outfile, int bitdepth, int nxcell, int nycell, double densmin, double densmax)
1788 double max_out_level = (1 << bitdepth) - 1;
1791 ImageFileArray v = getArray();
1793 unsigned char* rowp = new unsigned char [nx * nxcell * (bitdepth / 8)];
1795 FILE *fp = fopen (outfile, "wb");
1799 png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1803 png_infop info_ptr = png_create_info_struct (png_ptr);
1805 png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
1810 if (setjmp (png_ptr->jmpbuf)) {
1811 png_destroy_write_struct (&png_ptr, &info_ptr);
1816 png_init_io(png_ptr, fp);
1818 png_set_IHDR (png_ptr, info_ptr, nx * nxcell, ny * nycell, bitdepth, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1820 png_write_info(png_ptr, info_ptr);
1821 for (int irow = ny - 1; irow >= 0; irow--) {
1822 png_bytep row_pointer = rowp;
1824 for (int icol = 0; icol < nx; icol++) {
1825 int pos = icol * nxcell;
1826 double dens = (v[icol][irow] - densmin) / (densmax - densmin);
1827 dens = clamp (dens, 0., 1.);
1828 unsigned int outval = static_cast<unsigned int> (dens * max_out_level);
1830 for (int p = pos; p < pos + nxcell; p++) {
1835 rowp[rowpos+1] = (outval >> 8) & 0xFF;
1836 rowp[rowpos] = (outval & 0xFF);
1840 for (int ir = 0; ir < nycell; ir++)
1841 png_write_rows (png_ptr, &row_pointer, 1);
1844 png_write_end (png_ptr, info_ptr);
1845 png_destroy_write_struct (&png_ptr, &info_ptr);
1856 static const int N_GRAYSCALE=256;
1859 ImageFile::writeImageGIF (const char* const outfile, int nxcell, int nycell, double densmin, double densmax)
1861 int gs_indices[N_GRAYSCALE];
1864 ImageFileArray v = getArray();
1866 unsigned char* rowp = new unsigned char [nx * nxcell];
1868 gdImagePtr gif = gdImageCreate(nx * nxcell, ny * nycell);
1869 for (int i = 0; i < N_GRAYSCALE; i++)
1870 gs_indices[i] = gdImageColorAllocate(gif, i, i, i);
1872 int lastrow = ny * nycell - 1;
1873 for (int irow = 0; irow < ny; irow++) {
1874 int rpos = irow * nycell;
1875 for (int ir = rpos; ir < rpos + nycell; ir++) {
1876 for (int icol = 0; icol < nx; icol++) {
1877 int cpos = icol * nxcell;
1878 double dens = (v[icol][irow] - densmin) / (densmax - densmin);
1879 dens = clamp(dens, 0., 1.);
1880 for (int ic = cpos; ic < cpos + nxcell; ic++) {
1881 rowp[ic] = (unsigned int) (dens * (double) (N_GRAYSCALE - 1));
1882 gdImageSetPixel(gif, ic, lastrow - ir, gs_indices[rowp[ic]]);
1889 if ((out = fopen (outfile,"w")) == NULL) {
1890 sys_error(ERR_SEVERE, "Error opening output file %s for writing", outfile);
1893 gdImageGif(gif,out);
1895 gdImageDestroy(gif);