Download code

Jump to: navigation, search

Back to Image_downsampling_(C)

Download for Windows: zip

Download for UNIX: zip, tar.gz, tar.bz2

ImageTest.c

  1 /* The authors of this work have released all rights to it and placed it
  2 in the public domain under the Creative Commons CC0 1.0 waiver
  3 (http://creativecommons.org/publicdomain/zero/1.0/).
  4 
  5 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  6 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  7 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  8 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  9 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 10 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 11 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 12 
 13 Retrieved from: http://en.literateprograms.org/Image_downsampling_(C)?oldid=18185
 14 */
 15 
 16 #include <stdio.h>
 17 #include <stdlib.h>
 18 #include <SDL/SDL.h>
 19 #include <SDL/SDL_image.h>
 20 #include "DownScale.h"
 21 
 22 #define WINW    500
 23 #define WINH    500
 24 
 25 int main(int nb, char * argv[])
 26 {
 27 	if (SDL_Init(SDL_INIT_VIDEO) < 0)
 28 		return 1;
 29 
 30 	IMG_Init(IMG_INIT_PNG|IMG_INIT_JPG);
 31 	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
 32 
 33 	atexit(SDL_Quit);
 34 
 35 	SDL_Surface * screen = SDL_SetVideoMode(WINW, WINH, 32, SDL_HWSURFACE|SDL_ANYFORMAT);
 36 	if (! screen) return 1;
 37 
 38 	SDL_WM_SetCaption("Image down sampling", NULL);
 39 
 40 	char * file = nb > 1 ? argv[1] : "Rings1_small.png";
 41 	SDL_Surface * img = IMG_Load(file);
 42 
 43 	if (img == NULL) { perror(file); return 1; }
 44 
 45 	struct Image_t source = {
 46 		.bitmap = img->pixels, .stride = img->pitch, .width = img->w, .height = img->h,
 47 		.bpp = img->format->BytesPerPixel
 48 	};
 49 	int w = 300;
 50 	SDL_Surface * tmp = NULL;
 51 
 52 	memset(screen->pixels, 0xff, screen->pitch * screen->h);
 53 	SDL_Rect rect = {.x = (screen->w - img->w) >> 1, .y = (screen->h - img->h) >> 1};
 54 	SDL_BlitSurface(img, NULL, screen, &rect);
 55 	SDL_UpdateRect(screen, 0, 0, 0, 0);
 56 
 57 	while (1)
 58 	{
 59 		SDL_Event event;
 60 		while (SDL_WaitEvent(&event))
 61 		{
 62 			int inc = 0;
 63 			switch (event.type) {
 64 			case SDL_QUIT: return 0;
 65 			case SDL_KEYDOWN:
 66 				switch (event.key.keysym.sym) {
 67 				case SDLK_ESCAPE: return 0;
 68 				case SDLK_LEFT: case SDLK_UP: inc = -2; break;
 69 				case SDLK_RIGHT: case SDLK_DOWN: inc = 2; break;
 70 				default: continue;
 71 				}
 72 				if (inc)
 73 				{
 74 					w += inc;
 75 					if (w > img->w) { w = img->w; continue; }
 76 					if (w < 1) { w = 1; continue; }
 77 					int h = w * img->h / img->w;
 78 					h /= 2;
 79 					if (h < 1) h = 1;
 80 
 81 //					fprintf(stderr, "new dimension = %dx%d\n", w, h);
 82 
 83 					if (w != img->w && h != img->h)
 84 					{
 85 						/* Cannot use ImageReduce() directly on screen: pixel format differs */
 86 						tmp = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, img->format->BitsPerPixel,
 87 							img->format->Rmask, img->format->Gmask, img->format->Bmask, img->format->Amask);
 88 
 89 						struct Image_t dest = {
 90 							.bitmap = tmp->pixels, .stride = tmp->pitch, .width = tmp->w, .height = tmp->h,
 91 							.bpp = tmp->format->BytesPerPixel
 92 						};
 93 
 94 						ImageDownScale(&source, &dest);
 95 					}
 96 					else tmp = img;
 97 
 98 					SDL_Palette * old = tmp->format->palette;
 99 					tmp->format->palette = img->format->palette;
100 					memset(screen->pixels, 0xff, screen->pitch * screen->h);
101 					rect.x = (screen->w - tmp->w) >> 1;
102 					rect.y = (screen->h - tmp->h) >> 1;
103 					SDL_BlitSurface(tmp, NULL, screen, &rect);
104 					SDL_UpdateRect(screen, 0, 0, 0, 0);
105 					tmp->format->palette = old;
106 					if (tmp != img) SDL_FreeSurface(tmp);
107 				}
108 			}
109 		}
110 	}
111 	return 0;
112 }
113 
114 #ifdef WIN32
115 #include <windows.h>
116 int WINAPI WinMain (HINSTANCE instance,
117                     HINSTANCE previnst,
118                     LPSTR args,
119                     int wndState)
120 {
121 	return main(0, NULL);
122 }
123 #endif


hijacker
hijacker
hijacker
hijacker

DownScale.h

 1 /* The authors of this work have released all rights to it and placed it
 2 in the public domain under the Creative Commons CC0 1.0 waiver
 3 (http://creativecommons.org/publicdomain/zero/1.0/).
 4 
 5 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 6 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 7 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 8 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 9 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
10 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
11 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 
13 Retrieved from: http://en.literateprograms.org/Image_downsampling_(C)?oldid=18185
14 */
15 
16 
17 #ifndef DOWN_SAMPLE_H
18 #define DOWN_SAMPLE_H
19 
20 typedef uint8_t *                DATA8;
21 typedef uint16_t *               DATA16;
22 typedef uint32_t *               DATA32;
23 typedef struct Image_t *         Image;
24 
25 struct Image_t
26 {
27 	int   width, height, bpp;
28 	int   stride, format;
29 	DATA8 bitmap;
30 };
31 
32 Image ImageDownScale(Image source, Image ret);
33 #endif
34 


hijacker
hijacker
hijacker
hijacker

build.log

 1 /tmp/litprog4834448/ImageTest.c:18:21: fatal error: SDL/SDL.h: No such file or directory
 2 compilation terminated.
 3 In file included from /tmp/litprog4834448/Resize.c:20:0:
 4 /tmp/litprog4834448/DownScale.h:20:1: error: unknown type name 'uint8_t'
 5 /tmp/litprog4834448/DownScale.h:21:1: error: unknown type name 'uint16_t'
 6 /tmp/litprog4834448/DownScale.h:22:1: error: unknown type name 'uint32_t'
 7 /tmp/litprog4834448/Resize.c:22:21: error: unknown type name 'Iter'
 8 /tmp/litprog4834448/Resize.c:39:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
 9 /tmp/litprog4834448/Resize.c:51:5: error: conflicting types for 'ImageDownScale'
10 /tmp/litprog4834448/DownScale.h:32:7: note: previous declaration of 'ImageDownScale' was here
11 /tmp/litprog4834448/Resize.c: In function 'ImageDownScale':
12 /tmp/litprog4834448/Resize.c:58:5: error: unknown type name 'Iter'
13 /tmp/litprog4834448/Resize.c:77:40: error: request for member 'err' in something not a structure or union
14 /tmp/litprog4834448/Resize.c:78:5: warning: implicit declaration of function 'InitDDA' [-Wimplicit-function-declaration]
15 /tmp/litprog4834448/Resize.c:79:53: error: request for member 'dx' in something not a structure or union
16 /tmp/litprog4834448/Resize.c:81:16: error: request for member 'x' in something not a structure or union
17 /tmp/litprog4834448/Resize.c:81:25: error: request for member 'xe' in something not a structure or union
18 /tmp/litprog4834448/Resize.c:87:9: warning: implicit declaration of function 'IterDDA' [-Wimplicit-function-declaration]
19 /tmp/litprog4834448/Resize.c:88:21: error: request for member 'xe' in something not a structure or union
20 /tmp/litprog4834448/Resize.c:88:31: error: request for member 'err' in something not a structure or union
21 /tmp/litprog4834448/Resize.c:88:52: error: request for member 'xe' in something not a structure or union
22 /tmp/litprog4834448/Resize.c:90:24: error: request for member 'y' in something not a structure or union
23 /tmp/litprog4834448/Resize.c:97:31: error: request for member 'xe' in something not a structure or union
24 /tmp/litprog4834448/Resize.c:97:52: error: request for member 'dx' in something not a structure or union
25 /tmp/litprog4834448/Resize.c:103:29: error: request for member 'y' in something not a structure or union
26 /tmp/litprog4834448/Resize.c:113:35: error: request for member 'y' in something not a structure or union
27 /tmp/litprog4834448/Resize.c:144:29: error: request for member 'y' in something not a structure or union
28 /tmp/litprog4834448/Resize.c:154:35: error: request for member 'y' in something not a structure or union


hijacker
hijacker
hijacker
hijacker

Resize.c

  1 /* The authors of this work have released all rights to it and placed it
  2 in the public domain under the Creative Commons CC0 1.0 waiver
  3 (http://creativecommons.org/publicdomain/zero/1.0/).
  4 
  5 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  6 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  7 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  8 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  9 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 10 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 11 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 12 
 13 Retrieved from: http://en.literateprograms.org/Image_downsampling_(C)?oldid=18185
 14 */
 15 
 16 #include <stdio.h>
 17 #include <stdlib.h>
 18 #include <string.h>
 19 #include <malloc.h>
 20 #include "DownScale.h"
 21 
 22 static void InitDDA(Iter * iter, int xs, int xe, int ys, int ye)
 23 {
 24 	/* Pre-condition: xe > xs >= 0 */
 25 	div_t q = div(iter->dy = ye - ys, xe);
 26 	iter->y   = ys;
 27 	iter->ye  = ye;
 28 	iter->x   = xs;
 29 	iter->xe  = xe;
 30 	iter->err = xe;
 31 	iter->dx  = abs(q.rem);
 32 	iter->sx  = q.quot;
 33 	iter->sy  = (ys < ye ? 1 : -1);
 34 	if (xs > 0)
 35 		iter->y   = ye-(iter->dy * (xe-xs) + iter->sy * iter->err)/xe,
 36 		iter->err = (iter->err-iter->dx*xs) % xe + xe;
 37 }
 38 
 39 static inline void IterDDA(Iter * iter)
 40 {
 41 	iter->x ++;
 42 	iter->y += iter->sx;
 43 	iter->err -= iter->dx;
 44 	if (iter->err <= 0)
 45 		iter->y += iter->sy, iter->err += iter->xe;
 46 }
 47 
 48 #define	BITS         8
 49 #define	VALUES       (1 @<< BITS)
 50 
 51 int ImageDownScale(Image src, Image ret)
 52 {
 53     DATA32 sum;
 54     int    i, y, w, h, chan, sz, surf, xerr;
 55 
 56     DATA8 out = ret->bitmap;
 57     DATA8 in  = src->bitmap;
 58     Iter  ypos, xpos, nerr;
 59 
 60     sz = src->width * src->bpp;
 61     if (ret->width == 0 || ret->height == 0) return 0;
 62     if (ret->width > src->width || ret->height > src->height) return 0;
 63     if (ret->width == src->width && ret->height == src->height) {
 64         for (y = ret->height; y > 0; y --, in += src->stride, out += ret->stride)
 65             memcpy(out, in, sz);
 66         return 1;
 67     }
 68 
 69     w    = ret->width;
 70     h    = ret->height;
 71     chan = src->bpp;
 72     sum  = calloc(sz, sizeof *sum);
 73     surf = (unsigned long long) src->width * src->height * VALUES / (w * h);
 74     y    = 0;
 75 
 76     if (sum == NULL) return 0;
 77     memset(&nerr, 0, sizeof nerr); nerr.err = 1;
 78     InitDDA(&ypos, 0, h, 0, src->height);
 79     InitDDA(&xpos, 0, w, 0, src->width); xerr = xpos.dx > 0;
 80 
 81     while (ypos.x < ypos.xe)
 82     {
 83         DATA8 d = out, p;
 84         int x, yerr;
 85         int total[4], tmp;
 86         DATA32 s;
 87         IterDDA(&ypos);
 88         yerr = (ypos.xe - ypos.err) * VALUES / ypos.xe;
 89 
 90         while (y < ypos.y)
 91         {
 92             for (p = in, i = sz, s = sum; i > 0; *s++ += (*p<<BITS), p++, i --);
 93             y ++; in += src->stride;
 94         }
 95 
 96         InitDDA(&xpos, 0, w, 0, src->width); x = 0;      IterDDA(&xpos);
 97         InitDDA(&nerr, 0, xpos.xe, 0, VALUES * xpos.dx); IterDDA(&nerr);
 98         memset(total, 0, sizeof total);
 99         if (yerr > 0)
100         {
101             #define MAX_255(ptr, val) { int z = val; *ptr = (z >= 255 ? 255 : z); ptr ++; }
102             for (p = in, i = ret->width, s = sum; i > 0; ) {
103                 if (x < xpos.y) {
104                     /* Vertical error compensation */
105                     switch (chan) {
106                     case 4: tmp = *p * yerr; total[3] += tmp + *s; *s = (*p<<BITS) - tmp; s ++; p ++;
107                     case 3: tmp = *p * yerr; total[2] += tmp + *s; *s = (*p<<BITS) - tmp; s ++; p ++;
108                             tmp = *p * yerr; total[1] += tmp + *s; *s = (*p<<BITS) - tmp; s ++; p ++;
109                     case 1: tmp = *p * yerr; total[0] += tmp + *s; *s = (*p<<BITS) - tmp; s ++; p ++;
110                     }
111                     x ++;
112                 } else {
113                     int err = nerr.y & (VALUES-1);
114                     if (xerr == 0 || err == 0) {
115                         switch (chan) {
116                         case 4: MAX_255(d, (total[3] + (surf>>1)) / surf);
117                         case 3: MAX_255(d, (total[2] + (surf>>1)) / surf);
118                                 MAX_255(d, (total[1] + (surf>>1)) / surf);
119                         case 1: MAX_255(d, (total[0] + (surf>>1)) / surf);
120                         }
121                         memset(total, 0, sizeof total);
122                     } else {
123                         int k;
124                         /* Vertical and horizontal error compensation */
125                         for (k = chan-1; k >= 0; k --, p ++, s++) {
126                             tmp = *p * yerr;
127                             int tmp2 = tmp * err >> BITS;
128                             int right = *s * err >> BITS;
129                             MAX_255(d, (total[k] + tmp2 + (surf>>1) + right) / surf);
130                             total[k] = *s - right + tmp - tmp2;
131                             *s = (*p<<BITS) - tmp;
132                         }
133                         x++;
134                     }
135                     IterDDA(&nerr);
136                     IterDDA(&xpos); i --;
137                 }
138             }
139             y ++; in += src->stride;
140         }
141         else /* No vertical error (maybe horizontal) */
142         {
143             for (i = ret->width, s = sum; i > 0; ) {
144                 if (x < xpos.y) {
145                     /* No error compensation */
146                     switch (chan) {
147                     case 4: total[3] += *s; s ++;
148                     case 3: total[2] += *s; s ++;
149                             total[1] += *s; s ++;
150                     case 1: total[0] += *s; s ++;
151                     }
152                     x ++;
153                 } else {
154                     int err = nerr.y & (VALUES-1);
155                     if (xerr == 0 || err == 0) {
156                         switch (chan) {
157                         case 4: MAX_255(d, (total[3] + (surf>>1)) / surf);
158                         case 3: MAX_255(d, (total[2] + (surf>>1)) / surf);
159                                 MAX_255(d, (total[1] + (surf>>1)) / surf);
160                         case 1: MAX_255(d, (total[0] + (surf>>1)) / surf);
161                         }
162                     } else {
163                         /* Horizontal error compensation */
164                         switch (chan) {
165                         case 4: tmp = *s * err >> BITS; MAX_255(d, (total[3] + tmp + (surf>>1)) / surf); *s -= tmp; s++;
166                         case 3: tmp = *s * err >> BITS; MAX_255(d, (total[2] + tmp + (surf>>1)) / surf); *s -= tmp; s++;
167                                 tmp = *s * err >> BITS; MAX_255(d, (total[1] + tmp + (surf>>1)) / surf); *s -= tmp; s++;
168                         case 1: tmp = *s * err >> BITS; MAX_255(d, (total[0] + tmp + (surf>>1)) / surf); *s -= tmp; s++;
169                         }
170                         s -= chan;
171                     }
172                     IterDDA(&nerr);
173                     IterDDA(&xpos); i --;
174                     memset(total, 0, sizeof total);
175                 }
176             }
177             #undef MAX_255
178             memset(sum, 0, sz<<2);
179         }
180         out += ret->stride;
181     }
182     free(sum);
183     return 1;
184 }


hijacker
hijacker
hijacker
hijacker