]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/Thumb.cc
:ThumbColorMap): Changed field init order to match decl and to avoid
[evince.git] / pdf / xpdf / Thumb.cc
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-indent-level: 8; c-basic-offset: 8 -*- */
2 /* 
3  *  Copyright (C) 2003 Remi Cohen-Scali
4  *
5  *  Author:
6  *    Remi Cohen-Scali <Remi@Cohen-Scali.com>
7  *
8  * GPdf is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * GPdf is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21  */
22
23 #include <aconf.h>
24 #include <string.h>
25
26 #ifdef USE_GCC_PRAGMAS
27 #pragma implementation
28 #endif
29
30 #include <gpdf-g-switch.h>
31 #  include <glib.h>
32 #include <gpdf-g-switch.h>
33 #include "gmem.h"
34 #include "Object.h"
35 #include "Gfx.h"
36 #include "GfxState.h"
37 #include "Thumb.h"
38
39 static GHashTable *cmhash = NULL;
40
41 /*
42  * ThumbColorMap
43  */
44 ThumbColorMap::ThumbColorMap(int bitsA,
45                              Object *obj,
46                              GfxColorSpace *csA) :
47   bits(bitsA),
48   str(NULL),
49   cs(csA), 
50   length(0)
51 {
52         Object obj1, obj2; 
53         GfxIndexedColorSpace *iCS;
54         GfxSeparationColorSpace *sepCS;
55         int maxPixel;
56         Dict *streamDict;
57         int n;
58         int baseNComps; 
59
60         ok = gFalse;
61         maxPixel = (1 << bits) - 1;
62
63         do {
64                 if (!obj->isStream ()) {
65                         printf ("Error: Invalid object of type %s\n",
66                                 obj->getTypeName ()); 
67                         break; 
68                 }
69                 str = obj->getStream(); 
70
71                 streamDict = obj->streamGetDict ();
72
73                 streamDict->lookupNF ("Filter", &obj1);
74                 if (!obj1.isArray ()) {
75                         printf ("Error: Invalid filter object of type %s\n",
76                                 obj1.getTypeName ()); 
77                         break;                         
78                 }
79
80                 str = str->addFilters(obj);
81
82                 streamDict->lookup ("Length", &obj1);
83                 if (obj1.isNull ())
84                 {
85                         printf ("Error: No Length object\n"); 
86                         break; 
87                 }
88                 if (!obj1.isInt ()) {
89                         printf ("Error: Invalid Width object %s\n",
90                                 obj1.getTypeName ());
91                         obj1.free ();
92                         break;
93                 }
94                 length = obj1.getInt ();
95                 obj1.free ();
96
97                 nComps = cs->getNComps();
98
99                 if (cs->getMode () == csIndexed) {
100                         iCS = (GfxIndexedColorSpace *)cs;
101                         baseNComps = iCS->getBase ()->getNComps ();
102                         str->reset(); 
103                         if (iCS->getBase ()->getMode () == csDeviceGray) {
104                                 gray = (double *)gmalloc(sizeof(double) * (iCS->getIndexHigh () + 1));
105                                 for (n = 0; n <= iCS->getIndexHigh (); n++) {
106                                         double comp = (double)str->getChar(); 
107                                         //printf ("Gray pixel [%03d] = %02x\n", n, (int)comp); 
108                                         gray[n] = comp / (double)iCS->getIndexHigh (); 
109                                 }
110                         }
111                         else if (iCS->getBase ()->getMode () == csDeviceRGB) {
112                                 rgb = (GfxRGB *)gmalloc(sizeof(GfxRGB) * (iCS->getIndexHigh () + 1));
113                                 for (n = 0; n <= iCS->getIndexHigh (); n++) {
114                                         double comp_r = (double)str->getChar(); 
115                                         double comp_g = (double)str->getChar(); 
116                                         double comp_b = (double)str->getChar(); 
117 //                                        printf ("RGB pixel [0x%02x] = (%02x,%02x,%02x)\n",
118 //                                                n, (int)comp_r, (int)comp_g, (int)comp_b); 
119                                         rgb[n].r = comp_r / (double)iCS->getIndexHigh (); 
120                                         rgb[n].g = comp_g / (double)iCS->getIndexHigh (); 
121                                         rgb[n].b = comp_b / (double)iCS->getIndexHigh (); 
122                                 }
123                         }
124                         else if (iCS->getBase ()->getMode () == csDeviceCMYK) {
125                                 cmyk = (GfxCMYK *)gmalloc(sizeof(GfxCMYK) * (iCS->getIndexHigh () + 1));
126                                 for (n = 0; n <= iCS->getIndexHigh (); n++) {
127                                         double comp_c = (double)str->getChar(); 
128                                         double comp_m = (double)str->getChar(); 
129                                         double comp_y = (double)str->getChar(); 
130                                         double comp_k = (double)str->getChar(); 
131                                         //printf ("CMYK pixel [%03d] = (%02x,%02x,%02x,%02x)\n",
132                                         //        n, (int)comp_c, (int)comp_m, (int)comp_y, (int)comp_k); 
133                                         cmyk[n].c = comp_c / (double)iCS->getIndexHigh (); 
134                                         cmyk[n].m = comp_m / (double)iCS->getIndexHigh (); 
135                                         cmyk[n].y = comp_y / (double)iCS->getIndexHigh (); 
136                                         cmyk[n].k = comp_k / (double)iCS->getIndexHigh (); 
137                                 }
138                         }
139                 }
140                 else if (cs->getMode () == csSeparation) {
141                         sepCS = (GfxSeparationColorSpace *)cs; 
142                         /* FIXME: still to do */
143                 }
144
145                 ok = gTrue;
146         }
147         while (0); 
148 }
149
150 ThumbColorMap *
151 ThumbColorMap::lookupColorMap(XRef *xref, int bits, Object *obj, GfxColorSpace *cs)
152 {
153         Object obj1; 
154         ThumbColorMap *cm; 
155         gchar *key;
156         
157         if (!cmhash)
158                 cmhash = g_hash_table_new(NULL, g_int_equal); 
159
160         key = g_strdup_printf ("%d %d R", obj->getRefNum (), obj->getRefGen ());
161
162         if (!(cm = (ThumbColorMap *)g_hash_table_lookup (cmhash, &key))) {
163                 cm = new ThumbColorMap(bits, obj->fetch(xref, &obj1), cs);
164                 obj1.free(); 
165                 g_hash_table_insert(cmhash, &key, cm); 
166         }
167
168         g_free (key); 
169
170         return cm; 
171 }
172
173 void
174 ThumbColorMap::getGray(Guchar *x, double *outgray)
175 {
176         *outgray = gray[*x];
177 }
178
179 void
180 ThumbColorMap::getRGB(Guchar *x, GfxRGB *outrgb)
181 {
182         outrgb->r = rgb[*x].r;
183         outrgb->g = rgb[*x].g;
184         outrgb->b = rgb[*x].b;
185 }
186
187 void
188 ThumbColorMap::getCMYK(Guchar *x, GfxCMYK *outcmyk)
189 {
190         outcmyk->c = cmyk[*x].c;
191         outcmyk->m = cmyk[*x].m;
192         outcmyk->y = cmyk[*x].y;
193         outcmyk->k = cmyk[*x].k;
194 }
195
196 ThumbColorMap::~ThumbColorMap()
197 {
198         delete str;
199         gfree((void *)gray); 
200 }
201
202 /*
203  * Thumb
204  */
205
206 Thumb::Thumb(XRef *xrefA, Object *obj) :
207   xref(xrefA),
208   str(NULL)
209 {
210         Object obj1, obj2;
211         Dict *dict;
212
213         do {
214                 /* Get stream dict */
215                 dict = obj->streamGetDict ();
216                 str = obj->getStream(); 
217                 
218                 /* Get width */
219                 dict->lookup ("Width", &obj1);
220                 if (obj1.isNull ())
221                 {
222                         obj1.free ();
223                         dict->lookup ("W", &obj1);
224                 }
225                 if (!obj1.isInt ()) {
226                         printf ("Error: Invalid Width object %s\n",
227                                 obj1.getTypeName ());
228                         obj1.free ();
229                         break;
230                 }
231                 width = obj1.getInt ();
232                 obj1.free ();
233                 
234                 /* Get heigth */
235                 dict->lookup ("Height", &obj1);
236                 if (obj1.isNull ()) 
237                 {
238                         obj1.free ();
239                         dict->lookup ("H", &obj1);
240                 }
241                 if (!obj1.isInt ()) {
242                         printf ("Error: Invalid Height object %s\n",
243                                 obj1.getTypeName ());
244                         obj1.free ();
245                         break;
246                 }
247                 height = obj1.getInt ();
248                 obj1.free ();
249                 
250                 /* bit depth */
251                 dict->lookup ("BitsPerComponent", &obj1);
252                 if (obj1.isNull ())
253                 {
254                         obj1.free ();
255                         dict->lookup ("BPC", &obj1);
256                 }
257                 if (!obj1.isInt ()) {
258                         printf ("Error: Invalid BitsPerComponent object %s\n",
259                                 obj1.getTypeName ());
260                         obj1.free ();
261                         break;
262                 }
263                 bits = obj1.getInt ();
264                 obj1.free ();
265                 
266                 /* Get color space */
267                 dict->lookup ("ColorSpace", &obj1);
268                 if (obj1.isNull ()) 
269                 {
270                         obj1.free ();
271                         dict->lookup ("CS", &obj1);
272                 }
273                 if (!(gfxCS = GfxColorSpace::parse (&obj1)))
274                 {
275                         printf ("Error: Cannot parse color space\n");
276                         obj1.free ();
277                         break;
278                 }
279                 if (gfxCS->getMode () == csIndexed)                     
280                         thumbCM = ThumbColorMap::lookupColorMap (xref, bits, obj1.arrayGetNF(3, &obj2), gfxCS);
281                 else if (gfxCS->getMode () == csSeparation)
282                         printf ("Not yet implemented\n");
283                   
284                 
285                 dict->lookup ("Length", &obj1);
286                 if (!obj1.isInt ()) {
287                         printf ("Error: Invalid Length Object %s\n",
288                                 obj1.getTypeName ());
289                         obj1.free ();
290                         break;
291                 }
292                 length = obj1.getInt ();
293                 obj1.free ();
294
295                 str->addFilters(obj);
296         }
297         while (0);      
298 }
299
300 unsigned char *
301 Thumb::getPixbufData()
302 {
303         ImageStream *imgstr;
304         unsigned char *pixbufdata;
305         unsigned int pixbufdatasize;
306         int row, col;
307         unsigned char *p;
308
309         /* RGB Pixbuf data */
310         pixbufdatasize = width * height * 3;
311         pixbufdata =(unsigned char *)g_malloc(pixbufdatasize);
312         p = pixbufdata;
313
314         imgstr = new ImageStream(str, width, thumbCM->getNumPixelComps(), thumbCM->getBits());
315         imgstr->reset();
316         for (row = 0; row < height; ++row) {
317             for (col = 0; col < width; ++col) {
318                 Guchar pix[gfxColorMaxComps];
319                 GfxRGB rgb;
320
321                 imgstr->getPixel(pix);
322                 thumbCM->getRGB(pix, &rgb);
323
324                 *p++ = (guchar)(rgb.r * 255.99999);
325                 *p++ = (guchar)(rgb.g * 255.99999);
326                 *p++ = (guchar)(rgb.b * 255.99999);
327             }
328         }
329         delete imgstr;
330
331         return pixbufdata;
332 }
333
334 Thumb::~Thumb() {
335         delete thumbCM;
336         delete str;
337 }
338