1 /*
2  * pixbuf_from_imagesource.cpp
3  * Creates a GdkPixbuf from an ImageSource
4  *
5  * Copyright (c) 2005 by Alastair M. Robinson
6  * Distributed under the terms of the GNU General Public License -
7  * see the file named "COPYING" for more details.
8  *
9  */
10 
11 #include <iostream>
12 
13 #include "../support/debug.h"
14 #include "pixbuf_from_imagesource.h"
15 
16 using namespace std;
17 
pixbuf_from_imagesource(ImageSource * is,int redbg8,int greenbg8,int bluebg8,Progress * prog,GdkPixbuf * pb)18 GdkPixbuf *pixbuf_from_imagesource(ImageSource *is,
19 	int redbg8,int greenbg8,int bluebg8,Progress *prog,GdkPixbuf *pb)
20 {
21 	if(!is)
22 		return(NULL);
23 
24 	switch(is->type)
25 	{
26 		case IS_TYPE_RGB:
27 		case IS_TYPE_RGBA:
28 		case IS_TYPE_GREY:
29 		case IS_TYPE_GREYA:
30 		case IS_TYPE_CMYK:
31 			break;
32 		default:
33 			Debug[WARN] << "pixbuf_from_imagesource: unhandled type - bailing out..." << endl;
34 			return(NULL);
35 			break;
36 	}
37 
38 	if(pb)
39 	{
40 		if(gdk_pixbuf_get_width(pb)!=is->width)
41 			throw "Pixbuf's dimensions must match that of ImageSource!";
42 		if(gdk_pixbuf_get_height(pb)!=is->height)
43 			throw "Pixbuf's dimensions must match that of ImageSource!";
44 	}
45 	else
46 	{
47 		Debug[COMMENT] << "pixbuf_from_imagesource: Converting image of type " << is->type << endl;
48 		pb=gdk_pixbuf_new(GDK_COLORSPACE_RGB,FALSE,8,is->width,is->height);
49 	}
50 
51 	if(pb)
52 	{
53 		int rowstride=gdk_pixbuf_get_rowstride(pb);
54 		unsigned char *pixels=gdk_pixbuf_get_pixels(pb);
55 
56 		// Displaying the progress meter can be expensive,
57 		// so we only update it often enough to reflect single
58 		// percentage steps.
59 		int progressmodulo=is->height/100;
60 		if(progressmodulo==0) progressmodulo=1;
61 
62 		for(int y=0;y<is->height;++y)
63 		{
64 			ISDataType *src=is->GetRow(y);
65 			switch(is->type)
66 			{
67 				case IS_TYPE_RGBA:
68 					for(int x=0;x<is->width;++x)
69 					{
70 						int a=ISTOEIGHT(src[x*4+3]);
71 						pixels[x*3]=(ISTOEIGHT(src[x*4])*a+redbg8*(255-a))/255;
72 						pixels[x*3+1]=(ISTOEIGHT(src[x*4+1])*a+greenbg8*(255-a))/255;
73 						pixels[x*3+2]=(ISTOEIGHT(src[x*4+2])*a+bluebg8*(255-a))/255;
74 					}
75 					break;
76 				case IS_TYPE_GREYA:
77 					for(int x=0;x<is->width;++x)
78 					{
79 						int a=255-ISTOEIGHT(src[x*2+3]);
80 						pixels[x*3]=(ISTOEIGHT(IS_SAMPLEMAX-src[x*2])*a+redbg8*(255-a))/255;
81 						pixels[x*3+1]=(ISTOEIGHT(IS_SAMPLEMAX-src[x*2])*a+greenbg8*(255-a))/255;
82 						pixels[x*3+2]=(ISTOEIGHT(IS_SAMPLEMAX-src[x*2])*a+bluebg8*(255-a))/255;
83 					}
84 					break;
85 				case IS_TYPE_CMYK:
86 					for(int x=0;x<is->width;++x)
87 					{
88 						int pc=ISTOEIGHT(src[x*4]);
89 						int pm=ISTOEIGHT(src[x*4+1]);
90 						int py=ISTOEIGHT(src[x*4+2]);
91 						int pk=ISTOEIGHT(src[x*4+3]);
92 						int r=(255-pc)-(pk);
93 						int g=(255-pm)-(pk);
94 						int b=(255-py)-(pk);
95 						if(r<0) r=0;
96 						if(g<0) g=0;
97 						if(b<0) b=0;
98 						pixels[x*3]=r;
99 						pixels[x*3+1]=g;
100 						pixels[x*3+2]=b;
101 					}
102 					break;
103 				case IS_TYPE_RGB:
104 					for(int x=0;x<is->width*is->samplesperpixel;++x)
105 					{
106 						pixels[x]=ISTOEIGHT(src[x]);
107 					}
108 					break;
109 				case IS_TYPE_GREY:
110 					for(int x=0;x<is->width*is->samplesperpixel;++x)
111 					{
112 						pixels[x*3]=ISTOEIGHT(IS_SAMPLEMAX-src[x]);
113 						pixels[x*3+1]=ISTOEIGHT(IS_SAMPLEMAX-src[x]);
114 						pixels[x*3+2]=ISTOEIGHT(IS_SAMPLEMAX-src[x]);
115 					}
116 					break;
117 				default:
118 					Debug[WARN] << "pixbuf_from_imagesource: Huh?  IS type of " << is->type << " should have been rejected already." << endl;
119 					g_object_unref(G_OBJECT(pb));
120 					return(NULL);
121 					break;
122 			}
123 			pixels+=rowstride;
124 			bool cont=true;
125 			if((y%progressmodulo)==0)
126 			{
127 				if(prog)
128 					cont=prog->DoProgress(y,is->height);
129 			}
130 			if(!cont)
131 			{
132 				g_object_unref(G_OBJECT(pb));
133 				return(NULL);
134 			}
135 		}
136 	}
137 	return(pb);
138 }
139 
140 
pixbuf_alpha_from_imagesource(ImageSource * is,Progress * prog,GdkPixbuf * pb)141 GdkPixbuf *pixbuf_alpha_from_imagesource(ImageSource *is,Progress *prog,GdkPixbuf *pb)
142 {
143 	if(!is)
144 		return(NULL);
145 
146 	switch(is->type)
147 	{
148 		case IS_TYPE_RGB:
149 		case IS_TYPE_RGBA:
150 		case IS_TYPE_GREY:
151 		case IS_TYPE_GREYA:
152 		case IS_TYPE_CMYK:
153 			break;
154 		default:
155 			Debug[WARN] << "pixbuf_from_imagesource: unhandled type - bailing out..." << endl;
156 			return(NULL);
157 			break;
158 	}
159 
160 	if(pb)
161 	{
162 		if(gdk_pixbuf_get_width(pb)!=is->width)
163 			throw "Pixbuf's dimensions must match that of ImageSource!";
164 		if(gdk_pixbuf_get_height(pb)!=is->height)
165 			throw "Pixbuf's dimensions must match that of ImageSource!";
166 	}
167 	else
168 	{
169 		Debug[COMMENT] << "pixbuf_from_imagesource: Converting image of type " << is->type << endl;
170 		pb=gdk_pixbuf_new(GDK_COLORSPACE_RGB,TRUE,8,is->width,is->height);
171 	}
172 
173 	if(pb)
174 	{
175 		int rowstride=gdk_pixbuf_get_rowstride(pb);
176 		unsigned char *pixels=gdk_pixbuf_get_pixels(pb);
177 
178 		// Displaying the progress meter can be expensive,
179 		// so we only update it often enough to reflect single
180 		// percentage steps.
181 		int progressmodulo=is->height/100;
182 		if(progressmodulo==0) progressmodulo=1;
183 
184 		for(int y=0;y<is->height;++y)
185 		{
186 			ISDataType *src=is->GetRow(y);
187 			switch(is->type)
188 			{
189 				case IS_TYPE_RGBA:
190 					for(int x=0;x<is->width*is->samplesperpixel;++x)
191 					{
192 						pixels[x]=ISTOEIGHT(src[x]);
193 					}
194 					break;
195 				case IS_TYPE_GREYA:
196 					for(int x=0;x<is->width;++x)
197 					{
198 						pixels[x*4]=ISTOEIGHT(IS_SAMPLEMAX-src[x*2]);
199 						pixels[x*4+1]=ISTOEIGHT(IS_SAMPLEMAX-src[x*2]);
200 						pixels[x*4+2]=ISTOEIGHT(IS_SAMPLEMAX-src[x*2]);
201 						pixels[x*4+3]=ISTOEIGHT(IS_SAMPLEMAX-src[x*2+1]);
202 					}
203 					break;
204 				case IS_TYPE_CMYK:
205 					for(int x=0;x<is->width;++x)
206 					{
207 						int pc=ISTOEIGHT(src[x*4]);
208 						int pm=ISTOEIGHT(src[x*4+1]);
209 						int py=ISTOEIGHT(src[x*4+2]);
210 						int pk=ISTOEIGHT(src[x*4+3]);
211 						int r=(255-pc)-(pk);
212 						int g=(255-pm)-(pk);
213 						int b=(255-py)-(pk);
214 						if(r<0) r=0;
215 						if(g<0) g=0;
216 						if(b<0) b=0;
217 						pixels[x*4]=r;
218 						pixels[x*4+1]=g;
219 						pixels[x*4+2]=b;
220 						pixels[x*4+3]=255;
221 					}
222 					break;
223 				case IS_TYPE_RGB:
224 					for(int x=0;x<is->width;++x)
225 					{
226 						pixels[x*4]=ISTOEIGHT(src[x*3]);
227 						pixels[x*4+1]=ISTOEIGHT(src[x*3+1]);
228 						pixels[x*4+2]=ISTOEIGHT(src[x*3+2]);
229 						pixels[x*4+3]=255;
230 					}
231 					break;
232 				case IS_TYPE_GREY:
233 					for(int x=0;x<is->width*is->samplesperpixel;++x)
234 					{
235 						pixels[x*4]=ISTOEIGHT(src[x]);
236 						pixels[x*4+1]=ISTOEIGHT(src[x]);
237 						pixels[x*4+2]=ISTOEIGHT(src[x]);
238 						pixels[x*4+3]=255;
239 					}
240 					break;
241 				default:
242 					Debug[WARN] << "pixbuf_from_imagesource: Huh?  IS type of " << is->type << " should have been rejected already." << endl;
243 					g_object_unref(G_OBJECT(pb));
244 					return(NULL);
245 					break;
246 			}
247 			pixels+=rowstride;
248 			bool cont=true;
249 			if((y%progressmodulo)==0)
250 			{
251 				if(prog)
252 					cont=prog->DoProgress(y,is->height);
253 			}
254 			if(!cont)
255 			{
256 				g_object_unref(G_OBJECT(pb));
257 				return(NULL);
258 			}
259 		}
260 	}
261 	return(pb);
262 }
263