1 /*
2 Copyright 2007 nVidia, Inc.
3 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
4
5 You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
8 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
10 See the License for the specific language governing permissions and limitations under the License.
11 */
12
13 // the zoh compressor and decompressor
14
15 #include "tile.h"
16 #include "zoh.h"
17
18 #include <string.h> // memcpy
19
20 using namespace ZOH;
21
22
isone(const char * block)23 bool ZOH::isone(const char *block)
24 {
25 char code = block[0] & 0x1F;
26
27 return (code == 0x03 || code == 0x07 || code == 0x0b || code == 0x0f);
28 }
29
compress(const Tile & t,char * block)30 void ZOH::compress(const Tile &t, char *block)
31 {
32 char oneblock[ZOH::BLOCKSIZE], twoblock[ZOH::BLOCKSIZE];
33
34 float mseone = ZOH::compressone(t, oneblock);
35 float msetwo = ZOH::compresstwo(t, twoblock);
36
37 if (mseone <= msetwo)
38 memcpy(block, oneblock, ZOH::BLOCKSIZE);
39 else
40 memcpy(block, twoblock, ZOH::BLOCKSIZE);
41 }
42
decompress(const char * block,Tile & t)43 void ZOH::decompress(const char *block, Tile &t)
44 {
45 if (ZOH::isone(block))
46 ZOH::decompressone(block, t);
47 else
48 ZOH::decompresstwo(block, t);
49 }
50
51 /*
52 void ZOH::compress(string inf, string zohf)
53 {
54 Array2D<Rgba> pixels;
55 int w, h;
56 char block[ZOH::BLOCKSIZE];
57
58 Exr::readRgba(inf, pixels, w, h);
59 FILE *zohfile = fopen(zohf.c_str(), "wb");
60 if (zohfile == NULL) throw "Unable to open .zoh file for write";
61
62 // stuff for progress bar O.o
63 int ntiles = ((h+Tile::TILE_H-1)/Tile::TILE_H)*((w+Tile::TILE_W-1)/Tile::TILE_W);
64 int tilecnt = 0;
65 int ndots = 25;
66 int dotcnt = 0;
67 printf("Progress [");
68 for (int i=0; i<ndots;++i) printf(" ");
69 printf("]\rProgress ["); fflush(stdout);
70
71 // convert to tiles and compress each tile
72 for (int y=0; y<h; y+=Tile::TILE_H)
73 {
74 int ysize = min(Tile::TILE_H, h-y);
75 for (int x=0; x<w; x+=Tile::TILE_W)
76 {
77 int xsize = min(Tile::TILE_W, w-x);
78 Tile t(xsize, ysize);
79
80 t.insert(pixels, x, y);
81
82 ZOH::compress(t, block);
83 if (fwrite(block, sizeof(char), ZOH::BLOCKSIZE, zohfile) != ZOH::BLOCKSIZE)
84 throw "File error on write";
85
86 // progress bar
87 ++tilecnt;
88 if (tilecnt > (ntiles * dotcnt)/ndots) { printf("."); fflush(stdout); ++dotcnt; }
89 }
90 }
91
92 printf("]\n"); // advance to next line finally
93
94 if (fclose(zohfile)) throw "Close failed on .zoh file";
95 }
96
97 static int str2int(std::string s)
98 {
99 int thing;
100 std::stringstream str (stringstream::in | stringstream::out);
101 str << s;
102 str >> thing;
103 return thing;
104 }
105
106 // zoh file name is ...-w-h.zoh, extract width and height
107 static void extract(string zohf, int &w, int &h)
108 {
109 size_t n = zohf.rfind('.', zohf.length()-1);
110 size_t n1 = zohf.rfind('-', n-1);
111 size_t n2 = zohf.rfind('-', n1-1);
112 string width = zohf.substr(n2+1, n1-n2-1);
113 w = str2int(width);
114 string height = zohf.substr(n1+1, n-n1-1);
115 h = str2int(height);
116 }
117
118 static int mode_to_prec[] = {
119 10,7,11,10,
120 10,7,11,11,
121 10,7,11,12,
122 10,7,9,16,
123 10,7,8,-1,
124 10,7,8,-1,
125 10,7,8,-1,
126 10,7,6,-1,
127 };
128
129 static int shapeindexhist[32], modehist[32], prechistone[16], prechisttwo[16], oneregion, tworegions;
130
131 static void stats(char block[ZOH::BLOCKSIZE])
132 {
133 char mode = block[0] & 0x1F; if ((mode & 0x3) == 0) mode = 0; if ((mode & 0x3) == 1) mode = 1; modehist[mode]++;
134 int prec = mode_to_prec[mode];
135 nvAssert (prec != -1);
136 if (!ZOH::isone(block))
137 {
138 tworegions++;
139 prechisttwo[prec]++;
140 int shapeindex = ((block[0] & 0xe0) >> 5) | ((block[1] & 0x3) << 3);
141 shapeindexhist[shapeindex]++;
142 }
143 else
144 {
145 oneregion++;
146 prechistone[prec]++;
147 }
148 }
149
150 static void printstats()
151 {
152 printf("\nPrecision histogram 10b to 16b one region: "); for (int i=10; i<=16; ++i) printf("%d,", prechistone[i]);
153 printf("\nPrecision histogram 6b to 11b two regions: "); for (int i=6; i<=11; ++i) printf("%d,", prechisttwo[i]);
154 printf("\nMode histogram: "); for (int i=0; i<32; ++i) printf("%d,", modehist[i]);
155 printf("\nShape index histogram: "); for (int i=0; i<32; ++i) printf("%d,", shapeindexhist[i]);
156 printf("\nOne region %5.2f%% Two regions %5.2f%%", 100.0*oneregion/float(oneregion+tworegions), 100.0*tworegions/float(oneregion+tworegions));
157 printf("\n");
158 }
159
160 void ZOH::decompress(string zohf, string outf)
161 {
162 Array2D<Rgba> pixels;
163 int w, h;
164 char block[ZOH::BLOCKSIZE];
165
166 extract(zohf, w, h);
167 FILE *zohfile = fopen(zohf.c_str(), "rb");
168 if (zohfile == NULL) throw "Unable to open .zoh file for read";
169 pixels.resizeErase(h, w);
170
171 // convert to tiles and decompress each tile
172 for (int y=0; y<h; y+=Tile::TILE_H)
173 {
174 int ysize = min(Tile::TILE_H, h-y);
175 for (int x=0; x<w; x+=Tile::TILE_W)
176 {
177 int xsize = min(Tile::TILE_W, w-x);
178 Tile t(xsize, ysize);
179
180 if (fread(block, sizeof(char), ZOH::BLOCKSIZE, zohfile) != ZOH::BLOCKSIZE)
181 throw "File error on read";
182
183 stats(block); // collect statistics
184
185 ZOH::decompress(block, t);
186
187 t.extract(pixels, x, y);
188 }
189 }
190 if (fclose(zohfile)) throw "Close failed on .zoh file";
191 Exr::writeRgba(outf, pixels, w, h);
192
193 #ifndef EXTERNAL_RELEASE
194 printstats(); // print statistics
195 #endif
196 }
197 */
198