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