File: decimate.c

package info (click to toggle)
dvdisaster 0.72.4-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 22,908 kB
  • ctags: 8,121
  • sloc: ansic: 29,314; php: 3,324; sh: 369; xml: 296; makefile: 82; cs: 33
file content (128 lines) | stat: -rw-r--r-- 3,706 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*  pngpack: lossless image compression for a series of screen shots
 *  Copyright (C) 2005-2010 Carsten Gnoerlich.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA,
 *  or direct your browser at http://www.gnu.org.
 */

#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "pngio.h"
#include "memory.h"

/*
 * Thumbnail generation
 */

void SaveThumbnail(Image *pi, char *name, int thumb_size, char *thumb_dir)
{  Image *thumb;
   char tname[strlen(thumb_dir)+strlen(name)+2];
   double ratio, inv_ratio;
   unsigned int size, *pixel;
   int i,j;

   /* sanity check */

   if(pi->width < thumb_size && pi->height < thumb_size)
   {  fprintf(stdout, "... NOT creating thumbnail because of image size (%dx%d)\n",
	      pi->width, pi->height);
      return;
   }

   /* Create thumbnail copy from image */

   thumb=malloc(sizeof(Image));
   memcpy(thumb, pi, sizeof(Image));

   if(thumb->width > thumb->height) 
        inv_ratio = (double)thumb->width/(double)thumb_size;
   else inv_ratio = (double)thumb->height/(double)thumb_size;

   ratio = 1.0/inv_ratio;

   thumb->width  = (int)((double)thumb->width*ratio+0.5);
   thumb->height = (int)((double)thumb->height*ratio+0.5);

   sprintf(tname, "%s/%s", thumb_dir, name);

   fprintf(stdout, "... and %dx%d thumbnail %s\n", thumb->width, thumb->height, tname);

   size = thumb->width * thumb->height;
   thumb->bytesize = sizeof(unsigned int) * size;
   thumb->image = malloc(thumb->bytesize);
   if(!thumb->image) Stop("out of memory for image");

   /*
    * Decimate the image 
    */

   pixel = thumb->image;
   for(i=0; i<thumb->height; i++)
      for(j=0; j<thumb->width; j++)
      {  double first_x = j*inv_ratio;
	 double first_y = i*inv_ratio;
	 double last_x  = (j+1)*inv_ratio;
	 double last_y  = (i+1)*inv_ratio;
	 double area = 0.0;
	 int x0 = floor(first_x);
	 int x1 = ceil(last_x);
	 int y0 = floor(first_y);
	 int y1 = ceil(last_y);
	 int x,y;
	 double c1,c2,c3,c4;
	 unsigned int ci1,ci2,ci3,ci4;
#if 0
	 printf("%d %d -> (%d %d) - (%d %d)\n", j,i, x0,y0, x1, y1);
	 printf("%f %f %f %f\n", first_x, first_y, last_x, last_y);
	 printf("%f %f\n", ratio, inv_ratio);
#endif
	 if(x1>=pi->width) x1=pi->width-1;
	 if(y1>=pi->height) y1=pi->height-1;

	 c1 = c2 = c3 = c4 = 0.0;
	 for(y=y0; y<=y1; y++)
	 {  double ysize = 1.0;
	    double size;

	    if(y<y0) ysize = 1.0-(y0-y);
	    if(y>y1) ysize = 1.0-(y-y1);

	    for(x=x0; x<=x1; x++)
	    {  int idx = x+y*pi->width;
	       size = ysize;
	       if(x<x0) size *= (1.0-(x0-x));
	       if(x>x1) size *= (1-0-(x-x1));

	       c1 += size * ((pi->image[idx]>>24)&0xff);
	       c2 += size * ((pi->image[idx]>>16)&0xff);
	       c3 += size * ((pi->image[idx]>> 8)&0xff);
	       c4 += size * ((pi->image[idx]    )&0xff);
	       area += size;
	    }
	 }

	 ci1 = c1/area; ci2 = c2/area; ci3 = c3/area; ci4 = c4/area;
	 *pixel++ = (ci1<<24) | (ci2<<16) | (ci3<<8) | ci4;
      }

   SavePNG(thumb, tname);

   free(thumb->image);
   free(thumb);
}