PngWriter.cc 4.6 KB
Newer Older
1 2 3 4 5 6 7
/******************************************************************************
 *
 * AMDiS - Adaptive multidimensional simulations
 *
 * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
 * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
 *
8
 * Authors:
9 10 11 12 13 14 15 16 17
 * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *
 * This file is part of AMDiS
 *
 * See also license.opensource.txt in the distribution.
18
 *
19
 ******************************************************************************/
20 21


22
#if defined HAVE_PNG
23

24 25 26
#include <float.h>
#include <png.h>

27
#include "PngWriter.h"
28 29
#include "Traverse.h"
#include "DOFVector.h"
30
#include "DataCollector.h"
31

32
namespace AMDiS { namespace io {
33 34

  int PngWriter::writeFile(std::string filename, int imageType)
35
  {
36
    FUNCNAME("PngWriter::writeFile()");
37

38 39
    double minX = DBL_MAX, minY = DBL_MAX;
    double maxX = DBL_MIN, maxY = DBL_MIN;
40

41
    TraverseStack stack;
42
    ElInfo *elInfo = stack.traverseFirst(dataCollector->getMesh(), -1,
43
					 Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS);
44 45
    double pointdist = std::min(absteukl(elInfo->getCoord(0), elInfo->getCoord(1)),
			   std::min(absteukl(elInfo->getCoord(1), elInfo->getCoord(2)),
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
			       absteukl(elInfo->getCoord(2), elInfo->getCoord(0))));
    while (elInfo) {
      for (int i = 0; i < 3; i++) {
	double x = (elInfo->getCoord(i))[0];
	double y = (elInfo->getCoord(i))[1];
	if (x < minX) minX = x;
	if (x > maxX) maxX = x;
	if (y < minY) minY = y;
	if (y > maxY) maxY = y;
      }

      elInfo = stack.traverseNext(elInfo);
    }

    TEST_EXIT(minX == 0.0 && minY == 0.0)("Only supported for minX = minY = 0.0!\n");
    TEST_EXIT(pointdist > 0.0)("This should not happen!\n");

    int imageX = static_cast<int>(maxX / pointdist) + 1;
    int imageY = static_cast<int>(maxY / pointdist) + 1;

66 67
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
						  NULL, NULL, NULL);
68 69 70
    if (!png_ptr)
      return 0;

71
    png_bytep* rowPointers = new png_bytep[imageY];
72
    for (int i = 0; i < imageY; i++) {
73 74 75
//       rowPointers[i] = (png_byte*)png_malloc(png_ptr,
// 					     (imageType == 0 ? imageX : imageX * 3));
      rowPointers[i] = (png_byte*)malloc(sizeof(png_byte) * imageX * 3);
76
    }
77

78
    const BasisFunction* basisFcts = dataCollector->getFeSpace()->getBasisFcts();
79
    std::vector<DegreeOfFreedom> localDofs(3);
80 81 82 83 84
    DOFVector<double>* dofvalues = dataCollector->getValues();

    elInfo = stack.traverseFirst(dataCollector->getMesh(), -1,
				 Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS);
    while (elInfo) {
85
      basisFcts->getLocalIndices(elInfo->getElement(),
86
				 dataCollector->getFeSpace()->getAdmin(),
87
				 localDofs);
88 89 90 91 92

      for (int i = 0; i < 3; i++) {
	if (imageType == 0) {
	  int indexX = static_cast<int>((elInfo->getCoord(i))[0] / pointdist);
	  int indexY = static_cast<int>((elInfo->getCoord(i))[1] / pointdist);
93
	  rowPointers[indexY][indexX] =
94 95
	    static_cast<unsigned char>((*dofvalues)[localDofs[i]]);
	} else {
96
	  int indexX = static_cast<int>((elInfo->getCoord(i))[0] / pointdist);
97
	  int indexY = static_cast<int>((elInfo->getCoord(i))[1] / pointdist);
98

99 100 101
	  TEST_EXIT(indexX >= 0 && indexX < imageX)("X-index out of range!");
	  TEST_EXIT(indexY >= 0 && indexY < imageY)("Y-index out of range!");

102 103 104 105 106
	  int value = static_cast<int>((*dofvalues)[localDofs[i]]);

 	  unsigned char r = value % 256;
 	  unsigned char g = (value - r % (256 * 256)) / 256;
 	  unsigned char b = (value - r - g) / (256 * 256);
107 108 109
	  rowPointers[indexY][indexX * 3] = r;
	  rowPointers[indexY][indexX * 3 + 1] = g;
	  rowPointers[indexY][indexX * 3 + 2] = b;
110
	}
111

Thomas Witkowski's avatar
Thomas Witkowski committed
112
	}
113 114

      elInfo = stack.traverseNext(elInfo);
115
    }
116 117 118 119 120 121 122

    FILE *fp = fopen(filename.c_str(), "wb");
    TEST_EXIT(fp)("Cannot open file for writing matrix picture file!\n");

    png_infop info_ptr = png_create_info_struct(png_ptr);

    if (!info_ptr) {
123
       png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
124 125 126
       return 0;
    }

127 128 129 130
    if (setjmp(png_jmpbuf(png_ptr))) {
      return 0;
    }

131 132 133 134 135 136 137 138 139 140
    png_init_io(png_ptr, fp);

    png_set_IHDR(png_ptr, info_ptr, imageX, imageY, 8,
		 (imageType == 0 ? PNG_COLOR_TYPE_GRAY : PNG_COLOR_TYPE_RGB),
		 PNG_INTERLACE_NONE,
		 PNG_COMPRESSION_TYPE_DEFAULT,
		 PNG_FILTER_TYPE_DEFAULT);

    png_set_rows(png_ptr, info_ptr, rowPointers);

141
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL);
142 143 144

    png_destroy_write_struct(&png_ptr, &info_ptr);

145
    fclose(fp);
146

147
    delete [] rowPointers;
148
    return 0;
149
  }
150

151
} } // end namespace io, AMDiS
152 153

#endif