List of gctr0/gctr1.c

Sun May 19 21:28:30 2024

戻る

TEXTAREA で表示(カット&ペーストむき)

/*************************************************************************
  gctr1.c

 1997/09/30 Ver.0.01

 (C) 1997 がま
 e-mail addr : gama@mvg.biglobe.ne.jp

*************************************************************************/
#include "gd.h"
#include <stdio.h>
#include <string.h>
#include <math.h>

int getcommex(FILE * fpin, char * comm);

char ctrstr[BUFSIZ]     ="9876543210";
char filename[BUFSIZ]   ="strip.gif";
char stripfmt[BUFSIZ]   ="";

#define stripfmt15 "0123456789:AP,-"
#define stripfmt14 "0123456789:AP-"

/************************************************************************/
int main(int argc, char * argv[])   {

    FILE * fpin;
    gdImagePtr imgout, imgin;

    int inwidth;
    int outwidth;
    int outheight;
    int out_x;

    char commex[BUFSIZ]="";

    int inpos[BUFSIZ];

    int i, j;
    char * c;
    char * p;

    /* arg の 受け入れ                                                  */
    if ( argc > 1) {
        strcpy(ctrstr, argv[1]);
    }
    if ( argc > 2) {
        strcpy(filename, argv[2]);
    }
    if ( argc > 3) {
        strcpy(stripfmt, argv[3]);
    }

    /* file を open                                                     */
    fpin = fopen(filename, "rb");

    /* .gif ファイルを読み込む                                          */
    imgin = gdImageCreateFromGif(fpin);

    /* 入力イメージの幅                                                 */
    inwidth = gdImageSX(imgin);

    /* GIF comment extention を読む                                     */
    if ( getcommex(fpin, commex) == -1) {
        /* commnet extention がないときの文字数の設定                   */

        /*   stripfmt が指定されているときは、その長さ                  */
        /*   stripfmt が指定されていないときは 10                       */
        if ( strlen(stripfmt) == 0 ) {
            inpos[0]=10;
        } else {
            inpos[0]=strlen(stripfmt);
        }

        /* inpos の設定                                                 */
        /*      inpos[0] は、文字数                                     */
        /*      inpos[1] は、左端の位置なので常に 0                     */
        /*      inpos[2...] は、入力イメージを文字数で案分して設定      */
        j=0;
        while ( j <= inpos[0] ) {
            inpos[j+1]= inwidth * j / inpos[0];
        }
    } else {
        /* comment extention の各桁を数値に変換し、inpos へ             */
        c=commex;
        i=0;
        inpos[i]=0;
        while (*c != 0) {
            if  (*c == ':') {
                i++;
                inpos[i]=0;
            } else {
                j = *c - '0';
                inpos[i]=inpos[i]*10+j;
            }
            c++;
        }
    }

    /*  .gif ファイルを閉じる                                           */
    fclose(fpin);

    /*  stripfmt が指定が省略されている場合の解釈                       */
    if ( strlen(stripfmt) == 0 ) {
        if (inpos[0] > 14) {
            strcpy(stripfmt, stripfmt15);
        } else {
            strncpy(stripfmt, stripfmt14, inpos[0]);
        }
    }

    /* outwidth :   出力するイメージの幅
                    プロポーショナルな指定もできるので、ちょっと面倒です。
                    inpos から得られた各桁の合計
        例 0 の幅: inpos[2]-inpos[1]
            9 の幅: inpos[11]-inpos[10]                                 */
    c = ctrstr;
    outwidth=0;
    while   (*c != 0 ) {
        j = strchr(stripfmt,(int) *c) - stripfmt;
        outwidth    = outwidth + inpos[j+2]-inpos[j+1];
        c++;
    }

    /*  outheight : イメージの高さ      入力の gif と同じ               */
    outheight = gdImageSY(imgin);

    /*  幅と高さを指定して gdImage を作成する。戻り値は gdImagePtr      */

    imgout = gdImageCreate(outwidth, outheight);

    /*  位置を指定してコピーする
        gdImageCopy (コピー先, コピー元,
                     先の位置 x, y,
                     元の位置 x,y,
                     幅, 高さ )
        例 0 の位置: inpos[1], 幅:inpos[2]-inpos[1]
            9 の位置: inpos[10],幅:inpos[11]-inpos[10]                  */

    c = ctrstr;
    out_x   = 0;
    while   (*c != 0 ) {
        j = strchr(stripfmt,(int) *c) - stripfmt;

        gdImageCopy(imgout, imgin,
                    out_x, 0,
                    inpos[j+1], 0,
                    inpos[j+2]-inpos[j+1], outheight);
        out_x   = out_x + inpos[j+2]-inpos[j+1];
        c++;
    }
    fflush(stdout);

    /* お約束のヘッダー                                                 */
    printf ( "Content-type: image/gif\n\n");

    /*  gdImage を出力する                                              */
    gdImageGif(imgout, stdout);

    fflush(stdout);

    gdImageDestroy(imgin);
    gdImageDestroy(imgout);

    return 0;
}

/*************************************************************************
    int getcommex(FILE * fp, char *comm)
        GIF comment extention を読む
        戻り値
            GIF comment extention を読めた場合は 0
            読めなかった場合は -1

    void gifstr(FILE *fp, const long p, const int n, char *comm)
        p で指定された位置から n Byte を comm へ読み込む

    int gifbyte(FILE * fp, const long p)
        p で指定された 1 Byte を数値として読む

    int gifbit(FILE * fp, const long p, const int pp, const int n)
        p で指定された 1 Byte の pp で指定された bit から n bit を数値と
        して読む
*************************************************************************/
int gifbyte(FILE * fp, const long p) {

    unsigned char c;

    fseek(fp, p, 0);
    c = fgetc(fp);
    return c;
}
/************************************************************************/
int gifbit(FILE *fp, const long p, const int pp, const int n) {

    unsigned char c;

    fseek(fp, p, 0);
    c = fgetc(fp);
    c = c << (pp);
    c = c >> (8-n);
    return c;
}
/************************************************************************/
void gifstr(FILE *fp, const long p, const int n, char *comm) {

    int c;
    int i = 0;

    fseek(fp, p, 0);
    while (i++ < n) {
        c = fgetc(fp);
        *comm++=c;
    }
    *comm=0;
}
/************************************************************************/
int getcommex(FILE *fp, char *comm){

    double sgct=0;
    long p=0;
    int n;
    int ret=-1;

    gifstr(fp,0,6,comm);                    /* header : "GIF89a"        */
    /* エラーチェックをしようと、おもいつつも手抜き(^^;;;               */

    if (        gifbit(fp,10,0,1) == 1 ) {  /* Global Color Table Flag
                                                                (1Bit)  */
        sgct =  gifbit(fp,10,5,3);          /* Size of Global Color Table
                                                                (3Bits) */
        sgct =  sgct+1;
        sgct =  pow(2,sgct) * 3;
    }
    p=13+(long) sgct;

    /* commnet extention が最初にある場合にしか対応していない。
                                                    これは手抜き(^^;;;  */
    if (gifbyte(fp, p)==0x21) {             /*  block                   */
        if (gifbyte(fp, p+1)==0xfe) {       /*  commnet extention       */
            n=gifbyte(fp, p+2);             /*      length              */
            gifstr(fp, p+3, n, comm);
            ret=0;
        }
    }
    return ret;
}

戻る