All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Public Types | Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes | Friends | List of all members
evd::PNGArena Class Reference

#include <PNGArena.h>

Public Types

enum  { kArenaSize = 4096, kBlockSize = 512, kTotBytes = MipMapOffset(1, kArenaSize)+4 }
 

Public Member Functions

 PNGArena (const std::string &name)
 
png_byteoperator() (int i, int x, int y, int c)
 
const png_byteoperator() (int i, int x, int y, int c) const
 
void WritePNGBytes (FILE *fout, int imgIdx, int dim)
 
png_byteNewBlock ()
 

Public Attributes

std::string name
 
int elemx
 
int elemy
 
int nviews
 
std::vector< std::unique_ptr
< std::array< png_byte,
kTotBytes > > > 
data
 

Protected Member Functions

void FillMipMaps (int d)
 

Protected Attributes

std::vector< std::mutex * > fMIPLocks
 
std::vector< bool > fHasMIP
 

Friends

class PNGView
 
void AnalyzeArena (const PNGArena &)
 

Detailed Description

Definition at line 22 of file PNGArena.h.

Member Enumeration Documentation

anonymous enum
Enumerator
kArenaSize 
kBlockSize 
kTotBytes 

Definition at line 28 of file PNGArena.h.

28  {
29  // Square because seems to be necessary for mipmapping. Larger than this
30  // doesn't seem to work in the browser.
31  kArenaSize = 4096,
32  // We have APAs with 480 and 1148 wires. This fits them in 1 and 3 blocks
33  // without being too wasteful.
34  kBlockSize = 512,
35  kTotBytes = MipMapOffset(1, kArenaSize)+4 // leave space for 1x1 as well
36  };
static constexpr int MipMapOffset(int dim, int maxdim)
Definition: PNGArena.h:16

Constructor & Destructor Documentation

evd::PNGArena::PNGArena ( const std::string &  name)

Definition at line 14 of file PNGArena.cxx.

14  : name(n), nviews(0)
15  {
16  }
std::string name
Definition: PNGArena.h:55

Member Function Documentation

void evd::PNGArena::FillMipMaps ( int  d)
protected

Definition at line 43 of file PNGArena.cxx.

44  {
45  png_byte* src = data[d]->data();
46  png_byte* dest = data[d]->data() + kArenaSize*kArenaSize*4;
47 
48  for(int newdim = kArenaSize/2; newdim >= 1; newdim /= 2){
49  const int olddim = newdim*2;
50 
51  // The alpha channel is set to twice the average of the source
52  // pixels. The intuition is that a linear feature should remain equally
53  // as bright, but would be expected to only hit 2 of the 4 source
54  // pixels. The colour channels are averaged, weighted by the alpha
55  // values.
56  for(int y = 0; y < newdim; ++y){
57  for(int x = 0; x < newdim; ++x){
58  int totc[3] = {0,};
59  int tota = 0;
60  for(int dy = 0; dy <= 1; ++dy){
61  for(int dx = 0; dx <= 1; ++dx){
62  const int i = (y*2+dy)*olddim + (x*2+dx);
63 
64  const png_byte va = src[i*4+3]; // alpha value
65  tota += va;
66 
67  for(int c = 0; c < 3; ++c){
68  const png_byte vc = src[i*4+c]; // colour value
69  totc[c] += vc * va;
70  } // end for c
71  } // end for dx
72  } // end for dy
73 
74  const int i = y*newdim+x;
75  for(int c = 0; c < 3; ++c) dest[i*4+c] = tota > 0 ? std::min(totc[c]/tota, 255) : 0;
76  dest[i*4+3] = std::min(tota/2, 255);
77  } // end for x
78  } // end for y
79 
80  src = dest;
81  dest += 4*newdim*newdim;
82  } // end for newdim
83  }
unsigned char png_byte
Definition: PNGArena.h:10
process_name opflash particleana ie x
std::vector< std::unique_ptr< std::array< png_byte, kTotBytes > > > data
Definition: PNGArena.h:59
process_name opflash particleana ie ie y
png_byte * evd::PNGArena::NewBlock ( )

Definition at line 19 of file PNGArena.cxx.

20  {
21  const int nfitx = kArenaSize/kBlockSize;
22  const int nfity = kArenaSize/kBlockSize;
23 
24  int ix = nviews%nfitx;
25  int iy = nviews/nfitx;
26 
27  if(data.empty() || iy >= nfity){
28  ix = 0;
29  iy = 0;
30  nviews = 0;
31  data.push_back(std::make_unique<std::array<png_byte, kTotBytes>>());
32  data.back()->fill(0);
33  fHasMIP.push_back(false);
34  fMIPLocks.push_back(new std::mutex);
35  }
36 
37  ++nviews;
38 
39  return &(*data.back())[(iy*kArenaSize + ix)*kBlockSize*4];
40  }
std::vector< std::unique_ptr< std::array< png_byte, kTotBytes > > > data
Definition: PNGArena.h:59
std::vector< bool > fHasMIP
Definition: PNGArena.h:65
std::vector< std::mutex * > fMIPLocks
Definition: PNGArena.h:64
png_byte& evd::PNGArena::operator() ( int  i,
int  x,
int  y,
int  c 
)
inline

Definition at line 40 of file PNGArena.h.

41  {
42  return (*data[i])[(y*kArenaSize+x)*4+c];
43  }
process_name opflash particleana ie x
std::vector< std::unique_ptr< std::array< png_byte, kTotBytes > > > data
Definition: PNGArena.h:59
process_name opflash particleana ie ie y
const png_byte& evd::PNGArena::operator() ( int  i,
int  x,
int  y,
int  c 
) const
inline

Definition at line 45 of file PNGArena.h.

46  {
47  return (*data[i])[(y*kArenaSize+x)*4+c];
48  }
process_name opflash particleana ie x
std::vector< std::unique_ptr< std::array< png_byte, kTotBytes > > > data
Definition: PNGArena.h:59
process_name opflash particleana ie ie y
void evd::PNGArena::WritePNGBytes ( FILE *  fout,
int  imgIdx,
int  dim 
)

Definition at line 108 of file PNGArena.cxx.

109  {
110  if(imgIdx >= int(data.size())){
111  std::cout << "Bad index " << imgIdx << std::endl;
112  return; // TODO return 404 instead
113  }
114 
115  if(dim != kArenaSize){ // might need MIPMaps generated
116  std::lock_guard<std::mutex> guard(*fMIPLocks[imgIdx]);
117  if(!fHasMIP[imgIdx]){
118  FillMipMaps(imgIdx);
119  fHasMIP[imgIdx] = true;
120  }
121  }
122 
123  // Figure out offset
124  png_byte* src = &(*data[imgIdx])[MipMapOffset(dim, kArenaSize)];
125 
126  if(src + 4*dim*dim - 1 > &(*data[imgIdx]).back()){ // would run off end of data
127  std::cout << "Bad mipmap size " << dim << std::endl;
128  return; // TODO return 404 instead
129  }
130 
131  png_struct_def* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
132 
133  auto info_ptr = png_create_info_struct(png_ptr);
134 
135  // I'm trying to optimize the compression speed, without blowing the file
136  // size up. It's far from clear these are the best parameters, but they do
137  // seem to be an improvement on the defaults.
138  png_set_compression_level(png_ptr, 1);
139  png_set_compression_strategy(png_ptr, Z_RLE);
140 
141  png_set_IHDR(png_ptr, info_ptr, dim, dim,
142  8/*bit_depth*/, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
143  PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
144 
145  std::vector<png_byte*> pdatas(dim);
146  for(int i = 0; i < dim; ++i) pdatas[i] = src + i*dim*4;
147 
148  png_set_rows(png_ptr, info_ptr, pdatas.data());
149 
150  // This works fine until libpng throws a fatal error when the browser hangs
151  // up
152  // png_init_io(png_ptr, fout);
153 
154  // So set our own write function that does the same thing but ignores
155  // errors
156  png_set_write_fn(png_ptr, fout, webevd_png_write_fn, webevd_png_flush_fn);
157 
158  png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
159 
160  png_destroy_write_struct(&png_ptr, &info_ptr);
161  }
void webevd_png_write_fn(png_struct_def *png_ptr, png_byte *buffer, long unsigned int nbytes)
Definition: PNGArena.cxx:88
unsigned char png_byte
Definition: PNGArena.h:10
void webevd_png_flush_fn(png_struct_def *png_ptr)
Definition: PNGArena.cxx:102
std::vector< std::unique_ptr< std::array< png_byte, kTotBytes > > > data
Definition: PNGArena.h:59
static constexpr int MipMapOffset(int dim, int maxdim)
Definition: PNGArena.h:16
void FillMipMaps(int d)
Definition: PNGArena.cxx:43
std::vector< bool > fHasMIP
Definition: PNGArena.h:65
std::vector< std::mutex * > fMIPLocks
Definition: PNGArena.h:64
BEGIN_PROLOG could also be cout

Friends And Related Function Documentation

void AnalyzeArena ( const PNGArena )
friend

Definition at line 169 of file PNGArena.cxx.

170  {
171  for(int blockSize = 1; blockSize <= PNGArena::kArenaSize; blockSize *= 2){
172  long nfilled = 0;
173  for(unsigned int d = 0; d < bytes.data.size(); ++d){
174  for(int iy = 0; iy < PNGArena::kArenaSize/blockSize; ++iy){
175  for(int ix = 0; ix < PNGArena::kArenaSize/blockSize; ++ix){
176  bool filled = false;
177  for(int y = 0; y < blockSize && !filled; ++y){
178  for(int x = 0; x < blockSize; ++x){
179  if(bytes(d, ix*blockSize+x, iy*blockSize+y, 3) > 0){
180  filled = true;
181  break;
182  }
183  }
184  } // end for y
185  if(filled) ++nfilled;
186  }
187  }
188  }
189 
190  std::cout << "With block size = " << blockSize << " " << double(nfilled)/((PNGArena::kArenaSize*PNGArena::kArenaSize)/(blockSize*blockSize)*bytes.data.size()) << " of the blocks are filled" << std::endl;
191  }
192  }
process_name opflash particleana ie x
process_name opflash particleana ie ie y
byte bytes
Alias for common language habits.
Definition: datasize.h:101
BEGIN_PROLOG could also be cout
friend class PNGView
friend

Definition at line 25 of file PNGArena.h.

Member Data Documentation

std::vector<std::unique_ptr<std::array<png_byte, kTotBytes> > > evd::PNGArena::data

Definition at line 59 of file PNGArena.h.

int evd::PNGArena::elemx

Definition at line 56 of file PNGArena.h.

int evd::PNGArena::elemy

Definition at line 56 of file PNGArena.h.

std::vector<bool> evd::PNGArena::fHasMIP
protected

Definition at line 65 of file PNGArena.h.

std::vector<std::mutex*> evd::PNGArena::fMIPLocks
protected

Definition at line 64 of file PNGArena.h.

std::string evd::PNGArena::name

Definition at line 55 of file PNGArena.h.

int evd::PNGArena::nviews

Definition at line 57 of file PNGArena.h.


The documentation for this class was generated from the following files: