~ubuntu-branches/debian/stretch/pngquant/stretch

« back to all changes in this revision

Viewing changes to pngquant.c

  • Committer: Package Import Robot
  • Author(s): Andreas Tille
  • Date: 2014-10-07 09:19:38 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20141007091938-jmu20wvmi6hd2nb3
Tags: 2.3.0-1
* New upstream version
* cme fix dpkg-control
* d/copyright: Fix some DEP5 names
* d/rules: cope with hand-written configure script

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* pngquant.c - quantize the colors in an alphamap down to a specified number
2
2
**
3
3
** Copyright (C) 1989, 1991 by Jef Poskanzer.
4
 
** Copyright (C) 1997, 2000, 2002 by Greg Roelofs; based on an idea by
5
 
**                                Stefan Schneider.
6
 
** © 2009-2013 by Kornel Lesinski.
7
4
**
8
5
** Permission to use, copy, modify, and distribute this software and its
9
6
** documentation for any purpose and without fee is hereby granted, provided
11
8
** copyright notice and this permission notice appear in supporting
12
9
** documentation.  This software is provided "as is" without express or
13
10
** implied warranty.
 
11
**
 
12
** - - - -
 
13
**
 
14
** © 1997-2002 by Greg Roelofs; based on an idea by Stefan Schneider.
 
15
** © 2009-2014 by Kornel Lesiński.
 
16
**
 
17
** All rights reserved.
 
18
**
 
19
** Redistribution and use in source and binary forms, with or without modification,
 
20
** are permitted provided that the following conditions are met:
 
21
**
 
22
** 1. Redistributions of source code must retain the above copyright notice,
 
23
**    this list of conditions and the following disclaimer.
 
24
**
 
25
** 2. Redistributions in binary form must reproduce the above copyright notice,
 
26
**    this list of conditions and the following disclaimer in the documentation
 
27
**    and/or other materials provided with the distribution.
 
28
**
 
29
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
30
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
31
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
32
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 
33
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
34
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
35
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
36
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
37
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
38
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
39
**
14
40
*/
15
41
 
16
 
#define PNGQUANT_VERSION "2.1.0 (February 2014)"
 
42
#define PNGQUANT_VERSION "2.3.0 (July 2014)"
17
43
 
18
44
#define PNGQUANT_USAGE "\
19
45
usage:  pngquant [options] [ncolors] [pngfile [pngfile ...]]\n\n\
21
47
  --force           overwrite existing output files (synonym: -f)\n\
22
48
  --nofs            disable Floyd-Steinberg dithering\n\
23
49
  --ext new.png     set custom suffix/extension for output filename\n\
 
50
  --output file     output path, only if one input file is specified (synonym: -o)\n\
24
51
  --speed N         speed/quality trade-off. 1=slow, 3=default, 11=fast & rough\n\
25
52
  --quality min-max don't save below min, use less colors below max (0-100)\n\
26
53
  --verbose         print status messages (synonym: -v)\n\
66
93
    void *log_callback_user_info;
67
94
    float floyd;
68
95
    bool using_stdin, force, fast_compression, ie_mode,
69
 
        min_quality_limit, skip_if_larger;
 
96
        min_quality_limit, skip_if_larger,
 
97
        verbose;
70
98
};
71
99
 
72
100
static pngquant_error prepare_output_image(liq_result *result, liq_image *input_image, png8_image *output_image);
73
101
static void set_palette(liq_result *result, png8_image *output_image);
74
 
static void pngquant_output_image_free(png8_image *output_image);
75
 
static pngquant_error read_image(liq_attr *options, const char *filename, int using_stdin, png24_image *input_image_p, liq_image **liq_image_p, bool keep_input_pixels);
 
102
static pngquant_error read_image(liq_attr *options, const char *filename, int using_stdin, png24_image *input_image_p, liq_image **liq_image_p, bool keep_input_pixels, bool verbose);
76
103
static pngquant_error write_image(png8_image *output_image, png24_image *output_image24, const char *outname, struct pngquant_options *options);
77
104
static char *add_filename_extension(const char *filename, const char *newext);
78
105
static bool file_exists(const char *outname);
111
138
    struct buffered_log *log = context;
112
139
    if (log->buf_used) {
113
140
        fwrite(log->buf, 1, log->buf_used, stderr);
 
141
        fflush(stderr);
114
142
        log->buf_used = 0;
115
143
    }
116
144
}
133
161
{
134
162
    fprintf(fd, "pngquant, %s, by Greg Roelofs, Kornel Lesinski.\n"
135
163
        #ifndef NDEBUG
136
 
                    "   DEBUG (slow) version.\n"
 
164
                    "   DEBUG (slow) version.\n" /* NDEBUG disables assert() */
 
165
        #endif
 
166
        #if USE_SSE
 
167
                    "   Compiled with SSE instructions.\n"
137
168
        #endif
138
169
        #if _OPENMP
139
170
                    "   Compiled with OpenMP (multicore support).\n"
255
286
    options.liq = liq_attr_create();
256
287
 
257
288
    if (!options.liq) {
258
 
        fputs("SSE2-capable CPU is required for this build.\n", stderr);
 
289
        fputs("SSE-capable CPU is required for this build.\n", stderr);
259
290
        return WRONG_ARCHITECTURE;
260
291
    }
261
292
 
270
301
        opt = getopt_long(argc, argv, "Vvqfhs:Q:o:", long_options, NULL);
271
302
        switch (opt) {
272
303
            case 'v':
273
 
                liq_set_log_callback(options.liq, log_callback, NULL);
274
 
                options.log_callback = log_callback;
 
304
                options.verbose = true;
275
305
                break;
276
306
            case 'q':
277
 
                liq_set_log_callback(options.liq, NULL, NULL);
278
 
                options.log_callback = NULL;
 
307
                options.verbose = false;
279
308
                break;
280
309
 
281
310
            case arg_floyd:
282
311
                options.floyd = optarg ? atof(optarg) : 1.0;
283
 
                if (options.floyd < 0 || options.floyd > 1.0) {
 
312
                if (options.floyd < 0 || options.floyd > 1.f) {
284
313
                    fputs("--floyd argument must be in 0..1 range\n", stderr);
285
314
                    return INVALID_ARGUMENT;
286
315
                }
287
316
                break;
288
317
            case arg_ordered: options.floyd = 0; break;
 
318
 
289
319
            case 'f': options.force = true; break;
290
320
            case arg_no_force: options.force = false; break;
291
321
 
345
375
            case arg_map:
346
376
                {
347
377
                    png24_image tmp = {};
348
 
                    if (SUCCESS != read_image(options.liq, optarg, false, &tmp, &options.fixed_palette_image, false)) {
 
378
                    if (SUCCESS != read_image(options.liq, optarg, false, &tmp, &options.fixed_palette_image, false, false)) {
349
379
                        fprintf(stderr, "  error: Unable to load %s", optarg);
350
380
                        return INVALID_ARGUMENT;
351
381
                    }
380
410
        return MISSING_ARGUMENT;
381
411
    }
382
412
 
 
413
    if (options.verbose) {
 
414
        liq_set_log_callback(options.liq, log_callback, NULL);
 
415
        options.log_callback = log_callback;
 
416
    }
 
417
 
383
418
    char *colors_end;
384
419
    unsigned long colors = strtoul(argv[argn], &colors_end, 10);
385
420
    if (colors_end != argv[argn] && '\0' == colors_end[0]) {
398
433
    // new filename extension depends on options used. Typically basename-fs8.png
399
434
    if (newext == NULL) {
400
435
        newext = options.floyd > 0 ? "-ie-fs8.png" : "-ie-or8.png";
401
 
        if (!options.ie_mode) newext += 3; /* skip "-ie" */
 
436
        if (!options.ie_mode) {
 
437
            newext += 3;    /* skip "-ie" */
 
438
        }
402
439
    }
403
440
 
404
441
    if (argn == argc || (argn == argc-1 && 0==strcmp(argv[argn],"-"))) {
429
466
#endif
430
467
 
431
468
    #pragma omp parallel for \
432
 
        schedule(dynamic) reduction(+:skipped_count) reduction(+:error_count) reduction(+:file_count) shared(latest_error)
 
469
        schedule(static, 1) reduction(+:skipped_count) reduction(+:error_count) reduction(+:file_count) shared(latest_error)
433
470
    for(int i=0; i < num_files; i++) {
434
471
        struct pngquant_options opts = options;
435
472
        opts.liq = liq_attr_copy(options.liq);
502
539
    return latest_error;
503
540
}
504
541
 
505
 
 
506
 
static void pngquant_output_image_free(png8_image *output_image)
507
 
{
508
 
    free(output_image->indexed_data);
509
 
    output_image->indexed_data = NULL;
510
 
 
511
 
    free(output_image->row_pointers);
512
 
    output_image->row_pointers = NULL;
513
 
}
514
 
 
515
542
pngquant_error pngquant_file(const char *filename, const char *outname, struct pngquant_options *options)
516
543
{
517
544
    pngquant_error retval = SUCCESS;
522
549
    png24_image input_image_rwpng = {};
523
550
    bool keep_input_pixels = options->skip_if_larger || (options->using_stdin && options->min_quality_limit); // original may need to be output to stdout
524
551
    if (!retval) {
525
 
        retval = read_image(options->liq, filename, options->using_stdin, &input_image_rwpng, &input_image, keep_input_pixels);
 
552
        retval = read_image(options->liq, filename, options->using_stdin, &input_image_rwpng, &input_image, keep_input_pixels, options->verbose);
526
553
    }
527
554
 
528
555
    int quality_percent = 90; // quality on 0-100 scale, updated upon successful remap
529
556
    png8_image output_image = {};
530
557
    if (!retval) {
531
 
        verbose_printf(options, "  read %luKB file corrected for gamma %2.1f",
532
 
                       (input_image_rwpng.file_size+1023UL)/1024UL, 1.0/input_image_rwpng.gamma);
 
558
        verbose_printf(options, "  read %luKB file", (input_image_rwpng.file_size+1023UL)/1024UL);
 
559
 
 
560
#if USE_LCMS
 
561
        if (input_image_rwpng.lcms_status == ICCP) {
 
562
            verbose_printf(options, "  used embedded ICC profile to transform image to sRGB colorspace");
 
563
        } else if (input_image_rwpng.lcms_status == GAMA_CHRM) {
 
564
            verbose_printf(options, "  used gAMA and cHRM chunks to transform image to sRGB colorspace");
 
565
        } else if (input_image_rwpng.lcms_status == ICCP_WARN_GRAY) {
 
566
            verbose_printf(options, "  warning: ignored ICC profile in GRAY colorspace");
 
567
        }
 
568
#endif
 
569
 
 
570
        if (input_image_rwpng.gamma != 0.45455) {
 
571
            verbose_printf(options, "  corrected image from gamma %2.1f to sRGB gamma",
 
572
                           1.0/input_image_rwpng.gamma);
 
573
        }
533
574
 
534
575
        // when using image as source of a fixed palette the palette is extracted using regular quantization
535
576
        liq_result *remap = liq_quantize_image(options->liq, options->fixed_palette_image ? options->fixed_palette_image : input_image);
568
609
        }
569
610
 
570
611
        output_image.fast_compression = options->fast_compression;
 
612
        output_image.chunks = input_image_rwpng.chunks; input_image_rwpng.chunks = NULL;
571
613
        retval = write_image(&output_image, NULL, outname, options);
572
614
 
573
615
        if (TOO_LARGE_FILE == retval) {
580
622
        // so if quality is too low, output 24-bit original
581
623
        if (keep_input_pixels) {
582
624
            pngquant_error write_retval = write_image(NULL, &input_image_rwpng, outname, options);
583
 
            if (write_retval) retval = write_retval;
 
625
            if (write_retval) {
 
626
                retval = write_retval;
 
627
            }
584
628
        }
585
629
    }
586
630
 
587
631
    liq_image_destroy(input_image);
588
 
    pngquant_output_image_free(&output_image);
589
 
 
590
 
    free(input_image_rwpng.row_pointers);
591
 
    free(input_image_rwpng.rgba_data);
 
632
    rwpng_free_image24(&input_image_rwpng);
 
633
    rwpng_free_image8(&output_image);
592
634
 
593
635
    return retval;
594
636
}
667
709
        }
668
710
 
669
711
        const char *outfilename = strrchr(outname, '/');
670
 
        if (outfilename) outfilename++; else outfilename = outname;
 
712
        if (outfilename) {
 
713
            outfilename++;
 
714
        } else {
 
715
            outfilename = outname;
 
716
        }
671
717
 
672
718
        if (output_image) {
673
719
            verbose_printf(options, "  writing %d-color image as %s", output_image->num_palette, outfilename);
690
736
        fprintf(stderr, "  error: failed writing image to %s\n", outname);
691
737
    }
692
738
 
693
 
    if (!options->using_stdin)
 
739
    if (!options->using_stdin) {
694
740
        fclose(outfile);
 
741
    }
695
742
 
696
743
    return retval;
697
744
}
698
745
 
699
 
static pngquant_error read_image(liq_attr *options, const char *filename, int using_stdin, png24_image *input_image_p, liq_image **liq_image_p, bool keep_input_pixels)
 
746
static pngquant_error read_image(liq_attr *options, const char *filename, int using_stdin, png24_image *input_image_p, liq_image **liq_image_p, bool keep_input_pixels, bool verbose)
700
747
{
701
748
    FILE *infile;
702
749
 
711
758
    pngquant_error retval;
712
759
    #pragma omp critical (libpng)
713
760
    {
714
 
        retval = rwpng_read_image24(infile, input_image_p);
 
761
        retval = rwpng_read_image24(infile, input_image_p, verbose);
715
762
    }
716
763
 
717
 
    if (!using_stdin)
 
764
    if (!using_stdin) {
718
765
        fclose(infile);
 
766
    }
719
767
 
720
768
    if (retval) {
721
769
        fprintf(stderr, "  error: rwpng_read_image() error %d\n", retval);