~ubuntu-branches/ubuntu/trusty/netpbm-free/trusty

« back to all changes in this revision

Viewing changes to ppm/ppmtowinicon.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2004-07-29 20:25:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040729202546-9o69r65403wvtla5
Tags: 2:10.0-5
* build-depends against libtiff4.
* fix typo in ppmtowinicon. Closes: #261999.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* ppmtowinicon.c - read portable pixmap file(s) and write a MS Windows .ico
2
2
**
3
 
** Copyright (C) 2000 by Lee Benfield - lee@recoil.org
 
3
** Copyright (C) 2000 by Lee Benfield - lee@benf.org
4
4
**
5
5
** Permission to use, copy, modify, and distribute this software and its
6
6
** documentation for any purpose and without fee is hereby granted, provided
14
14
 * Changelog
15
15
 *
16
16
 * 2002/01/25 - Use pbm instead of ppm for alpha maps and fix alpha
17
 
 *              sense. (black = transparent, white = opaque).
18
 
 *              Option renamed to -andpbms; -andppms retained
19
 
 *              for compatibility.
20
 
 *              ppmtowinicon should now be the true reverse of winicontoppm.
21
 
 *              Filled some "ignored" fields in ICO output for maximum
22
 
 *              compatibility.  MVB.
 
17
 *      sense. (black = transparent, white = opaque).
 
18
 *      Option renamed to -andpbms; -andppms retained
 
19
 *      for compatibility.
 
20
 *      ppmtowinicon should now be the true reverse of winicontoppm.
 
21
 *      Filled some "ignored" fields in ICO output for maximum
 
22
 *      compatibility.  MVB.
23
23
 *
24
24
 * 2000/05/24 - using colorhash_table instead of a straight array search
25
25
 *              Though it's a little slower for files due to the low # of
28
28
 
29
29
#include <string.h>
30
30
#include <math.h>
 
31
#include <string.h>
 
32
 
31
33
#include "winico.h"
32
34
#include "ppm.h"
33
35
#include "ppmcmap.h"
45
47
static int      file_offset = 0;    /* not actually used, but useful for debug. */
46
48
static int      readFromStdin = 0;
47
49
static char     er_write[] = "%s: write error";
48
 
static char *   infname  = "";
49
 
static char *   outfname = "-";
 
50
static const char *   infname  = "";
 
51
static const char *   outfname = "-";
50
52
static FILE *   ofp;
51
53
static FILE *   ifp;
52
54
 
55
57
   
56
58
   if (putc(v, ofp) == EOF)
57
59
     {
58
 
        pm_error(er_write, outfname);
 
60
    pm_error(er_write, outfname);
59
61
     }
60
62
}
61
63
   
64
66
   
65
67
   if (pm_writelittleshort(ofp, v) == -1)
66
68
     {
67
 
        pm_error(er_write, outfname);
 
69
    pm_error(er_write, outfname);
68
70
     }
69
71
   
70
72
}
74
76
   
75
77
   if (pm_writelittlelong(ofp, v) == -1)
76
78
     {
77
 
        pm_error(er_write, outfname);
 
79
    pm_error(er_write, outfname);
78
80
     }
79
81
   
80
82
}
89
91
   PutByte(v);
90
92
}
91
93
 
92
 
static void 
93
 
writeU1String (char * const string, int const length) {
94
 
   fwrite(string,sizeof(u1),length,ofp);
95
 
   file_offset += length;
96
 
}
97
 
 
98
94
static  void 
99
95
writeU2 (u2 const v) {
100
96
   file_offset +=2;
110
106
static MS_Ico 
111
107
createIconFile (void) {
112
108
   MS_Ico MSIconData = malloc( sizeof (* MSIconData) );
 
109
 
 
110
   if (MSIconData == NULL)
 
111
       pm_error("out of memory");
 
112
 
113
113
   MSIconData->reserved     = 0;
114
114
   MSIconData->type         = 1;
115
115
   MSIconData->count        = 0;
131
131
   int xBytes,y,x;
132
132
   int wt = cols;
133
133
   u1 ** rowData;
 
134
   if (icBitmap == NULL)
 
135
        pm_error("out of memory");
134
136
   wt >>= 3;
135
137
   if (wt & 3) {
136
138
      wt = (wt & ~3) + 4;
137
139
   }
138
140
   xBytes = wt;
139
141
   rowData = malloc2 ( rows , sizeof (char *));
 
142
   if (rowData == NULL)
 
143
        pm_error("out of memory");
140
144
   icBitmap->xBytes = xBytes;
141
145
   icBitmap->data   = rowData;
142
146
   overflow2(xBytes, rows);
145
149
      u1 * row = malloc2 ( xBytes, sizeof (u1));
146
150
      int byteOn = 0;
147
151
      int bitOn = 128;
 
152
      if (row == NULL)
 
153
          pm_error("out of memory");
148
154
      memset (row, 0, xBytes);
149
155
      rowData[rows-y-1] = row;
150
156
      /* 
151
157
       * Check there's a bit array, otherwise we're just faking this...
152
158
       */
153
159
      if (ba) {
154
 
         for (x=0;x<cols;x++) {
 
160
         for (x=0;x<cols;x++) {
155
161
            /* Black (bit clear) is transparent in PGM alpha maps,
156
162
             * in ICO bit *set* is transparent.
157
163
             */
158
164
            if (ba[y][x] <= maxval/2) row[byteOn] |= bitOn;
159
165
 
160
 
            if (bitOn == 1) {
161
 
               byteOn++;
162
 
               bitOn = 128;
163
 
            } else {
164
 
               bitOn >>= 1;
165
 
            }
166
 
         }
 
166
            if (bitOn == 1) {
 
167
               byteOn++;
 
168
               bitOn = 128;
 
169
            } else {
 
170
               bitOn >>= 1;
 
171
            }
 
172
         }
167
173
      }
168
174
   }
169
175
   return icBitmap;
192
198
   int xBytes,y,x;
193
199
   int wt = cols;
194
200
   u1 ** rowData;
 
201
   if (icBitmap == NULL)
 
202
        pm_error("out of memory");
195
203
   wt >>= 3;
196
204
   if (wt & 3) {
197
205
      wt = (wt & ~3) + 4;
198
206
   }
199
207
   xBytes = wt;
200
208
   rowData = malloc2 ( rows,  sizeof (char *));
 
209
   if (rowData == NULL)
 
210
        pm_error("out of memory");
201
211
   icBitmap->xBytes = xBytes;
202
212
   icBitmap->data   = rowData;
 
213
   overflow2(xBytes, rows);
203
214
   icBitmap->size   = xBytes * rows;
204
215
   for (y=0;y<rows;y++) {
205
216
      u1 * row = malloc2 ( xBytes , sizeof (u1));
206
217
      int byteOn = 0;
207
218
      int bitOn = 128;
208
219
      int value;
 
220
      if (row == NULL)
 
221
         pm_error("out of memory");
209
222
      memset (row, 0, xBytes);
210
223
      rowData[rows-y-1] = row;
211
224
      /* 
212
225
       * Check there's a pixel array, otherwise we're just faking this...
213
226
       */
214
227
      if (pa) {
215
 
         for (x=0;x<cols;x++) {
216
 
            /*
217
 
             * So we've got a colorhash_table with two colors in it.
218
 
             * Which is black?!
219
 
             * 
220
 
             * Unless the hashing function changes, 0's black.
221
 
             */
222
 
            value = ppm_lookupcolor(cht, &pa[y][x]);
223
 
            if (!value) {
224
 
               /* leave black. */
225
 
            } else {
226
 
               row[byteOn] |= bitOn;
227
 
            }
228
 
            if (bitOn == 1) {
229
 
               byteOn++;
230
 
               bitOn = 128;
231
 
            } else {
232
 
               bitOn >>= 1;
233
 
            }
234
 
         }
 
228
         for (x=0;x<cols;x++) {
 
229
            /*
 
230
             * So we've got a colorhash_table with two colors in it.
 
231
             * Which is black?!
 
232
             * 
 
233
             * Unless the hashing function changes, 0's black.
 
234
             */
 
235
            value = ppm_lookupcolor(cht, &pa[y][x]);
 
236
            if (!value) {
 
237
               /* leave black. */
 
238
            } else {
 
239
               row[byteOn] |= bitOn;
 
240
            }
 
241
            if (bitOn == 1) {
 
242
               byteOn++;
 
243
               bitOn = 128;
 
244
            } else {
 
245
               bitOn >>= 1;
 
246
            }
 
247
         }
235
248
      }
236
249
   }
237
250
   return icBitmap;
249
262
   int xBytes,y,x;
250
263
   int wt = cols;
251
264
   u1 ** rowData;
 
265
   if (icBitmap == NULL)
 
266
        pm_error("out of memory");
252
267
   wt >>= 1;
253
268
   if (wt & 3) {
254
269
      wt = (wt & ~3) + 4;
255
270
   }
256
271
   xBytes = wt;
257
272
   rowData = malloc2 ( rows , sizeof (char *));
 
273
   if (rowData == NULL)
 
274
        pm_error("out of memory");
258
275
   icBitmap->xBytes = xBytes;
259
276
   icBitmap->data   = rowData;
260
277
   overflow2(xBytes, rows);
261
278
   icBitmap->size   = xBytes * rows;
262
 
   overflow2(xBytes, rows);
263
279
 
264
280
   for (y=0;y<rows;y++) {
265
281
      u1 * row = malloc2 ( xBytes, sizeof (u1));
266
282
      int byteOn = 0;
267
283
      int nibble = 1;   /* high nibble = 1, low nibble = 0; */
268
284
      int value;
 
285
      if (row == NULL)
 
286
         pm_error("out of memory");
269
287
      memset (row, 0, xBytes);
270
288
      rowData[rows-y-1] = row;
271
289
      /* 
272
290
       * Check there's a pixel array, otherwise we're just faking this...
273
291
       */
274
292
      if (pa) {
275
 
         for (x=0;x<cols;x++) {
276
 
            value = ppm_lookupcolor(cht, &pa[y][x]);
277
 
            /*
278
 
             * Shift it, if we're putting it in the high nibble.
279
 
             */
280
 
            if (nibble) {
281
 
               value <<= 4;
282
 
            }
283
 
            row[byteOn] |= value;
284
 
            if (nibble) {
285
 
               nibble = 0;
286
 
            } else {
287
 
               nibble = 1;
288
 
               byteOn++;
289
 
            }
290
 
         }
 
293
         for (x=0;x<cols;x++) {
 
294
            value = ppm_lookupcolor(cht, &pa[y][x]);
 
295
            /*
 
296
             * Shift it, if we're putting it in the high nibble.
 
297
             */
 
298
            if (nibble) {
 
299
               value <<= 4;
 
300
            }
 
301
            row[byteOn] |= value;
 
302
            if (nibble) {
 
303
               nibble = 0;
 
304
            } else {
 
305
               nibble = 1;
 
306
               byteOn++;
 
307
            }
 
308
         }
291
309
      }
292
310
   }
293
311
   return icBitmap;
306
324
   int xBytes,y,x;
307
325
   int wt = cols;
308
326
   u1 ** rowData;
 
327
   if (icBitmap == NULL)
 
328
        pm_error("out of memory");
309
329
   if (wt & 3) {
310
330
      wt = (wt & ~3) + 4;
311
331
   }
312
332
   xBytes = wt;
313
333
   rowData = malloc2 ( rows,  sizeof (char *));
 
334
   if (rowData == NULL)
 
335
        pm_error("out of memory");
314
336
   icBitmap->xBytes = xBytes;
315
337
   icBitmap->data   = rowData;
 
338
   overflow2(xBytes, rows);
316
339
   icBitmap->size   = xBytes * rows;
317
 
   overflow2(xBytes, rows);
318
340
 
319
341
   for (y=0;y<rows;y++) {
320
342
      u1 * row = malloc2 ( xBytes, sizeof (u1));
 
343
      if (row == NULL)
 
344
         pm_error("out of memory");
321
345
      memset (row, 0, xBytes);
322
346
      rowData[rows-y-1] = row;
323
347
      /* 
324
348
       * Check there's a pixel array, otherwise we're just faking this...
325
349
       */
326
350
      if (pa) {
327
 
         for (x=0;x<cols;x++) {
328
 
            row[x] = ppm_lookupcolor(cht, &pa[y][x]);
329
 
         }
 
351
         for (x=0;x<cols;x++) {
 
352
            row[x] = ppm_lookupcolor(cht, &pa[y][x]);
 
353
         }
330
354
      }
331
355
   }
332
356
   return icBitmap;
338
362
createInfoHeader(IC_Entry const entry, ICON_bmp const xbmp,
339
363
                 ICON_bmp const abmp) {
340
364
   IC_InfoHeader ih  = malloc ( sizeof (* ih) );
 
365
   if (ih == NULL)
 
366
       pm_error("out of memory");
 
367
 
341
368
   ih->size          = 40;
342
369
   ih->width         = entry->width;
343
370
   ih->height        = entry->height * 2;  
358
385
createCleanPalette(void) {
359
386
   IC_Palette palette = malloc ( sizeof (* palette) );
360
387
   int x;
361
 
   palette->colors = malloc(MAXCOLORS * sizeof(IC_Color *));
 
388
   if (palette == NULL)
 
389
        pm_error("out of memory");
 
390
   palette->colors = malloc2 (MAXCOLORS, sizeof(IC_Color *));
 
391
   if (palette->colors == NULL)
 
392
        pm_error("out of memory");
 
393
 
362
394
   for (x=0;x<MAXCOLORS;x++ ){
363
395
      palette->colors[x] = NULL;
364
396
   }
371
403
addColorToPalette(IC_Palette const palette, int const i,
372
404
                  int const r, int const g, int const b) {
373
405
   palette->colors[i] = malloc ( sizeof (* palette->colors[i]) );
374
 
   palette->colors[i]->red      = r;
375
 
   palette->colors[i]->green    = g;
376
 
   palette->colors[i]->blue     = b;
377
 
   palette->colors[i]->reserved = 0;
 
406
    if (palette->colors[i] == NULL)
 
407
        pm_error("out of memory");
 
408
 
 
409
    palette->colors[i]->red      = r;
 
410
    palette->colors[i]->green    = g;
 
411
    palette->colors[i]->blue     = b;
 
412
    palette->colors[i]->reserved = 0;
378
413
}
379
414
 
380
415
 
405
440
 
406
441
 
407
442
static void 
408
 
addEntryToIcon (MS_Ico const MSIconData, char * const xorPPM,
409
 
                char * const andPGM) {
 
443
addEntryToIcon (MS_Ico const MSIconData, const char * const xorPPM,
 
444
                const char * const andPGM) {
410
445
 
411
446
   IC_Entry entry = malloc ( sizeof (* entry) );
412
447
   FILE * xorfile;
425
460
   
426
461
   pixval xorMaxval;
427
462
   gray andMaxval;
 
463
   if (entry == NULL)
 
464
       pm_error("out of memory");
 
465
 
428
466
   /*
429
467
    * Read the xor PPM.
430
468
    */
450
488
   xorChv = ppm_computecolorhist(xorPPMarray, xorCols, xorRows, MAXCOLORS, 
451
489
                                 &colors);
452
490
   if (xorChv == (colorhist_vector) 0)
453
 
     pm_error("%s has too many colors - try doing a 'ppmquant %d'"
454
 
              , xorPPM, MAXCOLORS);
 
491
     pm_error("%s has too many colors - try doing a 'pnmquant %d'"
 
492
          , xorPPM, MAXCOLORS);
455
493
   if (verbose) pm_message("%d colors found", colors);
456
494
 
457
495
   if (verbose && (xorMaxval > 255))
458
496
       pm_message("maxval is not 255 - automatically rescaling colors");
459
497
   for (i = 0; i < colors; ++i)
460
498
     {
461
 
        if (xorMaxval == 255)
462
 
          {
463
 
             addColorToPalette(palette,i,
464
 
                               PPM_GETR(xorChv[i].color),
465
 
                               PPM_GETG(xorChv[i].color),
466
 
                               PPM_GETB(xorChv[i].color));
467
 
          }
468
 
        else
469
 
          {
470
 
             addColorToPalette(palette,i,
471
 
                               PPM_GETR(xorChv[i].color) * 255 / xorMaxval,
472
 
                               PPM_GETG(xorChv[i].color) * 255 / xorMaxval,
473
 
                               PPM_GETB(xorChv[i].color) * 255 / xorMaxval);
474
 
          }
 
499
    if (xorMaxval == 255)
 
500
      {
 
501
         addColorToPalette(palette,i,
 
502
                   PPM_GETR(xorChv[i].color),
 
503
                   PPM_GETG(xorChv[i].color),
 
504
                   PPM_GETB(xorChv[i].color));
 
505
      }
 
506
    else
 
507
      {
 
508
         addColorToPalette(palette,i,
 
509
                   PPM_GETR(xorChv[i].color) * 255 / xorMaxval,
 
510
                   PPM_GETG(xorChv[i].color) * 255 / xorMaxval,
 
511
                   PPM_GETB(xorChv[i].color) * 255 / xorMaxval);
 
512
      }
475
513
     }
476
514
   
477
515
   /* And make a hash table for fast lookup. */
643
681
   for (x=0;x<MSIconData->count;x++) {
644
682
      writeIC_InfoHeader(MSIconData->entries[x]->ih);
645
683
      for (y=0;y<(MSIconData->entries[x]->color_count);y++) {
646
 
         writeIC_Color(MSIconData->entries[x]->colors[y]);
 
684
     writeIC_Color(MSIconData->entries[x]->colors[y]);
647
685
      }
648
686
      if (verbose) pm_message("writing xor bitmap\n");
649
687
      writeBitmap(MSIconData->entries[x]->xorBitmapOut,
660
698
 
661
699
 
662
700
int 
663
 
main (int argc, char ** argv) {
664
 
   MS_Ico MSIconData = createIconFile();
665
 
   int iconOn = 1;
666
 
   int argn;
667
 
   int offset;
668
 
   char * usage = "[-andppms] [-output output.ico] [icon1.ppm icon2.ppm ... ]";
669
 
   
670
 
   /*
671
 
    * usage:
672
 
    * 
673
 
    * ppmtowinicon [-andppms] icon1.ppm [icon2.ppm icon3.ppm ... ] output.ico
674
 
    * 
675
 
    * Use -a flag if you supply your own and bitmaps.
676
 
    */
677
 
   ppm_init ( &argc, argv);
678
 
   /*
679
 
    * Parse command line arguments.
680
 
    */
681
 
   argn = 1;
682
 
   while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
683
 
      if (pm_keymatch(argv[argn], "-verbose", 2))
684
 
        verbose++;
685
 
      else if (pm_keymatch(argv[argn], "-andpgms", 2) 
686
 
               || pm_keymatch(argv[argn], "-andppms", 2)) {
687
 
        readAndMaps++;
688
 
      }
689
 
      else if (pm_keymatch(argv[argn], "-output", 2)) {
690
 
         if (argc - argn > 1) {
691
 
            outfname = argv[argn+1];
692
 
            argn++;
693
 
         } else {
694
 
            pm_error ("-output must be supplied a filename");
695
 
         }
696
 
      }
697
 
      else pm_usage(usage);
698
 
      ++argn;
699
 
   }
700
 
   
701
 
   if (argn < argc) {
702
 
      /*
703
 
       * If there's cmd line args left over, fine. 
704
 
       * Use them later.
705
 
       */
706
 
   } else {
707
 
      ifp = stdin;
708
 
      infname = "noname";
709
 
      readFromStdin++;
710
 
   }
 
701
main(int argc, char ** argv) {
 
702
    MS_Ico MSIconData = createIconFile();
 
703
    int iconOn = 1;
 
704
    int argn;
 
705
    int offset;
 
706
   
 
707
    ppm_init ( &argc, argv);
 
708
    /*
 
709
     * Parse command line arguments.
 
710
     */
 
711
    argn = 1;
 
712
    while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
 
713
        if (pm_keymatch(argv[argn], "-verbose", 2))
 
714
            verbose++;
 
715
        else if (pm_keymatch(argv[argn], "-andpgms", 2) 
 
716
                 || pm_keymatch(argv[argn], "-andppms", 2)) {
 
717
            readAndMaps++;
 
718
        }
 
719
        else if (pm_keymatch(argv[argn], "-output", 2)) {
 
720
            if (argc - argn > 1) {
 
721
                outfname = argv[argn+1];
 
722
                argn++;
 
723
            } else {
 
724
                pm_error ("-output must be supplied a filename");
 
725
            }
 
726
        }
 
727
        else pm_error("Invalid option '%s'", argv[argn]);
 
728
        ++argn;
 
729
    }
 
730
   
 
731
    if (argn < argc) {
 
732
        /*
 
733
         * If there's cmd line args left over, fine. 
 
734
         * Use them later.
 
735
         */
 
736
    } else {
 
737
        ifp = stdin;
 
738
        infname = "noname";
 
739
        readFromStdin++;
 
740
    }
711
741
 
712
742
   
713
 
   if (readFromStdin) {
714
 
      addEntryToIcon(MSIconData, "-", "");
715
 
      if (verbose) pm_message ("Added entry from stdin.\n");
716
 
   } else {
717
 
      /*
718
 
       * If we're not using fake and maps, then we skip 1 each time.
719
 
       */
720
 
      for ( iconOn = argn; iconOn < argc ; iconOn += (readAndMaps ? 2 : 1) ) {
721
 
         char * xorPPM;
722
 
         char * andPPM;
723
 
         xorPPM = argv[iconOn];
724
 
         andPPM = (readAndMaps ? argv[iconOn+1] : "");
725
 
         addEntryToIcon(MSIconData, xorPPM, andPPM);
726
 
      }
727
 
   }
728
 
   /*
729
 
    * Now we have to go through and calculate the offsets.
730
 
    * The first infoheader starts at 6 + count*16 bytes.
731
 
    */
732
 
   offset = (MSIconData->count * 16) + 6;
733
 
   for ( iconOn = 0; iconOn < MSIconData->count; iconOn++ ) {
734
 
      IC_Entry entry = MSIconData->entries[iconOn];
735
 
      entry->file_offset = offset;
736
 
      /* 
737
 
       * Increase the offset by the size of this offset & data.
738
 
       * this includes the size of the color data.
739
 
       */
740
 
      offset += entry->size_in_bytes;
741
 
   }
742
 
   /*
743
 
    * And now, we have to actually SAVE the .ico!
744
 
    */
745
 
   writeMS_Ico(MSIconData,argv[argc-1]);
746
 
   return 0;
 
743
    if (readFromStdin) {
 
744
        addEntryToIcon(MSIconData, "-", "");
 
745
        if (verbose) pm_message ("Added entry from stdin.\n");
 
746
    } else {
 
747
        /*
 
748
         * If we're not using fake and maps, then we skip 1 each time.
 
749
         */
 
750
        for ( iconOn = argn; 
 
751
              iconOn < argc ; 
 
752
              iconOn += (readAndMaps ? 2 : 1) ) {
 
753
            const char * xorPPM;
 
754
            const char * andPPM;
 
755
            xorPPM = argv[iconOn];
 
756
            andPPM = (readAndMaps ? argv[iconOn+1] : "");
 
757
            addEntryToIcon(MSIconData, xorPPM, andPPM);
 
758
        }
 
759
    }
 
760
    /*
 
761
     * Now we have to go through and calculate the offsets.
 
762
     * The first infoheader starts at 6 + count*16 bytes.
 
763
     */
 
764
    offset = (MSIconData->count * 16) + 6;
 
765
    for ( iconOn = 0; iconOn < MSIconData->count; iconOn++ ) {
 
766
        IC_Entry entry = MSIconData->entries[iconOn];
 
767
        entry->file_offset = offset;
 
768
        /* 
 
769
         * Increase the offset by the size of this offset & data.
 
770
         * this includes the size of the color data.
 
771
         */
 
772
        offset += entry->size_in_bytes;
 
773
    }
 
774
    /*
 
775
     * And now, we have to actually SAVE the .ico!
 
776
     */
 
777
    writeMS_Ico(MSIconData,argv[argc-1]);
 
778
    return 0;
747
779
}