Exemplo n.º 1
0
bool gif_optimize(const char *in_name, const char *out_name) {
    bool ret = true;
    FILE *in;
    FILE *out;
    Gif_Stream *gfs;

    if(!(in = fopen(in_name, "rb"))){
        return false;
    }

    if(!(out = fopen(out_name, "wb"))){
        fclose(in);
        return false;
    }

    gfs = Gif_FullReadFile(in, GIF_READ_COMPRESSED, 0, 0);
    Gif_InitCompressInfo(&gif_write_info);

    if (!gfs || (Gif_ImageCount(gfs) == 0 && gfs->errors > 0)) {
      fprintf(stdout,"open error");
      Gif_DeleteStream(gfs);
      ret = false;
      goto err;
    }

    optimize_fragments(gfs, GT_OPT_MASK, 0);
    Gif_FullWriteFile(gfs, &gif_write_info, out);
    Gif_DeleteStream(gfs);

err:
    fclose(in);
    fclose(out);
    return ret;
}
Exemplo n.º 2
0
void
cat(FILE *f, int n, double bbox[4])
{
    int y, i, j, pos, transparent, bw;
    uint32_t val;
    Gif_Color *colors, white;
    unsigned char buf[8], outbuf[5];
    double r, g, b;
    double scale;
    double xoff, yoff;
    double ptwidth, ptheight;
    double dpi = 300;
    Gif_Stream *gfs;
    Gif_Image *gfi;

    white.gfc_red = white.gfc_green = white.gfc_blue = 255;

  again:
    // pick cat
    if (ncats == 0)
        return;
    do {
        i = random() % ncats;
        if (cats[i].filename && !cats[i].gfs) {
            FILE *f = fopen(cats[i].filename, "rb");
            if (f
                && (cats[i].gfs = Gif_FullReadFile(f, GIF_READ_UNCOMPRESSED, cats[i].filename, gif_fileerror))
                && cats[i].gfs->nimages > 0)
                /* OK */;
            else {
                if (cats[i].gfs)
                    Gif_DeleteStream(cats[i].gfs);
                cats[i].gfs = NULL;
                cats[i].filename = NULL;
            }
            if (f)
                fclose(f);
        }
    } while (!cats[i].gfs);

    gfs = cats[i].gfs;
    gfi = Gif_GetImage(gfs, 0);

    // pick random color
    if (!cats[i].colorize && !cats[i].lighten)
        r = g = b = 0;
    else
        hsvtorgb(&r, &g, &b, FRANDOM() * 360,
                 (cats[i].colorize ? (cats[i].lighten ? FRANDOM() * 0.75 : 1) : 0),
                 (cats[i].lighten ? FRANDOM() * 0.4 + 0.5 : 1));

    // pick scale and position
    scale = (FRANDOM() + 0.2) * 3;
    ptwidth = 72 * gfi->width / dpi * scale;
    ptheight = 72 * gfi->height / dpi * scale;
    xoff = bbox[0] + FRANDOM() * ((bbox[2] - bbox[0]) + .2 * ptwidth) - .2 * ptwidth;
    yoff = bbox[1] + FRANDOM() * ((bbox[3] - bbox[1]) + .2 * ptheight) - .2 * ptheight;

    colors = (gfi->local ? gfi->local->col : gfs->global->col);
    transparent = gfi->transparent;

    // Black-and-white image?  Use /Separation color space to compress PostScript.
    bw = 1;
    pos = (gfi->local ? gfi->local->ncol : gfs->global->ncol);
    for (i = 0; i < pos && bw; i++)
        if (colors[i].gfc_red != colors[i].gfc_green || colors[i].gfc_red != colors[i].gfc_blue)
            bw = 0;

    // Determine color space
    if (bw && r == g && g == b)
        fprintf(f, "gsave /DeviceGray setcolorspace\n");
    else if (bw) {
        static int catcolorspace = 0;
        fprintf(f, "gsave [/Separation (Cat Color %d) /DeviceRGB {neg 1 add dup", catcolorspace++);
        if (r > 0)
            fprintf(f, " %.10g mul %.10g add exch", 1 - r, r);
        fprintf(f, " dup");
        if (g > 0)
            fprintf(f, " %.10g mul %.10g add exch", 1 - g, g);
        if (b > 0)
            fprintf(f, " %.10g mul %.10g add", 1 - b, b);
        fprintf(f, "}] setcolorspace\n");
        bw = 2;
    } else
        fprintf(f, "gsave /DeviceRGB setcolorspace\n");

    fprintf(f, "%.10g %.10g translate", xoff, yoff);
    if (cats[i].rotate)
        fprintf(f, " %.10g rotate", (FRANDOM() - 0.5) * 2 * cats[i].rotate);
    fprintf(f, " %.10g %.10g scale\n", ptwidth, ptheight);
    fprintf(f, "<< /ImageType 4\n\
   /Width %d /Height %d /BitsPerComponent 8\n", gfi->width, gfi->height);

    // Color space decoding: let 0 = white to help compress
    if (bw > 1)
        // /Decode [0 1] to get around Acrobat Distiller bug with /MaskColor
        fprintf(f, "   /MaskColor [0] /Decode [0 1]\n");
    else if (bw)
        fprintf(f, "   /MaskColor [0] /Decode [1 %.10g]\n", r);
    else
        fprintf(f, "   /MaskColor [0 0 0] /Decode [1 %.10g 1 %.10g 1 %.10g]\n", r, g, b);

    fprintf(f, "   /ImageMatrix [%d 0 0 -%d 0 %d]\n\
   /DataSource currentfile /ASCII85Decode filter >>\n\
image\n", gfi->width, gfi->height, gfi->height);

    i = pos = 0;
    for (y = 0; y < gfi->height; y++) {
        const uint8_t *x = gfi->img[y];
        const uint8_t *endx = x + gfi->width;
        for (; x < endx; x++) {
            Gif_Color *c = (*x == transparent ? &white : &colors[*x]);

            if (bw)
                buf[i++] = 255 - c->gfc_red;
            else {
                buf[i++] = 255 - c->gfc_red;
                buf[i++] = 255 - c->gfc_green;
                buf[i++] = 255 - c->gfc_blue;
            }

            if (i >= 4) {
                val = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
                if (val == 0) {
                    fputc('z', f);
                    pos++;
                } else {
                    for (j = 4; j >= 0; j--) {
                        outbuf[j] = 33 + val % 85;
                        val /= 85;
                    }
                    fwrite(outbuf, 1, 5, f);
                    pos += 5;
                }
                memcpy(buf, buf + 4, 4);
                i -= 4;
                if (pos >= 72)
                    fputc('\n', f), pos = 0;
            }
        }
    }

    if (i > 0) {
        buf[i] = buf[i + 1] = buf[i + 2] = 0;
        val = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
        for (j = 4; j >= 0; j--) {
            outbuf[j] = 33 + val % 85;
            val /= 85;
        }
        fwrite(outbuf, 1, i + 1, f);
    }

    fputs("\n~>\ngrestore\n", f);

    if (FRANDOM() > 0.2 && n < maxcats && maxcats > 0) {
        n++;
        goto again;
    }
}