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