Exemple #1
0
int handle_decode(char **argv, Images &images, int quality, int scale) {
    char *ext = strrchr(argv[1],'.');
    if (!check_compatible_extension(ext)) {
        e_printf("Error: expected \".png\", \".pnm\" or \".pam\" file name extension for output file\n");
        return 1;
    }
    if (!decode_flif(argv, images, quality, scale)) return 3;
    if (scale>1)
        v_printf(3,"Downscaling output: %ux%u -> %ux%u\n",images[0].cols(),images[0].rows(),images[0].cols()/scale,images[0].rows()/scale);
    if (images.size() == 1) {
        if (!images[0].save(argv[1],scale)) return 2;
    } else {
        int counter=0;
        std::vector<char> vfilename(strlen(argv[1])+6);
        char *filename = &vfilename[0];
        strcpy(filename,argv[1]);
        char *a_ext = strrchr(filename,'.');
        for (Image& image : images) {
            sprintf(a_ext,"-%03d%s",counter++,ext);
            if (!image.save(filename,scale)) return 2;
            v_printf(2,"    (%i/%i)         \r",counter,(int)images.size()); v_printf(4,"\n");
        }
    }
    v_printf(2,"\n");
    return -1;
}
Exemple #2
0
int handle_decode(int argc, char **argv, Images &images, int quality, int scale, int resize_width, int resize_height) {
    if (scale < 0) {
        // just identify the file(s), don't actually decode
        while (argc>0) {
            decode_flif(argv, images, quality, scale, resize_width, resize_height);
            argv++; argc--;
        }
        return 0;
    }
    char *ext = strrchr(argv[1],'.');
    if (!check_compatible_extension(ext) && strcmp(argv[1],"null:")) {
        e_printf("Error: expected \".png\", \".pnm\" or \".pam\" file name extension for output file\n");
        return 1;
    }
    if (!decode_flif(argv, images, quality, scale, resize_width, resize_height)) {
        e_printf("Error: could not decode FLIF file\n"); return 3;
    }
    if (!strcmp(argv[1],"null:")) return 0;
//    if (scale>1)
//        v_printf(3,"Downscaling output: %ux%u -> %ux%u\n",images[0].cols(),images[0].rows(),images[0].cols()/scale,images[0].rows()/scale);
    if (images.size() == 1) {
        if (!images[0].save(argv[1])) return 2;
    } else {
        int counter=0;
        std::vector<char> vfilename(strlen(argv[1])+6);
        char *filename = &vfilename[0];
        strcpy(filename,argv[1]);
        char *a_ext = strrchr(filename,'.');
        for (Image& image : images) {
            sprintf(a_ext,"-%03d%s",counter++,ext);
            if (!image.save(filename)) return 2;
            v_printf(2,"    (%i/%i)         \r",counter,(int)images.size()); v_printf(4,"\n");
        }
    }
    v_printf(2,"\n");
    return 0;
}
Exemple #3
0
int main(int argc, char **argv)
{
    Images images;
#ifdef HAS_ENCODER
    int mode = 0; // 0 = encode, 1 = decode, 2 = transcode
    flifEncodingOptional method;
    int learn_repeats = -1;
    int acb = -1; // try auto color buckets
    std::vector<int> frame_delay;
    frame_delay.push_back(100);
    int palette_size = -1;
    int lookback = 1;
    int divisor=CONTEXT_TREE_COUNT_DIV;
    int min_size=CONTEXT_TREE_MIN_SUBTREE_SIZE;
    int split_threshold=CONTEXT_TREE_SPLIT_THRESHOLD;
    int yiq = 1;
    int plc = 1;
    int frs = 1;
    bool alpha_zero_special = true;
    int alpha=19;
    int cutoff=2;
#else
    int mode = 1;
#endif
    int quality = 100; // 100 = everything, positive value: partial decode, negative value: only rough data
    int scale = 1;
    int resize_width = 0, resize_height = 0;
    bool showhelp = false;
    if (strcmp(argv[0],"flif") == 0) mode = 0;
    if (strcmp(argv[0],"dflif") == 0) mode = 1;
    if (strcmp(argv[0],"deflif") == 0) mode = 1;
    if (strcmp(argv[0],"decflif") == 0) mode = 1;
    static struct option optlist[] = {
        {"help", 0, NULL, 'h'},
        {"decode", 0, NULL, 'd'},
        {"verbose", 0, NULL, 'v'},
        {"quality", 1, NULL, 'q'},
        {"scale", 1, NULL, 's'},
        {"resize", 1, NULL, 'r'},
        {"identify", 0, NULL, 'i'},
        {"version", 0, NULL, 'V'},
#ifdef HAS_ENCODER
        {"encode", 0, NULL, 'e'},
        {"transcode", 0, NULL, 't'},
        {"interlace", 0, NULL, 'I'},
        {"no-interlace", 0, NULL, 'N'},
        {"frame-delay", 1, NULL, 'F'},
        {"keep-invisible-rgb", 0, NULL, 'K'},
        {"max-palette-size", 1, NULL, 'P'},
        {"force-color-buckets", 0, NULL, 'A'},
        {"no-color-buckets", 0, NULL, 'B'},
        {"no-ycocg", 0, NULL, 'Y'},
        {"no-channel-compact", 0, NULL, 'C'},
        {"max-frame-lookback", 1, NULL, 'L'},
        {"no-frame-shape", 0, NULL, 'S'},
        {"maniac-repeats", 1, NULL, 'R'},
        {"maniac-divisor", 1, NULL, 'D'},
        {"maniac-min-size", 1, NULL, 'M'},
        {"maniac-threshold", 1, NULL, 'T'},
        {"chance-cutoff", 1, NULL, 'X'},
        {"chance-alpha", 1, NULL, 'Z'},
#endif
        {0, 0, 0, 0}
    };
    int i,c;
#ifdef HAS_ENCODER
    while ((c = getopt_long (argc, argv, "hdviVq:s:r:etINnF:KP:ABYCL:SR:D:M:T:X:Z:", optlist, &i)) != -1) {
#else
    while ((c = getopt_long (argc, argv, "hdviVq:s:r:", optlist, &i)) != -1) {
#endif
        switch (c) {
        case 'd': mode=1; break;
        case 'v': increase_verbosity(); break;
        case 'V': increase_verbosity(3); break;
        case 'q': quality=atoi(optarg);
                  if (quality < 0 || quality > 100) {e_printf("Not a sensible number for option -q\n"); return 1; }
                  break;
        case 's': scale=atoi(optarg);
                  if (scale < 1 || scale > 128) {e_printf("Not a sensible number for option -s\n"); return 1; }
                  break;
        case 'r': if (sscanf(optarg,"%ix%i", &resize_width, &resize_height) < 1) {e_printf("Not a sensible value for option -r (expected WxH)\n"); return 1; }
                  if (!resize_height) resize_height = resize_width;
                  break;
        case 'i': scale = -1; break;
#ifdef HAS_ENCODER
        case 'e': mode=0; break;
        case 't': mode=2; break;
        case 'I': method.encoding=flifEncoding::interlaced; break;
        case 'n': // undocumented: lower case -n still works
        case 'N': method.encoding=flifEncoding::nonInterlaced; break;
        case 'A': acb=1; break;
        case 'B': acb=0; break;
        case 'P': palette_size=atoi(optarg);
                  if (palette_size < -32000 || palette_size > 32000) {e_printf("Not a sensible number for option -P\n"); return 1; }
                  if (palette_size == 0) {v_printf(5,"Palette disabled\n"); }
                  break;
        case 'R': learn_repeats=atoi(optarg);
                  if (learn_repeats < 0 || learn_repeats > 20) {e_printf("Not a sensible number for option -R\n"); return 1; }
                  break;
        case 'F': frame_delay.clear();
                  while(optarg != 0) {
                    int d=strtol(optarg,&optarg,10);
                    if (d==0) break;
                    if (*optarg == ',' || *optarg == '+') optarg++;
                    frame_delay.push_back(d);
                    if (d < 0 || d > 60000) {e_printf("Not a sensible number for option -F: %i\n",d); return 1; }
                  }
                  if (frame_delay.size() < 1) frame_delay.push_back(100);
                  break;
        case 'L': lookback=atoi(optarg);
                  if (lookback < -1 || lookback > 256) {e_printf("Not a sensible number for option -L\n"); return 1; }
                  break;
        case 'D': divisor=atoi(optarg);
                  if (divisor <= 0 || divisor > 0xFFFFFFF) {e_printf("Not a sensible number for option -D\n"); return 1; }
                  break;
        case 'M': min_size=atoi(optarg);
                  if (min_size < 0) {e_printf("Not a sensible number for option -M\n"); return 1; }
                  break;
        case 'T': split_threshold=atoi(optarg);
                  if (split_threshold <= 3 || split_threshold > 100000) {e_printf("Not a sensible number for option -T\n"); return 1; }
                  split_threshold *= 5461;
                  break;
        case 'Y': yiq=0; break;
        case 'C': plc=0; break;
        case 'S': frs=0; break;
        case 'K': alpha_zero_special=false; break;
        case 'X': cutoff=atoi(optarg);
                  if (cutoff < 1 || cutoff > 128) {e_printf("Not a sensible number for option -X (try something between 1 and 128)\n"); return 1; }
                  break;
        case 'Z': alpha=atoi(optarg);
                  if (alpha < 2 || alpha > 128) {e_printf("Not a sensible number for option -Z (try something between 2 and 128)\n"); return 1; }
                  break;
#endif
        case 'h': showhelp=true; break;
        default: show_help(); return 0;
        }
    }
    argc -= optind;
    argv += optind;

    show_banner();
    if (argc == 0 || showhelp) {
        if (get_verbosity() == 1 || showhelp) show_help();
        return 0;
    }

    if (argc == 1 && scale != -1) {
        show_help();
        e_printf("\nOutput file missing.\n");
        return 1;
    }
    if (scale == -1) mode = 1;
    if (file_exists(argv[0])) {
        char *f = strrchr(argv[0],'/');
        char *ext = f ? strrchr(f,'.') : strrchr(argv[0],'.');
#ifdef HAS_ENCODER
        if (mode == 0 && file_is_flif(argv[0])) {
            char *f = strrchr(argv[1],'/');
            char *ext = f ? strrchr(f,'.') : strrchr(argv[1],'.');
            if ((ext && ( !strcasecmp(ext,".flif")  || ( !strcasecmp(ext,".flf") )))) {
                v_printf(3,"Input and output file are both FLIF file, adding implicit -t\n");
                mode = 2;
            } else {
                v_printf(3,"Input file is a FLIF file, adding implicit -d\n");
                mode = 1;
            }
        }
        if (mode != 0) {
#endif
            if (!(ext && ( !strcasecmp(ext,".flif")  || ( !strcasecmp(ext,".flf") )))) {
                e_printf("Warning: expected file name extension \".flif\" for input file, trying anyway...\n");
            }
#ifdef HAS_ENCODER
        } else {
            if (!check_compatible_extension(ext)) {
                e_printf("Warning: expected \".png\", \".pnm\" or \".pam\" file name extension for input file, trying anyway...\n");
            }
        }
#endif
    } else if (argc>0) {
        e_printf("Input file does not exist: %s\n",argv[0]);
        return 1;
    }
    if (mode > 0 && argc > 2 && scale != -1) {
        e_printf("Too many arguments.\n");
        return 1;
    }

#ifdef HAS_ENCODER
    if (mode == 0) {
        if (!handle_encode(argc, argv, images, palette_size, acb, method, lookback, learn_repeats, frame_delay, divisor, min_size, split_threshold, yiq, plc, alpha_zero_special, frs, cutoff, alpha)) return 2;
    } else if (mode == 1) {
#endif
        return handle_decode(argc, argv, images, quality, scale, resize_width, resize_height);
#ifdef HAS_ENCODER
    } else if (mode == 2) {
//        if (scale > 1) {e_printf("Not yet supported: transcoding downscaled image; use decode + encode!\n");}
        if (!decode_flif(argv, images, quality, scale, resize_width, resize_height)) return 2;
        argc--; argv++;
        if (!encode_flif(argc, argv, images, palette_size, acb, method, lookback, learn_repeats, frame_delay, divisor, min_size, split_threshold, yiq, plc, frs, cutoff, alpha)) return 2;
    }
#endif
    return 0;
}
Exemple #4
0
int main(int argc, char **argv)
{
    Images images;
    flif_options options = FLIF_DEFAULT_OPTIONS;
#ifdef HAS_ENCODER
    int mode = -1; // 0 = encode, 1 = decode, 2 = transcode
#else
    int mode = 1;
#endif
    bool showhelp = false;
    if (strcmp(argv[0],"cflif") == 0) mode = 0;
    if (strcmp(argv[0],"dflif") == 0) mode = 1;
    if (strcmp(argv[0],"deflif") == 0) mode = 1;
    if (strcmp(argv[0],"decflif") == 0) mode = 1;
    static struct option optlist[] = {
        {"help", 0, NULL, 'h'},
        {"decode", 0, NULL, 'd'},
        {"verbose", 0, NULL, 'v'},
        {"no-crc", 0, NULL, 'c'},
        {"no-metadata", 0, NULL, 'm'},
        {"no-color-profile", 0, NULL, 'p'},
        {"quality", 1, NULL, 'q'},
        {"scale", 1, NULL, 's'},
        {"resize", 1, NULL, 'r'},
        {"fit", 1, NULL, 'f'},
        {"identify", 0, NULL, 'i'},
        {"version", 0, NULL, 'V'},
        {"overwrite", 0, NULL, 'o'},
        {"breakpoints", 0, NULL, 'b'},
        {"keep-palette", 0, NULL, 'k'},
#ifdef HAS_ENCODER
        {"encode", 0, NULL, 'e'},
        {"transcode", 0, NULL, 't'},
        {"interlace", 0, NULL, 'I'},
        {"no-interlace", 0, NULL, 'N'},
        {"frame-delay", 1, NULL, 'F'},
        {"keep-invisible-rgb", 0, NULL, 'K'},
        {"max-palette-size", 1, NULL, 'P'},
        {"force-color-buckets", 0, NULL, 'A'},
        {"no-color-buckets", 0, NULL, 'B'},
        {"no-ycocg", 0, NULL, 'Y'},
        {"no-channel-compact", 0, NULL, 'C'},
        {"max-frame-lookback", 1, NULL, 'L'},
        {"no-frame-shape", 0, NULL, 'S'},
        {"maniac-repeats", 1, NULL, 'R'},
        {"maniac-divisor", 1, NULL, 'D'},
        {"maniac-min-size", 1, NULL, 'M'},
        {"maniac-threshold", 1, NULL, 'T'},
        {"chance-cutoff", 1, NULL, 'X'},
        {"chance-alpha", 1, NULL, 'Z'},
        {"lossy", 1, NULL, 'Q'},
        {"adaptive", 0, NULL, 'U'},
        {"guess", 1, NULL, 'G'},
        {"invisible-guess", 1, NULL, 'H'},
        {"effort", 1, NULL, 'E'},
        {"chroma-subsample", 0, NULL, 'J'},
        {"no-subtract-green", 0, NULL, 'W'},
#endif
        {0, 0, 0, 0}
    };
    int i,c;
#ifdef HAS_ENCODER
    while ((c = getopt_long (argc, argv, "hdvcmiVq:s:r:f:obketINnF:KP:ABYWCL:SR:D:M:T:X:Z:Q:UG:H:E:J", optlist, &i)) != -1) {
#else
    while ((c = getopt_long (argc, argv, "hdvcmiVq:s:r:f:obk", optlist, &i)) != -1) {
#endif
        switch (c) {
        case 'd': mode=1; break;
        case 'v': increase_verbosity(); break;
        case 'V': increase_verbosity(3); break;
        case 'c': options.crc_check = 0; break;
        case 'm': options.metadata = 0; break;
        case 'p': options.color_profile = 0; break;
        case 'o': options.overwrite = 1; break;
        case 'q': options.quality=atoi(optarg);
                  if (options.quality < 0 || options.quality > 100) {e_printf("Not a sensible number for option -q\n"); return 1; }
                  break;
        case 's': options.scale=atoi(optarg);
                  if (options.scale < 1 || options.scale > 128) {e_printf("Not a sensible number for option -s\n"); return 1; }
                  break;
        case 'r': if (sscanf(optarg,"%ix%i", &options.resize_width, &options.resize_height) < 1) {
                    if (sscanf(optarg,"x%i", &options.resize_height) < 1) {e_printf("Not a sensible value for option -r (expected WxH)\n"); return 1; }
                  }
                  if (!options.resize_height) options.resize_height = options.resize_width;
                  break;
        case 'f': if (sscanf(optarg,"%ix%i", &options.resize_width, &options.resize_height) < 1) {
                    if (sscanf(optarg,"x%i", &options.resize_height) < 1) {e_printf("Not a sensible value for option -f (expected WxH)\n"); return 1; }
                  }
                  options.fit=1;
                  break;
        case 'i': options.scale = -1; break;
        case 'b': options.show_breakpoints = 8; mode=1; break;
        case 'k': options.keep_palette = true; break;
#ifdef HAS_ENCODER
        case 'e': mode=0; break;
        case 't': mode=2; break;
        case 'I': options.method.encoding=flifEncoding::interlaced; break;
        case 'n': // undocumented: lower case -n still works
        case 'N': options.method.encoding=flifEncoding::nonInterlaced; break;
        case 'A': options.acb=1; break;
        case 'B': options.acb=0; break;
        case 'P': options.palette_size=atoi(optarg);
                  if (options.palette_size < -32000 || options.palette_size > 32000) {e_printf("Not a sensible number for option -P\n"); return 1; }
                  if (options.palette_size > 512) {v_printf(1,"Warning: palette size above 512 implies that simple FLIF decoders (8-bit only) cannot decode this file.\n"); }
                  if (options.palette_size == 0) {v_printf(5,"Palette disabled\n"); }
                  break;
        case 'R': options.learn_repeats=atoi(optarg);
                  if (options.learn_repeats < 0 || options.learn_repeats > 20) {e_printf("Not a sensible number for option -R\n"); return 1; }
                  break;
        case 'F': options.frame_delay.clear();
                  while(optarg != 0) {
                    int d=strtol(optarg,&optarg,10);
                    if (d==0) break;
                    if (*optarg == ',' || *optarg == '+' || *optarg == ' ') optarg++;
                    options.frame_delay.push_back(d);
                    if (d < 0 || d > 60000) {e_printf("Not a sensible number for option -F: %i\n",d); return 1; }
                  }
                  if (options.frame_delay.size() < 1) options.frame_delay.push_back(100);
                  break;
        case 'L': options.lookback=atoi(optarg);
                  if (options.lookback < -1 || options.lookback > 256) {e_printf("Not a sensible number for option -L\n"); return 1; }
                  break;
        case 'D': options.divisor=atoi(optarg);
                  if (options.divisor <= 0 || options.divisor > 0xFFFFFFF) {e_printf("Not a sensible number for option -D\n"); return 1; }
                  break;
        case 'M': options.min_size=atoi(optarg);
                  if (options.min_size < 0) {e_printf("Not a sensible number for option -M\n"); return 1; }
                  break;
        case 'T': options.split_threshold=atoi(optarg);
                  if (options.split_threshold <= 3 || options.split_threshold > 100000) {e_printf("Not a sensible number for option -T\n"); return 1; }
                  options.split_threshold *= 5461;
                  break;
        case 'Y': options.ycocg=0; break;
        case 'W': options.ycocg=0; options.subtract_green=0; break;
        case 'C': options.plc=0; break;
        case 'S': options.frs=0; break;
        case 'K': options.alpha_zero_special=0; break;
        case 'X': options.cutoff=atoi(optarg);
                  if (options.cutoff < 1 || options.cutoff > 128) {e_printf("Not a sensible number for option -X (try something between 1 and 128)\n"); return 1; }
                  break;
        case 'Z': options.alpha=atoi(optarg);
                  if (options.alpha < 2 || options.alpha > 128) {e_printf("Not a sensible number for option -Z (try something between 2 and 128)\n"); return 1; }
                  break;
        case 'Q': options.loss=100-atoi(optarg);
                  // can't go above quality 100 = lossless
                  // can go way below 0 if you want
                  if (options.loss < 0) {e_printf("Not a sensible number for option -Q (try something between 0 and 100)\n"); return 1; }
                  break;
        case 'U': options.adaptive=1; break;
        case 'G': {
                  int p=0;
                  while(*optarg != 0) {
                    int d=0;
                    switch (*optarg) {
                        case '?': case 'G': case 'g': case 'H': case 'h': // guess/heuristically choose
                            d = -2; break;
                        case '0': case 'A': case 'a': // average
                            d = 0; break;
                        case '1': case 'M': case 'm': // median of 3 values (avg, grad1, grad2)
                            d = 1; break;
                        case '2': case 'N': case 'n': // median of 3 neighbors
                            d = 2; break;
                        case '3':
                        case 'X': case 'x': // auto/mixed, usually a bad idea
                            d = -1; break;
                        case ' ': case ',': case '+':
                            optarg++; continue;
                        default:
                        e_printf("Not a sensible value for option -G\nValid values are: 0 (avg), 1 (median avg/gradients), 2 (median neighbors), X (auto/mixed), ? (heuristically pick 0-2)\n"); return 1;
                    }
                    if (p>4) {e_printf("Error while parsing option -G: too many planes specified\n"); return 1; }
                    options.predictor[p] = d;
                    p++; optarg++;
                  }
                  for (; p<5; p++) options.predictor[p]=options.predictor[0];
                  }
                  break;
        case 'H': options.invisible_predictor=atoi(optarg);
                  if (options.invisible_predictor < 0 || options.invisible_predictor > 2) {e_printf("Not a sensible value for option -H\nValid values are: 0 (avg), 1 (median avg/gradients), 2 (median neighbors)\n"); return 1; }
                  break;
        case 'J': options.chroma_subsampling = 1;
                  break;
        case 'E': {
                  int effort=atoi(optarg);
                  if (effort < 0 || effort > 100) {e_printf("Not a sensible number for option -E (try something between 0 and 100)\n"); return 1; }
                  // set some parameters automatically
                  if (effort < 10) options.learn_repeats=0;
                  else if (effort <= 50) {options.learn_repeats=1; options.split_threshold=5461*8*5;}
                  else if (effort <= 70) {options.learn_repeats=2;  options.split_threshold=5461*8*8;}
                  else if (effort <= 90) {options.learn_repeats=3; options.split_threshold=5461*8*10;}
                  else if (effort <= 100) {options.learn_repeats=4; options.split_threshold=5461*8*12;}
                  if (effort < 15) { for (int i=0; i<5; i++) options.predictor[i]=0; }
                  else if (effort < 30) { options.predictor[1]=0; options.predictor[2]=0; }
                  if (effort < 5) options.acb=0;
                  if (effort < 8) options.palette_size=0;
                  if (effort < 25) options.plc=0;
                  if (effort < 30) options.lookback=0;
                  if (effort < 5) options.frs=0;
                  v_printf(3,"Encode effort: %i, corresponds to parameters -R%i -T%i%s%s%s%s\n", effort, options.learn_repeats, options.split_threshold/5461,
                                    (effort<15?" -G0":(effort<30?" -G?00":"")), (effort<5?" -B":""), (effort<8?" -P0":""), (effort<25?" -C":""));
                                    // not mentioning animation options since they're usually irrelevant
                  }
                  break;
#endif
        case 'h': showhelp=true; break;
        default: show_help(mode); return 0;
        }
    }
    argc -= optind;
    argv += optind;
    bool last_is_output = (options.scale != -1);
    if (options.show_breakpoints && argc == 1) { last_is_output = false; options.no_full_decode = 1; options.scale = 2; }

    if (!strcmp(argv[argc-1],"-")) {
        // writing output to stdout, so redirecting verbose output to stderr to avoid contaminating the output stream
        redirect_stdout_to_stderr();
    }

    show_banner();
    if (argc == 0 || showhelp) {
        if (get_verbosity() == 1 || showhelp) show_help(mode);
        return 0;
    }

    if (argc == 1 && last_is_output) {
        show_help(mode);
        e_printf("\nOutput file missing.\n");
        return 1;
    }
    if (options.scale == -1) mode = 1;
    if (mode < 0) mode = 0;
    if (file_exists(argv[0])) {
        char *f = strrchr(argv[0],'/');
        char *ext = f ? strrchr(f,'.') : strrchr(argv[0],'.');
#ifdef HAS_ENCODER
        if (mode == 0 && file_is_flif(argv[0])) {
            char *f = strrchr(argv[1],'/');
            char *ext = f ? strrchr(f,'.') : strrchr(argv[1],'.');
            if ((ext && ( !strcasecmp(ext,".flif")  || ( !strcasecmp(ext,".flf") )))) {
                v_printf(3,"Input and output file are both FLIF file, adding implicit -t\n");
                mode = 2;
            } else {
                v_printf(3,"Input file is a FLIF file, adding implicit -d\n");
                mode = 1;
            }
        }
        if (mode == 0) {
            char *f = strrchr(argv[argc-1],'/');
            char *ext = f ? strrchr(f,'.') : strrchr(argv[argc-1],'.');
            if (ext && !options.loss && strcasecmp(ext,".flif") && strcasecmp(ext,".flf") ) {
                e_printf("Warning: expected file name extension \".flif\" for output file.\n");
            } else if (options.loss && check_compatible_extension(ext)) {
                v_printf(2,"Not doing actual lossy encoding to FLIF, just applying loss.\n");
                options.just_add_loss = 1;
            }
        }
        if (mode != 0) {
#endif
            if (!(ext && ( !strcasecmp(ext,".flif")  || ( !strcasecmp(ext,".flf") )))) {
                e_printf("Warning: expected file name extension \".flif\" for input file, trying anyway...\n");
            }
#ifdef HAS_ENCODER
        } else {
            if (!check_compatible_extension(ext)) {
                e_printf("Warning: expected \".png\", \".pnm\" or \".pam\" file name extension for input file, trying anyway...\n");
            }
        }
#endif
    } else if (argc>0) {
        if (!strcmp(argv[0],"-")) {
          v_printf(4,"Taking input from standard input. Mode: %s\n",
             (mode==0?"encode": (mode==1?"decode":"transcode")));
        } else if (!strchr(argv[0],'%')) {
          e_printf("Error: input file does not exist: %s\n",argv[0]);
          return 1;
        }
    }
    if (last_is_output && file_exists(argv[argc-1]) && !options.overwrite) {
        e_printf("Error: output file already exists: %s\nUse --overwrite to force overwrite.\n",argv[argc-1]);
        return 1;
    }
    if (mode > 0 && argc > 2 && options.scale != -1) {
        e_printf("Too many arguments.\n");
        return 1;
    }

#ifdef HAS_ENCODER
    if (options.chroma_subsampling)
        v_printf(1,"Warning: chroma subsampling produces a truncated FLIF file. Image will not be lossless!\n");
    if (options.loss > 0) options.keep_palette = false; // not going to add loss to indexed colors
    if (options.adaptive) options.loss = -options.loss; // use negative loss to indicate we want to do adaptive lossy encoding
    if (mode == 0) {
        if (!handle_encode(argc, argv, images, options)) return 2;
    } else if (mode == 1) {
#endif
        return handle_decode(argc, argv, images, options);
#ifdef HAS_ENCODER
    } else if (mode == 2) {
//        if (scale > 1) {e_printf("Not yet supported: transcoding downscaled image; use decode + encode!\n");}
        if (!decode_flif(argv, images, options)) return 2;
        argc--; argv++;
        if (!encode_flif(argc, argv, images, options)) return 2;
    }
#endif
    return 0;
}
Exemple #5
0
int handle_decode(int argc, char **argv, Images &images, flif_options &options) {
    if (options.scale < 0) {
        // just identify the file(s), don't actually decode
        while (argc>0) {
            decode_flif(argv, images, options);
            argv++; argc--;
        }
        return 0;
    }
    if (argc == 1 && options.show_breakpoints) {
        decode_flif(argv, images, options);
        return 0;
    }
    char *ext = strrchr(argv[1],'.');
    if (check_metadata_extension(ext)) {
        // only requesting metadata, no need to actually decode the file
        options.scale = -2;
        decode_flif(argv, images, options);
        if (!images[0].save(argv[1])) return 2;
        v_printf(2,"\n");
        return 0;
    }
    if (!check_compatible_extension(ext) && strcmp(argv[1],"null:") && strcmp(argv[1],"-")) {
        e_printf("Error: expected \".png\", \".pnm\" or \".pam\" file name extension for output file\n");
        return 1;
    }
    if (!(ext && ( !strcasecmp(ext,".png"))))
        options.keep_palette = false;   // don't try to make a palette PNM

    try {
      if (!decode_flif(argv, images, options)) {
        e_printf("Error: could not decode FLIF file\n"); return 3;
      }
    } catch (std::bad_alloc& ba) {
        e_printf("Error: memory allocation problem (unexpected)\n"); return 3;
    }
    if (!strcmp(argv[1],"null:")) return 0;
//    if (scale>1)
//        v_printf(3,"Downscaling output: %ux%u -> %ux%u\n",images[0].cols(),images[0].rows(),images[0].cols()/scale,images[0].rows()/scale);
    if (images.size() == 1) {
        if (!images[0].save(argv[1])) return 2;
    } else {
        bool to_stdout=false;
        if (!strcmp(argv[1],"-")) {
            to_stdout=true;
            v_printf(1,"Warning: writing animation to standard output as a concatenation of PAM files.\n");
        }
        int counter=0;
        int maxlength = strlen(argv[1])+100;
        std::vector<char> vfilename(maxlength);
        char *filename = &vfilename[0];
        bool use_custom_format = false;
        if (strchr(argv[1],'%')) use_custom_format = true;
        strcpy(filename,argv[1]);
        char *a_ext = strrchr(filename,'.');
        if (!a_ext && !to_stdout) {
            e_printf("Problem saving animation to %s\n",filename);
            return 2;
        }
        for (Image& image : images) {
            if (!to_stdout) {
              if (use_custom_format) snprintf(filename,maxlength,argv[1],counter);
              else if (images.size() < 1000) sprintf(a_ext,"-%03d%s",counter,ext);
              else if (images.size() < 10000) sprintf(a_ext,"-%04d%s",counter,ext);
              else if (images.size() < 100000) sprintf(a_ext,"-%05d%s",counter,ext);
              else sprintf(a_ext,"-%08d%s",counter,ext);
              if (file_exists(filename) && !options.overwrite) {
                e_printf("Error: output file already exists: %s\nUse --overwrite to force overwrite.\n",filename);
                return 4;
              }
              if (!image.save(filename)) return 2;
            } else {
              if (!image.save(argv[1])) return 2;
            }
            counter++;
            v_printf(2,"    (%i/%i)         \r",counter,(int)images.size()); v_printf(4,"\n");
        }
    }
    // get rid of palette (should also do this in the non-standard/error paths, but being lazy here since the tool will exit anyway)
    images[0].clear();
    v_printf(2,"\n");
    return 0;
}
Exemple #6
0
int main(int argc, char **argv)
{
    Images images;
#ifdef HAS_ENCODER
    int mode = 0; // 0 = encode, 1 = decode, 2 = transcode
    flifEncodingOptional method;
    int learn_repeats = -1;
    int acb = -1; // try auto color buckets
    int frame_delay = 100;
    int palette_size = 512;
    int lookback = 1;
#else
    int mode = 1;
#endif
    int quality = 100; // 100 = everything, positive value: partial decode, negative value: only rough data
    int scale = 1;
    if (strcmp(argv[0],"flif") == 0) mode = 0;
    if (strcmp(argv[0],"dflif") == 0) mode = 1;
    if (strcmp(argv[0],"deflif") == 0) mode = 1;
    if (strcmp(argv[0],"decflif") == 0) mode = 1;
    static struct option optlist[] = {
        {"help", 0, NULL, 'h'},
        {"decode", 0, NULL, 'd'},
        {"verbose", 0, NULL, 'v'},
        {"quality", 1, NULL, 'q'},
        {"scale", 1, NULL, 's'},
#ifdef HAS_ENCODER
        {"encode", 0, NULL, 'e'},
        {"transcode", 0, NULL, 't'},
        {"interlace", 0, NULL, 'i'},
        {"no-interlace", 0, NULL, 'n'},
        {"acb", 0, NULL, 'a'},
        {"no-acb", 0, NULL, 'b'},
        {"palette", 1, NULL, 'p'},
        {"repeats", 1, NULL, 'r'},
        {"frame-delay", 1, NULL, 'f'},
        {"lookback", 1, NULL, 'l'},
#endif
        {0, 0, 0, 0}
    };
    int i,c;
#ifdef HAS_ENCODER
    while ((c = getopt_long (argc, argv, "hedtvinabq:s:p:r:f:l:", optlist, &i)) != -1) {
#else
    while ((c = getopt_long (argc, argv, "hdvq:s:", optlist, &i)) != -1) {
#endif
        switch (c) {
        case 'd': mode=1; break;
        case 'v': increase_verbosity(); break;
        case 'q': quality=atoi(optarg);
                  if (quality < 0 || quality > 100) {e_printf("Not a sensible number for option -q\n"); return 1; }
                  break;
        case 's': scale=atoi(optarg);
                  if (scale < 1 || scale > 128) {e_printf("Not a sensible number for option -s\n"); return 1; }
                  break;
#ifdef HAS_ENCODER
        case 'e': mode=0; break;
        case 't': mode=2; break;
        case 'i': method.encoding=flifEncoding::interlaced; break;
        case 'n': method.encoding=flifEncoding::nonInterlaced; break;
        case 'a': acb=1; break;
        case 'b': acb=0; break;
        case 'p': palette_size=atoi(optarg);
                  if (palette_size < -1 || palette_size > 30000) {e_printf("Not a sensible number for option -p\n"); return 1; }
                  if (palette_size == 0) {v_printf(2,"Palette disabled\n"); }
                  break;
        case 'r': learn_repeats=atoi(optarg);
                  if (learn_repeats < 0 || learn_repeats > 1000) {e_printf("Not a sensible number for option -r\n"); return 1; }
                  break;
        case 'f': frame_delay=atoi(optarg);
                  if (frame_delay < 0 || frame_delay > 60000) {e_printf("Not a sensible number for option -f\n"); return 1; }
                  break;
        case 'l': lookback=atoi(optarg);
                  if (lookback < -1 || lookback > 256) {e_printf("Not a sensible number for option -l\n"); return 1; }
                  break;
#endif
        case 'h':
        default: show_help(); return 0;
        }
    }
    argc -= optind;
    argv += optind;

    show_banner();
    if (argc == 0) {
        //e_printf("Input file missing.\n");
        if (get_verbosity() == 1) show_help();
        return 1;
    }

    if (argc == 1) {
        show_help();
        e_printf("\nOutput file missing.\n");
        return 1;
    }

    if (file_exists(argv[0])) {
#ifdef HAS_ENCODER
        if (mode == 0 && file_is_flif(argv[0])) {
            char *f = strrchr(argv[1],'/');
            char *ext = f ? strrchr(f,'.') : strrchr(argv[1],'.');
            if (check_compatible_extension(ext)) {
                v_printf(2,"Input file is a FLIF file, adding implicit -d\n");
                mode = 1;
            } else if ((ext && ( !strcasecmp(ext,".flif")  || ( !strcasecmp(ext,".flf") )))) {
                v_printf(2,"Input and output file are both FLIF file, adding implicit -t\n");
                mode = 2;
            }
        }
#endif
        char *f = strrchr(argv[0],'/');
        char *ext = f ? strrchr(f,'.') : strrchr(argv[0],'.');
        if (mode == 0) {
            if (!check_compatible_extension(ext)) {
                e_printf("Warning: expected \".png\" or \".pnm\" file name extension for input file, trying anyway...\n");
            }
        } else {
            if (!(ext && ( !strcasecmp(ext,".flif")  || ( !strcasecmp(ext,".flf") )))) {
                e_printf("Warning: expected file name extension \".flif\" for input file, trying anyway...\n");
            }
        }
    } else if (argc>0) {
        e_printf("Input file does not exist: %s\n",argv[0]);
        return 1;
    }
    if (mode > 0 && argc > 2) {
        e_printf("Too many arguments.\n");
        return 1;
    }

#ifdef HAS_ENCODER
    if (mode == 0) {
        if (!handle_encode(argc, argv, images, palette_size, acb, method, lookback, learn_repeats, frame_delay)) return 2;
    } else if (mode == 1) {
#endif
        if (!handle_decode(argv, images, quality, scale)) return 2;
#ifdef HAS_ENCODER
    } else if (mode == 2) {
        if (scale > 1) {e_printf("Not yet supported: transcoding downscaled image; use decode + encode!\n");}
        if (!decode_flif(argv, images, quality, scale)) return 2;
        argc--; argv++;
        if (!encode_flif(argc, argv, images, palette_size, acb, method, lookback, learn_repeats, frame_delay)) return 2;
    }
#endif
    return 0;
}
Exemple #7
0
int main(int argc, char **argv)
{
    Images images;
#ifdef HAS_ENCODER
    int mode = 0; // 0 = encode, 1 = decode, 2 = transcode
    flifEncodingOptional method;
    int learn_repeats = -1;
    int acb = -1; // try auto color buckets
    int frame_delay = 100;
    int palette_size = -1;
    int lookback = 1;
    int divisor=CONTEXT_TREE_COUNT_DIV;
    int min_size=CONTEXT_TREE_MIN_SUBTREE_SIZE;
    int split_threshold=CONTEXT_TREE_SPLIT_THRESHOLD;
    int yiq = 1;
    int plc = 1;
    bool alpha_zero_special = true;
#else
    int mode = 1;
#endif
    int quality = 100; // 100 = everything, positive value: partial decode, negative value: only rough data
    int scale = 1;
    bool showhelp = false;
    if (strcmp(argv[0],"flif") == 0) mode = 0;
    if (strcmp(argv[0],"dflif") == 0) mode = 1;
    if (strcmp(argv[0],"deflif") == 0) mode = 1;
    if (strcmp(argv[0],"decflif") == 0) mode = 1;
    static struct option optlist[] = {
        {"help", 0, NULL, 'h'},
        {"decode", 0, NULL, 'd'},
        {"verbose", 0, NULL, 'v'},
        {"quality", 1, NULL, 'q'},
        {"scale", 1, NULL, 's'},
        {"identify", 1, NULL, 'I'},
#ifdef HAS_ENCODER
        {"encode", 0, NULL, 'e'},
        {"transcode", 0, NULL, 't'},
        {"interlace", 0, NULL, 'i'},
        {"no-interlace", 0, NULL, 'n'},
        {"acb", 0, NULL, 'a'},
        {"no-acb", 0, NULL, 'b'},
        {"palette", 1, NULL, 'p'},
        {"repeats", 1, NULL, 'r'},
        {"frame-delay", 1, NULL, 'f'},
        {"lookback", 1, NULL, 'l'},
        {"divisor", 1, NULL, 'D'},
        {"min-size", 1, NULL, 'M'},
        {"split-threshold", 1, NULL, 'S'},
        {"rgb", 0, NULL, 'R'},
        {"no-plc", 0, NULL, 'C'},
        {"keep-alpha-zero", 0, NULL, 'A'},
#endif
        {0, 0, 0, 0}
    };
    int i,c;
#ifdef HAS_ENCODER
    while ((c = getopt_long (argc, argv, "hedtvIinabq:s:p:r:f:l:D:M:S:RCA", optlist, &i)) != -1) {
#else
    while ((c = getopt_long (argc, argv, "hdvIq:s:", optlist, &i)) != -1) {
#endif
        switch (c) {
        case 'd': mode=1; break;
        case 'v': increase_verbosity(); break;
        case 'q': quality=atoi(optarg);
                  if (quality < 0 || quality > 100) {e_printf("Not a sensible number for option -q\n"); return 1; }
                  break;
        case 's': scale=atoi(optarg);
                  if (scale < 1 || scale > 128) {e_printf("Not a sensible number for option -s\n"); return 1; }
                  break;
        case 'I': scale = -1; break;
#ifdef HAS_ENCODER
        case 'e': mode=0; break;
        case 't': mode=2; break;
        case 'i': method.encoding=flifEncoding::interlaced; break;
        case 'n': method.encoding=flifEncoding::nonInterlaced; break;
        case 'a': acb=1; break;
        case 'b': acb=0; break;
        case 'p': palette_size=atoi(optarg);
                  if (palette_size < 0 || palette_size > 30000) {e_printf("Not a sensible number for option -p\n"); return 1; }
                  if (palette_size == 0) {v_printf(2,"Palette disabled\n"); }
                  break;
        case 'r': learn_repeats=atoi(optarg);
                  if (learn_repeats < 0 || learn_repeats > 20) {e_printf("Not a sensible number for option -r\n"); return 1; }
                  break;
        case 'f': frame_delay=atoi(optarg);
                  if (frame_delay < 0 || frame_delay > 60000) {e_printf("Not a sensible number for option -f\n"); return 1; }
                  break;
        case 'l': lookback=atoi(optarg);
                  if (lookback < -1 || lookback > 256) {e_printf("Not a sensible number for option -l\n"); return 1; }
                  break;
        case 'D': divisor=atoi(optarg);
                  if (divisor <= 0 || divisor > 0xFFFFFFF) {e_printf("Not a sensible number for option -D\n"); return 1; }
                  break;
        case 'M': min_size=atoi(optarg);
                  if (min_size < 0 || min_size > CONTEXT_TREE_MAX_COUNT) {e_printf("Not a sensible number for option -M\n"); return 1; }
                  break;
        case 'S': split_threshold=atoi(optarg);
                  if (split_threshold <= 0 || split_threshold > 100000) {e_printf("Not a sensible number for option -S\n"); return 1; }
                  split_threshold *= 5461;
                  break;
        case 'R': yiq=0; break;
        case 'C': plc=0; break;
        case 'A': alpha_zero_special=false; break;
#endif
        case 'h': showhelp=true; break;
        default: show_help(); return 0;
        }
    }
    argc -= optind;
    argv += optind;

    show_banner();
    if (argc == 0 || showhelp) {
        //e_printf("Input file missing.\n");
        if (get_verbosity() == 1 || showhelp) show_help();
        return 1;
    }

    if (argc == 1 && scale != -1) {
        show_help();
        e_printf("\nOutput file missing.\n");
        return 1;
    }
    if (scale == -1) mode = 1;
    if (file_exists(argv[0])) {
        char *f = strrchr(argv[0],'/');
        char *ext = f ? strrchr(f,'.') : strrchr(argv[0],'.');
#ifdef HAS_ENCODER
        if (mode == 0 && file_is_flif(argv[0])) {
            char *f = strrchr(argv[1],'/');
            char *ext = f ? strrchr(f,'.') : strrchr(argv[1],'.');
            if (check_compatible_extension(ext)) {
                v_printf(3,"Input file is a FLIF file, adding implicit -d\n");
                mode = 1;
            } else if ((ext && ( !strcasecmp(ext,".flif")  || ( !strcasecmp(ext,".flf") )))) {
                v_printf(3,"Input and output file are both FLIF file, adding implicit -t\n");
                mode = 2;
            }
        }
        if (mode != 0) {
#endif
            if (!(ext && ( !strcasecmp(ext,".flif")  || ( !strcasecmp(ext,".flf") )))) {
                e_printf("Warning: expected file name extension \".flif\" for input file, trying anyway...\n");
            }
#ifdef HAS_ENCODER
        } else {
            if (!check_compatible_extension(ext)) {
                e_printf("Warning: expected \".png\", \".pnm\" or \".pam\" file name extension for input file, trying anyway...\n");
            }
        }
#endif
    } else if (argc>0) {
        e_printf("Input file does not exist: %s\n",argv[0]);
        return 1;
    }
    if (mode > 0 && argc > 2 && scale != -1) {
        e_printf("Too many arguments.\n");
        return 1;
    }

#ifdef HAS_ENCODER
    if (mode == 0) {
        if (!handle_encode(argc, argv, images, palette_size, acb, method, lookback, learn_repeats, frame_delay, divisor, min_size, split_threshold, yiq, plc, alpha_zero_special)) return 2;
    } else if (mode == 1) {
#endif
        return handle_decode(argc, argv, images, quality, scale);
#ifdef HAS_ENCODER
    } else if (mode == 2) {
        if (scale > 1) {e_printf("Not yet supported: transcoding downscaled image; use decode + encode!\n");}
        if (!decode_flif(argv, images, quality, scale)) return 2;
        argc--; argv++;
        if (!encode_flif(argc, argv, images, palette_size, acb, method, lookback, learn_repeats, frame_delay, divisor, min_size, split_threshold, yiq, plc)) return 2;
    }
#endif
    return 0;
}