/************************************************************************* 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; }