1 #include "AutoPanoSift.h"
2 
3 /* This is a replacement for the "GUIImage-Drawing.cs" */
4 /* the code is wrapping a libpano12 Image structure */
5 
DisplayImage_new0()6 DisplayImage* DisplayImage_new0() {
7 	DisplayImage* self = (DisplayImage*)malloc(sizeof(DisplayImage));
8 	self->data = NULL;
9 	return self;
10 }
11 
DisplayImage_new(char * filename)12 DisplayImage* DisplayImage_new(char* filename) {
13 	DisplayImage* self = DisplayImage_new0();
14 	fullPath filePath;
15 	if (StringtoFullPath(&filePath, filename) != 0) {
16 		FatalError("Syntax error: Not a valid pathname");
17 	}
18 #ifdef HAS_PANO13
19 	if ( panoImageRead(self, &filePath) == FALSE ) {
20 		FatalError("Syntax error: Not a valid image");
21 	}
22 #else
23 	if( readImage(self, &filePath) != 0) {
24 		FatalError("Syntax error: Not a valid image");
25 	}
26 #endif
27 
28 	return self;
29 }
30 
DisplayImage_delete(DisplayImage * self)31 void DisplayImage_delete(DisplayImage* self) {
32 	if (self) {
33 	    if (self->data) {
34 		myfree((void**)self->data);
35 		self->data = NULL;
36 	    }
37 	    free(self);
38 	}
39 }
40 
DisplayImage_ScaleSimple(DisplayImage * self,int width,int height)41 DisplayImage* DisplayImage_ScaleSimple(DisplayImage* self, int width, int height)
42 {
43 	DisplayImage* im = DisplayImage_new0();
44 	memcpy(im, self, sizeof(DisplayImage));
45 
46 	im->width = width;
47 	im->height = height;
48 	im->bytesPerLine = im->width * im->bitsPerPixel/8;
49 	im->dataSize = im->bytesPerLine * im->height;
50 	im->data = (unsigned char**) mymalloc( im->dataSize );
51 	if (im->data == NULL) {
52 		FatalError("out of memory!");
53 	}
54 	Image* src = self;
55 	Image* dest = im;
56 
57 
58 	/* modified copy from libpano12:filter.c:CopyImageData */
59 
60 	register unsigned char 	*in, *out;
61 	register int 			x,y, id, is, i;
62 	int						bpp_s, bpp_d;
63 	double sx, sy;
64 
65 	in 		= *(src->data);
66 	out 	= *(dest->data);
67 	sx		= (double)src->width / (double)dest->width;
68 	sy		= (double)src->height / (double)dest->height;
69 	bpp_s	= src->bitsPerPixel  / 8;
70 	bpp_d	= dest->bitsPerPixel / 8;
71 
72 	for( y = 0; y < dest->height; y++)
73 	{
74 		for( x = 0; x < dest->width; x++)
75 		{
76 			is = (int)(y * sy) * src->bytesPerLine  + bpp_s * (int)(x * sx);
77 			id = y        * dest->bytesPerLine + bpp_d * x;
78 
79 			if( (int)(y * sy) < 0 || (int)(y * sy) >= src->height ||
80 			    (int)(x * sx) < 0 || (int)(x * sx) >= src->width ) 	// outside src; set dest = 0
81 			{
82 				i = bpp_d;
83 				while( i-- > 0 ) out[ id++ ] = 0;
84 			}
85 			else 							// inside src; set dest = src
86 			{
87 				switch( bpp_d )
88 				{
89 				case 8: switch( bpp_s )
90 				{
91 				case 8:	memcpy( out + id, in + is, 8 );
92 					break;
93 				case 6: out[id++] = 255U; out[id++] = 255U;
94 					memcpy( out + id, in + is, 6 );
95 					break;
96 				case 4: out[id++] = in[ is++ ]; out[id++] = 0;
97 					out[id++] = in[ is++ ]; out[id++] = 0;
98 					out[id++] = in[ is++ ]; out[id++] = 0;
99 					out[id++] = in[ is++ ]; out[id++] = 0;
100 					break;
101 				case 3: out[id++] = 255U; out[id++] = 255U;
102 					out[id++] = in[ is++ ]; out[id++] = 0;
103 					out[id++] = in[ is++ ]; out[id++] = 0;
104 					out[id++] = in[ is++ ]; out[id++] = 0;
105 					break;
106 				}
107 					break;
108 				case 6:  switch( bpp_s )
109 				{
110 				case 8:	is += 2;
111 					memcpy( out + id, in + is, 6 );
112 					break;
113 				case 6: memcpy( out + id, in + is, 6 );
114 					break;
115 				case 4: is++;
116 					out[id++] = in[ is++ ]; out[id++] = 0;
117 					out[id++] = in[ is++ ]; out[id++] = 0;
118 					out[id++] = in[ is++ ]; out[id++] = 0;
119 					break;
120 				case 3: out[id++] = in[ is++ ]; out[id++] = 0;
121 					out[id++] = in[ is++ ]; out[id++] = 0;
122 					out[id++] = in[ is++ ]; out[id++] = 0;
123 					break;
124 				}
125 					break;
126 
127 				case 4:  switch( bpp_s )
128 				{
129 				case 8:	out[id++] = in[ is++ ]; is++;
130 					out[id++] = in[ is++ ]; is++;
131 					out[id++] = in[ is++ ]; is++;
132 					out[id++] = in[ is++ ]; is++;
133 					break;
134 				case 6: out[id++] = 255U;
135 					out[id++] = in[ is++ ]; is++;
136 					out[id++] = in[ is++ ]; is++;
137 					out[id++] = in[ is++ ]; is++;
138 					break;
139 				case 4: memcpy( out + id, in + is, 4 );
140 					break;
141 				case 3: out[id++] = 255U;
142 					memcpy( out + id, in + is, 3 );
143 					break;
144 				}
145 					break;
146 
147 				case 3:  switch( bpp_s )
148 				{
149 				case 8:	is+=2;
150 					out[id++] = in[ is++ ]; is++;
151 					out[id++] = in[ is++ ]; is++;
152 					out[id++] = in[ is++ ]; is++;
153 					break;
154 				case 6: out[id++] = in[ is++ ]; is++;
155 					out[id++] = in[ is++ ]; is++;
156 					out[id++] = in[ is++ ]; is++;
157 					break;
158 				case 4: is++;
159 					memcpy( out + id, in + is, 3 );
160 					break;
161 				case 3: memcpy( out + id, in + is, 3 );
162 					break;
163 				}
164 					break;
165 
166 				}
167 			}
168 		}
169 	}
170 
171 	return im;
172 }
173 
DisplayImage_ScaleWithin(DisplayImage * self,int dim)174 double DisplayImage_ScaleWithin(DisplayImage* self, int dim) {
175 
176 	if (self->width <= dim && self->height <= dim)
177 		return (1.0);
178 
179 	double xScale = ((double) dim / self->width);
180 	double yScale = ((double) dim / self->height);
181 	double smallestScale = xScale <= yScale ? xScale : yScale;
182 
183 	DisplayImage* scaled = DisplayImage_ScaleSimple (self,
184 							 (int) (self->width * smallestScale+0.0001),
185 							 (int) (self->height * smallestScale+0.0001));
186 
187 	if (self->data) {
188 		myfree((void**)self->data);
189 	}
190 	memmove(self, scaled, sizeof(DisplayImage));
191 	free(scaled);
192 
193 	return (smallestScale);
194 }
195 
DisplayImage_Carve(DisplayImage * self,int dx,int dy,int width,int height)196 DisplayImage* DisplayImage_Carve(DisplayImage* self, int dx, int dy, int width, int height)
197 {
198 	DisplayImage* result = DisplayImage_new0();
199 	memcpy(result, self, sizeof(DisplayImage));
200 
201 	result->width = width;
202 	result->height = height;
203 	result->bytesPerLine = result->width * result->bitsPerPixel/8;
204 	result->dataSize = result->bytesPerLine * result->height;
205 	result->data = (unsigned char**) mymalloc( result->dataSize );
206 	if (result->data == NULL) {
207 		FatalError("out of memory!");
208 	}
209 
210 	Image* src = self;
211 	Image* dest = result;
212 
213 	/* modified copy from libpano12:filter.c:CopyImageData */
214 	register unsigned char 	*in, *out;
215 	register int 			x,y, id, is, i;
216 	int						bpp_s, bpp_d;
217 
218 	in 		= *(src->data);
219 	out 	= *(dest->data);
220 	//dx		= (src->width  - dest->width)  / 2;
221 	//dy		= (src->height - dest->height) / 2;
222 	bpp_s	= src->bitsPerPixel  / 8;
223 	bpp_d	= dest->bitsPerPixel / 8;
224 
225 	for( y = 0; y < dest->height; y++)
226 	{
227 		for( x = 0; x < dest->width; x++)
228 		{
229 			is = (y + dy) * src->bytesPerLine  + bpp_s * (x + dx);
230 			id = y        * dest->bytesPerLine + bpp_d * x;
231 
232 			if( y + dy < 0 || y + dy >= src->height ||
233 			    x + dx < 0 || x + dx >= src->width ) 	// outside src; set dest = 0
234 			{
235 				i = bpp_d;
236 				while( i-- > 0 ) out[ id++ ] = 0;
237 			}
238 			else 						// inside src; set dest = src
239 			{
240 				switch( bpp_d )
241 				{
242 				case 8: switch( bpp_s )
243 				{
244 				case 8:	memcpy( out + id, in + is, 8 );
245 					break;
246 				case 6: out[id++] = 255U; out[id++] = 255U;
247 					memcpy( out + id, in + is, 6 );
248 					break;
249 				case 4: out[id++] = in[ is++ ]; out[id++] = 0;
250 					out[id++] = in[ is++ ]; out[id++] = 0;
251 					out[id++] = in[ is++ ]; out[id++] = 0;
252 					out[id++] = in[ is++ ]; out[id++] = 0;
253 					break;
254 				case 3: out[id++] = 255U; out[id++] = 255U;
255 					out[id++] = in[ is++ ]; out[id++] = 0;
256 					out[id++] = in[ is++ ]; out[id++] = 0;
257 					out[id++] = in[ is++ ]; out[id++] = 0;
258 					break;
259 				}
260 					break;
261 				case 6:  switch( bpp_s )
262 				{
263 				case 8:	is += 2;
264 					memcpy( out + id, in + is, 6 );
265 					break;
266 				case 6: memcpy( out + id, in + is, 6 );
267 					break;
268 				case 4: is++;
269 					out[id++] = in[ is++ ]; out[id++] = 0;
270 					out[id++] = in[ is++ ]; out[id++] = 0;
271 					out[id++] = in[ is++ ]; out[id++] = 0;
272 					break;
273 				case 3: out[id++] = in[ is++ ]; out[id++] = 0;
274 					out[id++] = in[ is++ ]; out[id++] = 0;
275 					out[id++] = in[ is++ ]; out[id++] = 0;
276 					break;
277 				}
278 					break;
279 
280 				case 4:  switch( bpp_s )
281 				{
282 				case 8:	out[id++] = in[ is++ ]; is++;
283 					out[id++] = in[ is++ ]; is++;
284 					out[id++] = in[ is++ ]; is++;
285 					out[id++] = in[ is++ ]; is++;
286 					break;
287 				case 6: out[id++] = 255U;
288 					out[id++] = in[ is++ ]; is++;
289 					out[id++] = in[ is++ ]; is++;
290 					out[id++] = in[ is++ ]; is++;
291 					break;
292 				case 4: memcpy( out + id, in + is, 4 );
293 					break;
294 				case 3: out[id++] = 255U;
295 					memcpy( out + id, in + is, 3 );
296 					break;
297 				}
298 					break;
299 
300 				case 3:  switch( bpp_s )
301 				{
302 				case 8:	is+=2;
303 					out[id++] = in[ is++ ]; is++;
304 					out[id++] = in[ is++ ]; is++;
305 					out[id++] = in[ is++ ]; is++;
306 					break;
307 				case 6: out[id++] = in[ is++ ]; is++;
308 					out[id++] = in[ is++ ]; is++;
309 					out[id++] = in[ is++ ]; is++;
310 					break;
311 				case 4: is++;
312 					memcpy( out + id, in + is, 3 );
313 					break;
314 				case 3: memcpy( out + id, in + is, 3 );
315 					break;
316 				}
317 					break;
318 
319 				}
320 			}
321 		}
322 	}
323 	return result;
324 }
325 
DisplayImage_ConvertToImageMap(DisplayImage * self)326 ImageMap* DisplayImage_ConvertToImageMap(DisplayImage* self)  //// dbl <= float
327 {
328 	ImageMap* result = ImageMap_new(self->width, self->height);
329 	if (self->bitsPerPixel == 32) {
330 	    LOOP_IMAGE(self,{
331 		    /* Data is (alpha,R,G,B) */
332 		    result->values[x][y] = (float)(((double)idata[1]+idata[2]+idata[3])/(255.0 * 3.0));
333 		});
334 	} else if (self->bitsPerPixel == 64) {
335 	    LOOP_IMAGE(self,{
336 		    unsigned short *udata=(unsigned short *)idata;
337 		    /* Data is (alpha,R,G,B) */
338 		    result->values[x][y] = (float)(((double)udata[1]+udata[2]+udata[3])/(65535 * 3.0));
339 		});
340 	} else {
341 	    /* It appears that TIFF library calls used (TIFFReadRGBA), will always return 32 or 64-bit, but just in case... */
342 	    FatalError("DisplayImage: Unsupported pixel size");
343 	}
344 	return result;
345 }
346