]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/Thumb.cc
Add implem for Thumb object parsing.
[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   length(0), 
50   cs(csA)
51 {
52         Object obj1, obj2; 
53         GfxIndexedColorSpace *iCS;
54         GfxSeparationColorSpace *sepCS;
55         int maxPixel, indexHigh;
56         Dict *streamDict;
57         int n;
58         int baseNComps; 
59         /* LZW params */
60         int colors = 0, early = 0;
61         /* CCITTFax params */
62         int encoding = 0, rows = 0;
63         GBool eol = gFalse, byteAlign = gFalse, eob = gFalse, black = gFalse;
64         /* Common params */
65         int pred = 0, cols = 0; 
66
67         ok = gFalse;
68         maxPixel = (1 << bits) - 1;
69
70         do {
71                 if (!obj->isStream ()) {
72                         printf ("Error: Invalid object of type %s\n",
73                                 obj->getTypeName ()); 
74                         break; 
75                 }
76                 str = obj->getStream(); 
77
78                 streamDict = obj->streamGetDict ();
79
80                 streamDict->lookupNF ("Filter", &obj1);
81                 if (!obj1.isArray ()) {
82                         printf ("Error: Invalid filter object of type %s\n",
83                                 obj1.getTypeName ()); 
84                         break;                         
85                 }
86
87                 str = str->addFilters(obj);
88
89                 streamDict->lookup ("Length", &obj1);
90                 if (obj1.isNull ())
91                 {
92                         printf ("Error: No Length object\n"); 
93                         break; 
94                 }
95                 if (!obj1.isInt ()) {
96                         printf ("Error: Invalid Width object %s\n",
97                                 obj1.getTypeName ());
98                         obj1.free ();
99                         break;
100                 }
101                 length = obj1.getInt ();
102                 obj1.free ();
103
104                 nComps = cs->getNComps();
105
106                 if (cs->getMode () == csIndexed) {
107                         iCS = (GfxIndexedColorSpace *)cs;
108                         baseNComps = iCS->getBase ()->getNComps ();
109                         str->reset(); 
110                         if (iCS->getBase ()->getMode () == csDeviceGray) {
111                                 gray = (double *)gmalloc(sizeof(double) * (iCS->getIndexHigh () + 1));
112                                 for (n = 0; n <= iCS->getIndexHigh (); n++) {
113                                         double comp = (double)str->getChar(); 
114                                         //printf ("Gray pixel [%03d] = %02x\n", n, (int)comp); 
115                                         gray[n] = comp / (double)iCS->getIndexHigh (); 
116                                 }
117                         }
118                         else if (iCS->getBase ()->getMode () == csDeviceRGB) {
119                                 rgb = (GfxRGB *)gmalloc(sizeof(GfxRGB) * (iCS->getIndexHigh () + 1));
120                                 for (n = 0; n <= iCS->getIndexHigh (); n++) {
121                                         double comp_r = (double)str->getChar(); 
122                                         double comp_g = (double)str->getChar(); 
123                                         double comp_b = (double)str->getChar(); 
124 //                                        printf ("RGB pixel [0x%02x] = (%02x,%02x,%02x)\n",
125 //                                                n, (int)comp_r, (int)comp_g, (int)comp_b); 
126                                         rgb[n].r = comp_r / (double)iCS->getIndexHigh (); 
127                                         rgb[n].g = comp_g / (double)iCS->getIndexHigh (); 
128                                         rgb[n].b = comp_b / (double)iCS->getIndexHigh (); 
129                                 }
130                         }
131                         else if (iCS->getBase ()->getMode () == csDeviceCMYK) {
132                                 cmyk = (GfxCMYK *)gmalloc(sizeof(GfxCMYK) * (iCS->getIndexHigh () + 1));
133                                 for (n = 0; n <= iCS->getIndexHigh (); n++) {
134                                         double comp_c = (double)str->getChar(); 
135                                         double comp_m = (double)str->getChar(); 
136                                         double comp_y = (double)str->getChar(); 
137                                         double comp_k = (double)str->getChar(); 
138                                         //printf ("CMYK pixel [%03d] = (%02x,%02x,%02x,%02x)\n",
139                                         //        n, (int)comp_c, (int)comp_m, (int)comp_y, (int)comp_k); 
140                                         cmyk[n].c = comp_c / (double)iCS->getIndexHigh (); 
141                                         cmyk[n].m = comp_m / (double)iCS->getIndexHigh (); 
142                                         cmyk[n].y = comp_y / (double)iCS->getIndexHigh (); 
143                                         cmyk[n].k = comp_k / (double)iCS->getIndexHigh (); 
144                                 }
145                         }
146                 }
147                 else if (cs->getMode () == csSeparation) {
148                         sepCS = (GfxSeparationColorSpace *)cs; 
149                         /* FIXME: still to do */
150                 }
151
152                 ok = gTrue;
153         }
154         while (0); 
155 }
156
157 ThumbColorMap *
158 ThumbColorMap::lookupColorMap(XRef *xref, int bits, Object *obj, GfxColorSpace *cs)
159 {
160         Object obj1; 
161         ThumbColorMap *cm; 
162         gchar *key;
163         
164         if (!cmhash)
165                 cmhash = g_hash_table_new(NULL, g_int_equal); 
166
167         key = g_strdup_printf ("%d %d R", obj->getRefNum (), obj->getRefGen ());
168
169         if (!(cm = (ThumbColorMap *)g_hash_table_lookup (cmhash, &key))) {
170                 cm = new ThumbColorMap(bits, obj->fetch(xref, &obj1), cs);
171                 obj1.free(); 
172                 g_hash_table_insert(cmhash, &key, cm); 
173         }
174
175         g_free (key); 
176
177         return cm; 
178 }
179
180 void
181 ThumbColorMap::getGray(Guchar *x, double *outgray)
182 {
183         *outgray = gray[*x];
184 }
185
186 void
187 ThumbColorMap::getRGB(Guchar *x, GfxRGB *outrgb)
188 {
189         outrgb->r = rgb[*x].r;
190         outrgb->g = rgb[*x].g;
191         outrgb->b = rgb[*x].b;
192 }
193
194 void
195 ThumbColorMap::getCMYK(Guchar *x, GfxCMYK *outcmyk)
196 {
197         outcmyk->c = cmyk[*x].c;
198         outcmyk->m = cmyk[*x].m;
199         outcmyk->y = cmyk[*x].y;
200         outcmyk->k = cmyk[*x].k;
201 }
202
203 ThumbColorMap::~ThumbColorMap()
204 {
205         delete str;
206         gfree((void *)gray); 
207 }
208
209 /*
210  * Thumb
211  */
212
213 Thumb::Thumb(XRef *xrefA, Object *obj) :
214   xref(xrefA),
215   str(NULL)
216 {
217         Object obj1, obj2;
218         Dict *dict;
219         unsigned int dsize;
220         int row, col, comp;
221
222         do {
223                 /* Get stream dict */
224                 dict = obj->streamGetDict ();
225                 str = obj->getStream(); 
226                 
227                 /* Get width */
228                 dict->lookup ("Width", &obj1);
229                 if (obj1.isNull ())
230                 {
231                         obj1.free ();
232                         dict->lookup ("W", &obj1);
233                 }
234                 if (!obj1.isInt ()) {
235                         printf ("Error: Invalid Width object %s\n",
236                                 obj1.getTypeName ());
237                         obj1.free ();
238                         break;
239                 }
240                 width = obj1.getInt ();
241                 obj1.free ();
242                 
243                 /* Get heigth */
244                 dict->lookup ("Height", &obj1);
245                 if (obj1.isNull ()) 
246                 {
247                         obj1.free ();
248                         dict->lookup ("H", &obj1);
249                 }
250                 if (!obj1.isInt ()) {
251                         printf ("Error: Invalid Height object %s\n",
252                                 obj1.getTypeName ());
253                         obj1.free ();
254                         break;
255                 }
256                 height = obj1.getInt ();
257                 obj1.free ();
258                 
259                 /* bit depth */
260                 dict->lookup ("BitsPerComponent", &obj1);
261                 if (obj1.isNull ())
262                 {
263                         obj1.free ();
264                         dict->lookup ("BPC", &obj1);
265                 }
266                 if (!obj1.isInt ()) {
267                         printf ("Error: Invalid BitsPerComponent object %s\n",
268                                 obj1.getTypeName ());
269                         obj1.free ();
270                         break;
271                 }
272                 bits = obj1.getInt ();
273                 obj1.free ();
274                 
275                 /* Get color space */
276                 dict->lookup ("ColorSpace", &obj1);
277                 if (obj1.isNull ()) 
278                 {
279                         obj1.free ();
280                         dict->lookup ("CS", &obj1);
281                 }
282                 if (!(gfxCS = GfxColorSpace::parse (&obj1)))
283                 {
284                         printf ("Error: Cannot parse color space\n");
285                         obj1.free ();
286                         break;
287                 }
288                 if (gfxCS->getMode () == csIndexed)                     
289                         thumbCM = ThumbColorMap::lookupColorMap (xref, bits, obj1.arrayGetNF(3, &obj2), gfxCS);
290                 else if (gfxCS->getMode () == csSeparation)
291                         printf ("Not yet implemented\n");
292                   
293                 
294                 dict->lookup ("Length", &obj1);
295                 if (!obj1.isInt ()) {
296                         printf ("Error: Invalid Length Object %s\n",
297                                 obj1.getTypeName ());
298                         obj1.free ();
299                         break;
300                 }
301                 length = obj1.getInt ();
302                 obj1.free ();
303
304                 str->addFilters(obj);
305         }
306         while (0);      
307 }
308
309 unsigned char *
310 Thumb::getPixbufData()
311 {
312         ImageStream *imgstr;
313         unsigned char *pixbufdata;
314         unsigned int pixbufdatasize;
315         int row, col, i;
316         unsigned char *p;
317
318         /* RGB Pixbuf data */
319         pixbufdatasize = width * height * 3;
320         pixbufdata =(unsigned char *)g_malloc(pixbufdatasize);
321         p = pixbufdata;
322
323         imgstr = new ImageStream(str, width, thumbCM->getNumPixelComps(), thumbCM->getBits());
324         imgstr->reset();
325         for (row = 0; row < height; ++row) {
326             for (col = 0; col < width; ++col) {
327                 Guchar pix[gfxColorMaxComps];
328                 GfxRGB rgb;
329
330                 imgstr->getPixel(pix);
331                 thumbCM->getRGB(pix, &rgb);
332
333                 *p++ = (guchar)(rgb.r * 255.99999);
334                 *p++ = (guchar)(rgb.g * 255.99999);
335                 *p++ = (guchar)(rgb.b * 255.99999);
336             }
337         }
338         delete imgstr;
339
340         return pixbufdata;
341 }
342
343 Thumb::~Thumb() {
344         delete thumbCM;
345         delete str;
346 }
347