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=19649
 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=19649
14 */
15 
16 
17 #ifndef DOWN_SAMPLE_H
18 #define DOWN_SAMPLE_H
19 
20 #include <stdint.h>
21 
22 typedef uint8_t *                DATA8;
23 typedef uint16_t *               DATA16;
24 typedef uint32_t *               DATA32;
25 typedef struct Image_t *         Image;
26 
27 struct Image_t
28 {
29 	int   width, height, bpp;
30 	int   stride, format;
31 	DATA8 bitmap;
32 };
33 
34 int ImageDownScale(Image source, Image ret);
35 #endif
36 


hijacker
hijacker
hijacker
hijacker

build.log

1 /tmp/litprog99665/ImageTest.c:18:21: fatal error: SDL/SDL.h: No such file or directory
2 compilation terminated.
3 /tmp/litprog99665/Resize.c:45:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'void'
4 /tmp/litprog99665/Resize.c: In function 'ImageDownScale':
5 /tmp/litprog99665/Resize.c:93:9: warning: implicit declaration of function 'IterDDA' [-Wimplicit-function-declaration]


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=19649
 14 */
 15 
 16 #include <stdio.h>
 17 #include <stdlib.h>
 18 #include <string.h>
 19 #include <malloc.h>
 20 #include "DownScale.h"
 21 
 22 typedef struct Iter {
 23   int y, ye, sy, dy,
 24       x, xe, sx, dx,
 25       err;
 26 } Iter;
 27 
 28 static void InitDDA(Iter * iter, int xs, int xe, int ys, int ye)
 29 {
 30 	/* Pre-condition: xe > xs >= 0 */
 31 	div_t q = div(iter->dy = ye - ys, xe);
 32 	iter->y   = ys;
 33 	iter->ye  = ye;
 34 	iter->x   = xs;
 35 	iter->xe  = xe;
 36 	iter->err = xe;
 37 	iter->dx  = abs(q.rem);
 38 	iter->sx  = q.quot;
 39 	iter->sy  = (ys < ye ? 1 : -1);
 40 	if (xs > 0)
 41 		iter->y   = ye-(iter->dy * (xe-xs) + iter->sy * iter->err)/xe,
 42 		iter->err = (iter->err-iter->dx*xs) % xe + xe;
 43 }
 44 
 45 static inline void IterDDA(Iter * iter)
 46 {
 47 	iter->x ++;
 48 	iter->y += iter->sx;
 49 	iter->err -= iter->dx;
 50 	if (iter->err <= 0)
 51 		iter->y += iter->sy, iter->err += iter->xe;
 52 }
 53 
 54 #define	BITS         8
 55 #define	VALUES       (1 @<< BITS)
 56 
 57 int ImageDownScale(Image src, Image ret)
 58 {
 59     DATA32 sum;
 60     int    i, y, w, h, chan, sz, surf, xerr;
 61 
 62     DATA8 out = ret->bitmap;
 63     DATA8 in  = src->bitmap;
 64     Iter  ypos, xpos, nerr;
 65 
 66     sz = src->width * src->bpp;
 67     if (ret->width == 0 || ret->height == 0) return 0;
 68     if (ret->width > src->width || ret->height > src->height) return 0;
 69     if (ret->width == src->width && ret->height == src->height) {
 70         for (y = ret->height; y > 0; y --, in += src->stride, out += ret->stride)
 71             memcpy(out, in, sz);
 72         return 1;
 73     }
 74 
 75     w    = ret->width;
 76     h    = ret->height;
 77     chan = src->bpp;
 78     sum  = calloc(sz, sizeof *sum);
 79     surf = (unsigned long long) src->width * src->height * VALUES / (w * h);
 80     y    = 0;
 81 
 82     if (sum == NULL) return 0;
 83     memset(&nerr, 0, sizeof nerr); nerr.err = 1;
 84     InitDDA(&ypos, 0, h, 0, src->height);
 85     InitDDA(&xpos, 0, w, 0, src->width); xerr = xpos.dx > 0;
 86 
 87     while (ypos.x < ypos.xe)
 88     {
 89         DATA8 d = out, p;
 90         int x, yerr;
 91         int total[4], tmp;
 92         DATA32 s;
 93         IterDDA(&ypos);
 94         yerr = (ypos.xe - ypos.err) * VALUES / ypos.xe;
 95 
 96         while (y < ypos.y)
 97         {
 98             for (p = in, i = sz, s = sum; i > 0; *s++ += (*p<<BITS), p++, i --);
 99             y ++; in += src->stride;
100         }
101 
102         InitDDA(&xpos, 0, w, 0, src->width); x = 0;      IterDDA(&xpos);
103         InitDDA(&nerr, 0, xpos.xe, 0, VALUES * xpos.dx); IterDDA(&nerr);
104         memset(total, 0, sizeof total);
105         if (yerr > 0)
106         {
107             #define MAX_255(ptr, val) { int z = val; *ptr = (z >= 255 ? 255 : z); ptr ++; }
108             for (p = in, i = ret->width, s = sum; i > 0; ) {
109                 if (x < xpos.y) {
110                     /* Vertical error compensation */
111                     switch (chan) {
112                     case 4: tmp = *p * yerr; total[3] += tmp + *s; *s = (*p<<BITS) - tmp; s ++; p ++;
113                     case 3: tmp = *p * yerr; total[2] += tmp + *s; *s = (*p<<BITS) - tmp; s ++; p ++;
114                             tmp = *p * yerr; total[1] += tmp + *s; *s = (*p<<BITS) - tmp; s ++; p ++;
115                     case 1: tmp = *p * yerr; total[0] += tmp + *s; *s = (*p<<BITS) - tmp; s ++; p ++;
116                     }
117                     x ++;
118                 } else {
119                     int err = nerr.y & (VALUES-1);
120                     if (xerr == 0 || err == 0) {
121                         switch (chan) {
122                         case 4: MAX_255(d, (total[3] + (surf>>1)) / surf);
123                         case 3: MAX_255(d, (total[2] + (surf>>1)) / surf);
124                                 MAX_255(d, (total[1] + (surf>>1)) / surf);
125                         case 1: MAX_255(d, (total[0] + (surf>>1)) / surf);
126                         }
127                         memset(total, 0, sizeof total);
128                     } else {
129                         int k;
130                         /* Vertical and horizontal error compensation */
131                         for (k = chan-1; k >= 0; k --, p ++, s++) {
132                             tmp = *p * yerr;
133                             int tmp2 = tmp * err >> BITS;
134                             int right = *s * err >> BITS;
135                             MAX_255(d, (total[k] + tmp2 + (surf>>1) + right) / surf);
136                             total[k] = *s - right + tmp - tmp2;
137                             *s = (*p<<BITS) - tmp;
138                         }
139                         x++;
140                     }
141                     IterDDA(&nerr);
142                     IterDDA(&xpos); i --;
143                 }
144             }
145             y ++; in += src->stride;
146         }
147         else /* No vertical error (maybe horizontal) */
148         {
149             for (i = ret->width, s = sum; i > 0; ) {
150                 if (x < xpos.y) {
151                     /* No error compensation */
152                     switch (chan) {
153                     case 4: total[3] += *s; s ++;
154                     case 3: total[2] += *s; s ++;
155                             total[1] += *s; s ++;
156                     case 1: total[0] += *s; s ++;
157                     }
158                     x ++;
159                 } else {
160                     int err = nerr.y & (VALUES-1);
161                     if (xerr == 0 || err == 0) {
162                         switch (chan) {
163                         case 4: MAX_255(d, (total[3] + (surf>>1)) / surf);
164                         case 3: MAX_255(d, (total[2] + (surf>>1)) / surf);
165                                 MAX_255(d, (total[1] + (surf>>1)) / surf);
166                         case 1: MAX_255(d, (total[0] + (surf>>1)) / surf);
167                         }
168                     } else {
169                         /* Horizontal error compensation */
170                         switch (chan) {
171                         case 4: tmp = *s * err >> BITS; MAX_255(d, (total[3] + tmp + (surf>>1)) / surf); *s -= tmp; s++;
172                         case 3: tmp = *s * err >> BITS; MAX_255(d, (total[2] + tmp + (surf>>1)) / surf); *s -= tmp; s++;
173                                 tmp = *s * err >> BITS; MAX_255(d, (total[1] + tmp + (surf>>1)) / surf); *s -= tmp; s++;
174                         case 1: tmp = *s * err >> BITS; MAX_255(d, (total[0] + tmp + (surf>>1)) / surf); *s -= tmp; s++;
175                         }
176                         s -= chan;
177                     }
178                     IterDDA(&nerr);
179                     IterDDA(&xpos); i --;
180                     memset(total, 0, sizeof total);
181                 }
182             }
183             #undef MAX_255
184             memset(sum, 0, sz<<2);
185         }
186         out += ret->stride;
187     }
188     free(sum);
189     return 1;
190 }


hijacker
hijacker
hijacker
hijacker