This source file includes following definitions.
- main
- QuitGifError
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
#include "gif_lib.h"
#include "getarg.h"
#define PROGRAM_NAME "gifhisto"
#define DEFAULT_HISTO_WIDTH 100
#define DEFAULT_HISTO_HEIGHT 256
#define HISTO_BITS_PER_PIXEL 2
static char
*VersionStr =
PROGRAM_NAME
VERSION_COOKIE
" Gershon Elber, "
__DATE__ ", " __TIME__ "\n"
"(C) Copyright 1989 Gershon Elber.\n";
static char
*CtrlStr =
PROGRAM_NAME
" v%- t%- s%-Width|Height!d!d n%-ImageNumber!d b%- h%- GifFile!*s";
static int
ImageWidth = DEFAULT_HISTO_WIDTH,
ImageHeight = DEFAULT_HISTO_HEIGHT,
ImageN = 1;
static GifColorType
HistoColorMap[] = {
{ 0, 0, 0 },
{ 255, 0, 0 },
{ 0, 255, 0 },
{ 0, 0, 255 }
};
static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut);
int main(int argc, char **argv)
{
int i, j, ErrorCode, NumFiles, ExtCode, CodeSize, NumColors = 2, ImageNum = 0;
bool Error, TextFlag = false, SizeFlag = false,
ImageNFlag = false, BackGroundFlag = false, HelpFlag = false;
long Histogram[256];
GifRecordType RecordType;
GifByteType *Extension, *CodeBlock;
char **FileName = NULL;
GifRowType Line;
GifFileType *GifFileIn = NULL, *GifFileOut = NULL;
if ((Error = GAGetArgs(argc, argv, CtrlStr, &GifNoisyPrint,
&TextFlag, &SizeFlag, &ImageWidth, &ImageHeight,
&ImageNFlag, &ImageN, &BackGroundFlag,
&HelpFlag, &NumFiles, &FileName)) != false ||
(NumFiles > 1 && !HelpFlag)) {
if (Error)
GAPrintErrMsg(Error);
else if (NumFiles > 1)
GIF_MESSAGE("Error in command line parsing - one GIF file please.");
GAPrintHowTo(CtrlStr);
exit(EXIT_FAILURE);
}
if (HelpFlag) {
(void)fprintf(stderr, VersionStr, GIFLIB_MAJOR, GIFLIB_MINOR);
GAPrintHowTo(CtrlStr);
exit(EXIT_SUCCESS);
}
if (NumFiles == 1) {
if ((GifFileIn = DGifOpenFileName(*FileName, &ErrorCode)) == NULL) {
PrintGifError(ErrorCode);
exit(EXIT_FAILURE);
}
}
else {
if ((GifFileIn = DGifOpenFileHandle(0, &ErrorCode)) == NULL) {
PrintGifError(ErrorCode);
exit(EXIT_FAILURE);
}
}
for (i = 0; i < 256; i++) Histogram[i] = 0;
do {
if (DGifGetRecordType(GifFileIn, &RecordType) == GIF_ERROR)
QuitGifError(GifFileIn, GifFileOut);
switch (RecordType) {
case IMAGE_DESC_RECORD_TYPE:
if (DGifGetImageDesc(GifFileIn) == GIF_ERROR)
QuitGifError(GifFileIn, GifFileOut);
if (GifFileIn->Image.ColorMap)
NumColors = GifFileIn->Image.ColorMap->ColorCount;
else if (GifFileIn->SColorMap)
NumColors = GifFileIn->SColorMap->ColorCount;
else
GIF_EXIT("Neither Screen nor Image color map exists.");
if ((ImageHeight / NumColors) * NumColors != ImageHeight)
GIF_EXIT("Image height specified not dividable by #colors.");
if (++ImageNum == ImageN) {
Line = (GifRowType) malloc(GifFileIn->Image.Width *
sizeof(GifPixelType));
GifQprintf("\n%s: Image %d at (%d, %d) [%dx%d]: ",
PROGRAM_NAME, ImageNum,
GifFileIn->Image.Left, GifFileIn->Image.Top,
GifFileIn->Image.Width, GifFileIn->Image.Height);
for (i = 0; i < GifFileIn->Image.Height; i++) {
if (DGifGetLine(GifFileIn, Line, GifFileIn->Image.Width)
== GIF_ERROR)
QuitGifError(GifFileIn, GifFileOut);
for (j = 0; j < GifFileIn->Image.Width; j++)
Histogram[Line[j]]++;
GifQprintf("\b\b\b\b%-4d", i);
}
free((char *) Line);
}
else {
if (DGifGetCode(GifFileIn, &CodeSize, &CodeBlock) == GIF_ERROR)
QuitGifError(GifFileIn, GifFileOut);
while (CodeBlock != NULL)
if (DGifGetCodeNext(GifFileIn, &CodeBlock) == GIF_ERROR)
QuitGifError(GifFileIn, GifFileOut);
}
break;
case EXTENSION_RECORD_TYPE:
if (DGifGetExtension(GifFileIn, &ExtCode, &Extension) == GIF_ERROR)
QuitGifError(GifFileIn, GifFileOut);
while (Extension != NULL) {
if (DGifGetExtensionNext(GifFileIn, &Extension) == GIF_ERROR)
QuitGifError(GifFileIn, GifFileOut);
}
break;
case TERMINATE_RECORD_TYPE:
break;
default:
break;
}
}
while (RecordType != TERMINATE_RECORD_TYPE);
if (BackGroundFlag) Histogram[GifFileIn->SBackGroundColor] = 0;
if (DGifCloseFile(GifFileIn, &ErrorCode) == GIF_ERROR)
{
PrintGifError(ErrorCode);
exit(EXIT_FAILURE);
}
if (TextFlag) {
for (i = 0; i < NumColors; i++)
printf("%12ld %3d\n", Histogram[i], i);
}
else {
int Color, Count;
long Scaler;
if ((GifFileOut = EGifOpenFileHandle(1, &ErrorCode)) == NULL) {
PrintGifError(ErrorCode);
exit(EXIT_FAILURE);
}
if (EGifPutScreenDesc(GifFileOut,
ImageWidth, ImageHeight, HISTO_BITS_PER_PIXEL, 0,
GifMakeMapObject(4, HistoColorMap)) == GIF_ERROR)
QuitGifError(GifFileIn, GifFileOut);
if (EGifPutImageDesc(GifFileOut,
0, 0, ImageWidth, ImageHeight, false, NULL) == GIF_ERROR)
QuitGifError(GifFileIn, GifFileOut);
Line = (GifRowType) malloc(ImageWidth * sizeof(GifPixelType));
for (Scaler = 0, i = 0; i < NumColors; i++) if (Histogram[i] > Scaler)
Scaler = Histogram[i];
Scaler /= ImageWidth;
if (Scaler == 0) Scaler = 1;
for (Count = ImageHeight, i = 0, Color = 1; i < NumColors; i++) {
int Size;
if ((Size = Histogram[i] / Scaler) > ImageWidth) Size = ImageWidth;
for (j = 0; j < Size; j++)
Line[j] = Color;
for (j = Size; j < ImageWidth; j++)
Line[j] = GifFileOut->SBackGroundColor;
if (++Color >= (1 << HISTO_BITS_PER_PIXEL)) Color = 1;
for (j = 0; j < ImageHeight / NumColors; j++) {
if (EGifPutLine(GifFileOut, Line, ImageWidth) == GIF_ERROR)
QuitGifError(GifFileIn, GifFileOut);
GifQprintf("\b\b\b\b%-4d", Count--);
}
}
if (EGifCloseFile(GifFileOut, &ErrorCode) == GIF_ERROR)
{
PrintGifError(ErrorCode);
exit(EXIT_FAILURE);
}
}
return 0;
}
static void QuitGifError(GifFileType *GifFileIn, GifFileType *GifFileOut)
{
if (GifFileIn != NULL) {
PrintGifError(GifFileIn->Error);
EGifCloseFile(GifFileIn, NULL);
}
if (GifFileOut != NULL) {
PrintGifError(GifFileOut->Error);
EGifCloseFile(GifFileOut, NULL);
}
exit(EXIT_FAILURE);
}