BMPTOPDF

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>

typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef unsigned long       DWORD;

#define FALSE               0
#define TRUE                1

BOOL  GetBMPSize(FILE *BMPStream,long *offset);
void  Write_CrossReferenceTable(FILE *AStream,DWORD ObjectPosArray[],int Count);
void  Write_ContentsObject(FILE *AStream,DWORD ObjectPosArray[],int *ObjectIndex,int w,int h);
int   BMPtoPDF(const char *OpenName,const char *SaveName);

int main(int argc,char *argv[]) {
    if (argc >= 2)
        return (BMPtoPDF(argv[1],argv[2]));
    else {
        printf("Not Found!/n");
        return(1);
    }
}


/* 1ラインの幅を算出 */
int GetLineWidth(WORD biBitCount, int biWidth) {
    return ((biBitCount * biWidth + 15) / 16) * 2 ;
}

/* イメージデータのサイズを算出 */
int GetBitsSize(int biWidth, int biHeight,WORD biBitCount) {
    switch (biBitCount) {
    case     1:
        return ( ((1 * biWidth + 15) / 16) * 2 * (biHeight) );
        break;
    case     4:
        return ( ((4 * biWidth + 15) / 16) * 2 * (biHeight) );
        break;
    case     8:
        return ( biWidth*biHeight )  ;
        break;
    case    24:
        return ( biWidth*biHeight*3 );
        break;
    default   :
        return ( 0 );
        break;
    }
}

/* イメージデータの取得 */
BOOL GetBitsData(FILE *AStream,int bfOffBits,BYTE *BitsData, int biWidth, int biHeight,WORD biBitCount) {
    int i;
    BYTE Dummy[4],DummyCnt;

    fseek(AStream,bfOffBits,SEEK_SET);

    switch (biBitCount) {
    case     1:
        ;
    case     4:
        ;
    case     8:
        DummyCnt= biWidth % 4;
        switch (DummyCnt) {
        case 0:
            for (i=0;i< biHeight;i++)
                fread(BitsData+(biWidth*i),1,biWidth,AStream);
            break;
        case 1 :
            ;
        case 2 :
            ;
        case 3 :
            ;
            for (i=0;i< biHeight;i++) {
                fread(BitsData+(biWidth*i),1,biWidth,AStream);
                fread(Dummy,1,4-DummyCnt,AStream);
            }
            break;
        default:
            return (FALSE);
        }
        break;

        ;
        break;
    case    24:
        DummyCnt= biWidth % 4;
        switch (DummyCnt) {
        case 0:
            for (i=0;i< biHeight;i++)
                fread(BitsData+(biWidth*3*i),1,biWidth*3,AStream);
            break;
        case 1 :
            ;
        case 2 :
            ;
        case 3 :
            for (i=0;i< biHeight;i++) {
                fread(BitsData+(biWidth*3*i),1,biWidth*3,AStream);
                fread(Dummy,1,DummyCnt,AStream);
            }
            break;
        default:
            return (FALSE);
        }
        break;
    }
    return (TRUE);
}

/* イメージデータを反転させる */
BOOL TurnBits(BYTE *BitsData,int BitsSize,int biWidth,WORD biBitCount) {
    int i,j,LineWidth=0;
    BYTE *buffer,*Linebuffer,tmp;

    // 1ラインの幅を算出
    switch (biBitCount) {
    case     1:
        ;
    case     4:
        LineWidth=GetLineWidth(biBitCount,biWidth);
        break;
    case     8:
        LineWidth=biWidth;
        break;
    case    24:
        LineWidth=biWidth*3;
        break;
    }

    Linebuffer=(BYTE *)malloc(LineWidth);
    if (Linebuffer==NULL)
        return FALSE;

    buffer=(BYTE *)malloc(BitsSize);
    if (buffer==NULL) {
        free(Linebuffer);
        return FALSE;
    }

    if (biBitCount==24) {
        for (i=0;i< (BitsSize / LineWidth);i++) {
            /* 1ラインを取得 */
            memcpy(Linebuffer,BitsData+(LineWidth*i),LineWidth);

            /* BGR<->RGB変換 */
            for (j=0;j<LineWidth ;j+=3) {
                tmp             = Linebuffer[j];
                Linebuffer[j]   = Linebuffer[j+2];
                Linebuffer[j+2] = tmp;
            }
            /* 1ラインをメモリに書き込む */
            memcpy(buffer+ (BitsSize- LineWidth * (i+1) ),Linebuffer,LineWidth);
        }
    } else {
        for (i=0;i< (BitsSize / LineWidth);i++) {
            /* 1ラインを取得 */
            memcpy(Linebuffer,BitsData+(LineWidth*i),LineWidth);
            /* 1ラインをメモリに書き込む */
            memcpy(buffer+ (BitsSize- LineWidth * (i+1) ),Linebuffer,LineWidth);
        }
    }

    // 元のデータと置き換える
    memcpy(BitsData,buffer,BitsSize);

    free(buffer);
    free(Linebuffer);

    return(TRUE);
}

BOOL GetBMPSize(FILE *BMPStream,long *offset) {
    //WORD wrk;
    //BYTE Sampling;

    //WORD SOF0 =0xFFC0; /* 通常 */
    //WORD SOF2 =0xFFC2; /* 進歩 */

    /*----------------------------*/
    /* ファイルヘッダ部 (14 Byte) */
    /*----------------------------*/

    int count = 0;
    long var_long;
    short var_short;
    char s[10];

    // BITMAP 認識文字 "BM"
    if (fread(s, 2, 1, BMPStream) == 1) {
        if (memcmp(s, "BM", 2) == 0) {
            printf("[BM] BITMAP file/n");
        } else {
            fprintf(stderr, "%s : Not a BITMAP file/n", s);
            exit(1);
        }
        count += 2;
    }
    printf("  [BITMAPFILEHEADER]/n");
    // ファイルサイズ
    if (fread(&var_long, 4, 1, BMPStream) == 1) {
        printf("  Size          : %ld [Byte]/n", var_long);
        count += 4;
    }
    // 予約領域 0
    if (fread(&var_short, 2, 1, BMPStream) == 1) {
        count += 2;
    }
    // 予約領域 0
    if (fread(&var_short, 2, 1, BMPStream) == 1) {
        count += 2;
    }
    // ファイルの先頭から画像データまでの位置
    if (fread(&var_long, 4, 1, BMPStream) == 1) {
        printf("  OffBits       : %ld [Byte]/n", var_long);
        *offset = var_long;
        count += 4;
    }
    return count;
}

/*------------------------------------------------------------------*/
/* 情報ヘッダ部 (12 Byte -> OS/2 Bitmap, 40 Byte -> Windows Bitmap) */
/*------------------------------------------------------------------*/
int infoheader(FILE *BMPStream,
               short *infosize,
               long *width, long *height,
               long *x_coodinate, long *y_coodinate,
               short *BitCount,
               long *ClrUsed) {
    int count = 0;
    long var_long, compress = 0;
    short var_short;

    // BITMAPINFOHEADER のサイズ
    if (fread(&var_long, 4, 1, BMPStream) == 1) {
        count += 4;
        *infosize = var_long;
    }

    printf("  [BITMAPINFOHEADER]/n");
    // OS/2 Bitmap
    if (*infosize == 12) {
        // 画像データの幅
        if (fread(&var_short, 2, 1, BMPStream) == 1) {
            printf("  Width         : %d [pixel]/n", var_short);
            *width = var_short;
            count += 2;
        }
        // 画像データの高さ
        if (fread(&var_short, 2, 1, BMPStream) == 1) {
            printf("  Height        : %d [pixel]/n", var_short);
            *height = var_short;
            count += 2;
        }
        // プレーン数 (1のみ)
        if (fread(&var_short, 2, 1, BMPStream) == 1) {
            count += 2;
        }
        // 1画素あたりのビット数 (1, 4, 8, 24, 32)
        if (fread(&var_short, 2, 1, BMPStream) == 1) {
            printf("  BitCount      : %d [bit]/n", var_short);
            *BitCount = var_short;
            count += 2;
        }
    }
    // Windows BMP
    else if (*infosize == 40) {
        // 画像データの幅
        if (fread(&var_long, 4, 1, BMPStream) == 1) {
            printf("  Width         : %ld [pixel]/n", var_long);
            *width = var_long;
            count += 4;
        }
        // 画像データの高さ
        if (fread(&var_long, 4, 1, BMPStream) == 1) {
            printf("  Height        : %ld [pixel]/n", var_long);
            *height = var_long;
            count += 4;
        }
        // プレーン数 (1のみ)
        if (fread(&var_short, 2, 1, BMPStream) == 1) {
            count += 2;
        }
        // 1画素あたりのビット数 (1, 4, 8, 24, 32)
        if (fread(&var_short, 2, 1, BMPStream) == 1) {
            printf("  BitCount      : %d [bit]/n", var_short);
            *BitCount = var_short;
            count += 2;
        }
        // 圧縮方式  0 : 無圧縮
        //           1 : BI_RLE8 8bit RunLength 圧縮
        //           2 : BI_RLE4 4bit RunLength 圧縮
        if (fread(&var_long, 4, 1, BMPStream) == 1) {
            printf("  Compression   : %ld/n", var_long);
            compress = var_long;
            count += 4;
        }
        // 画像データのサイズ
        if (fread(&var_long, 4, 1, BMPStream) == 1) {
            printf("  SizeImage     : %ld [Byte]/n", var_long);
            count += 4;
        }
        // 横方向解像度 (Pixel/meter)
        if (fread(&var_long, 4, 1, BMPStream) == 1) {
            printf("  XPelsPerMeter : %ld [pixel/m]/n", var_long);
            *x_coodinate = var_long;
            count += 4;
        }
        // 縦方向解像度 (Pixel/meter)
        if (fread(&var_long, 4, 1, BMPStream) == 1) {
            printf("  YPelsPerMeter : %ld [pixel/m]/n", var_long);
            *y_coodinate = var_long;
            count += 4;
        }
        // 使用色数
        if (fread(&var_long, 4, 1, BMPStream) == 1) {
            printf("  ClrUsed       : %ld [color]/n", var_long);
            *ClrUsed = var_long;
            count += 4;
        }
        // 重要な色の数 0の場合すべての色
        if (fread(&var_long, 4, 1, BMPStream) == 1) {
            count += 4;
        }
    } else {
        fprintf(stderr, "Bitmap Info Header error/n");
    }

    if (compress != 0) {
        fprintf(stderr, "圧縮ビットマップには対応していません/n");
        exit(1);
    }
    if (*BitCount == 4 || *BitCount == 8 || *BitCount == 24 || *BitCount == 32) {
        ;
    } else {
        fprintf(stderr, "%d ビット色には対応していません/n", *BitCount);
        exit(1);
    }
    return count;
}


/*-------------*/
/* OS/2 bitmap */
/*-------------*/
int rgbtriple(FILE *BMPStream,
              long used,
              unsigned char *red,
              unsigned char *green,
              unsigned char *blue) {
    long i;
    int count = 0;

    // ビットの並びは B G R
    for (i = 0; i < used; i++) {
        blue[i] = fgetc(BMPStream);
        green[i] = fgetc(BMPStream);
        red[i] = fgetc(BMPStream);
        count++;
    }

    return count;
}

/*----------------*/
/* Windows bitmap */
/*----------------*/
int rgbquad(FILE *BMPStream,
            long used,
            unsigned char *red,
            unsigned char *green,
            unsigned char *blue) {
    long i;
    int receive, count = 0;

    // ビットの並びは B G R 予約
    for (i = 0; i < used; i++) {
        blue[i] = fgetc(BMPStream);
        green[i] = fgetc(BMPStream);
        red[i] = fgetc(BMPStream);
        receive = fgetc(BMPStream);
        count++;
    }
    return count;
}


void Write_CrossReferenceTable(FILE *AStream,DWORD ObjectPosArray[],int Count) {
    int i;

    fprintf(AStream,"xref/n");
    fprintf(AStream,"0 %d/n",Count+1);
    fprintf(AStream,"0000000000 65535 f /n");

    for (i= 0; i<=Count-1;i++)
        fprintf(AStream,"%0.10d 00000 n /n",ObjectPosArray[i]);
}

void Write_ContentsObject(FILE *AStream,DWORD ObjectPosArray[],int *ObjectIndex,int w,int h) {
    int Length;

    /* PDFコンテンツ */
    ObjectPosArray[*ObjectIndex]  =(DWORD)ftell(AStream);
    fprintf(AStream,"%d 0 obj/n",*ObjectIndex+1);
    fprintf(AStream,"<< /Length %d 0 R >>/n",*ObjectIndex+2);
    fprintf(AStream,"stream/n");

    /* stream */
    Length=ftell(AStream);
    fprintf(AStream,"q/n");
    fprintf(AStream,"%d 0 0 %d 0 0 cm/n",w,h);
    fprintf(AStream,"/Im0 Do/n");
    fprintf(AStream,"Q/n");
    Length=ftell(AStream)-Length;

    fprintf(AStream,"endstream/n");
    fprintf(AStream,"endobj/n");
    *ObjectIndex=*ObjectIndex+1;

    /* stream Length */
    ObjectPosArray[*ObjectIndex] =(DWORD)ftell(AStream);
    fprintf(AStream,"%d 0 obj/n",*ObjectIndex+1);
    fprintf(AStream,"%d/n",Length);
    fprintf(AStream,"endobj/n");
    *ObjectIndex=*ObjectIndex+1;
}

int BMPtoPDF(const char *OpenName,const char *SaveName) {
    int   ObjectIndex;
    short infosize, bits;
    long used = 0, color = 0, offset, width, height, xreso, yreso;
    unsigned char red[256],blue[256],green[256];
    DWORD ObjectPosArray[10];
    FILE  *BMPStream,*AStream;

    int i,j=0;
    DWORD BitsSize;          // イメージデータのサイズ
    BYTE *BitsData;          // イメージデータ
    BYTE  BitsPalette[768];  // カラーパレット


    ObjectIndex=0;

    /* BMPファイルを開く*/
    BMPStream=fopen(OpenName,"rb");
    if(BMPStream==NULL) {
        printf("Error : Can not Open File./n");
        return(-1);
    }

    // ヘッダ情報 BITMAPFILEHEADER
    GetBMPSize(BMPStream, &offset);
    // ヘッダ情報 BITMAPINFOHEADER
    infoheader(BMPStream, &infosize, &width, &height, &xreso, &yreso, &bits, &color);
    //color = usedcolor(bits, color);

    // OS/2 Bitmap
    if (infosize == 12) {
        if (bits == 1 || bits == 4 || bits == 8) {
            used = rgbtriple(BMPStream, color, red, green, blue);
        }
        printf("[OS/2 bitmap] --- %d bit %ld color/n", bits, used);
    }
    // Windows Bitmap
    else if (infosize == 40) {
        if (bits == 1 || bits == 4 || bits == 8) {
            used = rgbquad(BMPStream, color, red, green, blue);
        }
        printf("[Windows bitmap] --- %d bit %ld color/n", bits, used);
    } else if (infosize == 108) {
        printf("[other bitmap]/n");
    } else {
        fprintf(stderr, "BITMAP INFOHEADER error/n");
    }


    /* とりあえず、8bitと24bitのみ*/
    if (!(bits == 8 || bits == 24)) {
        printf("Error : 対応していない形式です/n");
        fclose(BMPStream);
        return(-1);
    }

    /* PDFファイル作成 */
    AStream=fopen(SaveName,"wb+");
    if(AStream==NULL) {
        printf("Error : Can not Create File./n");
        fclose(BMPStream);
        return(-1);
    }

    /* ------------------------------------------------------------- */
    /*  Writting PDF (PDFの書式)                                     */
    /* ------------------------------------------------------------- */

    /* PDF のバージョン */
    fprintf(AStream,"%%PDF-1.2/n");

    /* Catalog */
    ObjectPosArray[ObjectIndex] =ftell(AStream);
    fprintf(AStream,"%d 0 obj/n",ObjectIndex+1);
    fprintf(AStream,"<</n");
    fprintf(AStream,"/Type /Catalog/n");
    fprintf(AStream,"/Pages 2 0 R/n");
    /* View Option (100%) */
    fprintf(AStream,"/OpenAction [3 0 R /XYZ -32768 -32768 1 ]/n");
    fprintf(AStream,">>/n");
    fprintf(AStream,"endobj/n");
    ObjectIndex++;

    /* Parent Pages */
    ObjectPosArray[ObjectIndex] =ftell(AStream);
    fprintf(AStream,"%d 0 obj/n",ObjectIndex+1);
    fprintf(AStream,"<</n");
    fprintf(AStream,"/Type /Pages/n");
    fprintf(AStream,"/Kids [ 3 0 R ]/n");
    fprintf(AStream,"/Count 1/n");
    fprintf(AStream,">>/n");
    fprintf(AStream,"endobj/n");
    ObjectIndex++;

    /* Kids Page */
    ObjectPosArray[ObjectIndex] =ftell(AStream);
    fprintf(AStream,"%d 0 obj/n",ObjectIndex+1);
    fprintf(AStream,"<</n");
    fprintf(AStream,"/Type /Page/n");
    fprintf(AStream,"/Parent 2 0 R/n");
    fprintf(AStream,"/Resources/n");
    fprintf(AStream,"<</n");
    fprintf(AStream,"/XObject << /Im0 4 0 R >>/n");

    // ProcSet
    switch (bits) {
    case 4  :
        ;
    case 8  :
        fprintf(AStream,"/ProcSet [ /PDF /ImageI ]/n");
        break;
    default :
        fprintf(AStream,"/ProcSet [ /PDF /ImageC ]/n");
        break;
    }

    fprintf(AStream,">>/n");
    fprintf(AStream,"/MediaBox [ 0 0 %d %d ]/n",width,abs(height));

    // コンテンツのオブジェクト番号
    switch (bits) {
    case 4  :
        ;
    case 8  :
        fprintf(AStream,"/Contents 6 0 R/n");
        break;
    default :
        fprintf(AStream,"/Contents 5 0 R/n");
        break;
    }

    fprintf(AStream,">>/n");
    fprintf(AStream,"endobj/n");
    ObjectIndex++;

    /* XObject Resource */
    ObjectPosArray[ObjectIndex] =ftell(AStream);
    fprintf(AStream,"%d 0 obj/n",ObjectIndex+1);
    fprintf(AStream,"<</n");
    fprintf(AStream,"/Type /XObject/n");
    fprintf(AStream,"/Subtype /Image/n");
    fprintf(AStream,"/Name /Im0/n");
    fprintf(AStream,"/Width %d/n",width);
    fprintf(AStream,"/Height %d/n",abs(height));

    fprintf(AStream,"/Filter []/n");

    /* BitsPerComponent */
    switch (bits) {
    case 1  :
        fprintf(AStream,"/BitsPerComponent 1/n");
        break;
    case 4  :
        fprintf(AStream,"/BitsPerComponent 4/n");
        break;
    default :
        fprintf(AStream,"/BitsPerComponent 8/n");
        break;
    }

    /* ColorSpace */
    switch (bits) {
    case     1   :
        fprintf(AStream,"/ColorSpace /DeviceGray/n");
        break;
    case     4   :
        ;
    case     8   :
        fprintf(AStream,"/ColorSpace [/Indexed /DeviceRGB 255 %d 0 R]/n",ObjectIndex+2);
        break;
    case     24  :
        fprintf(AStream,"/ColorSpace /DeviceRGB/n");
        break;
    }

    /* イメージデータのサイズを算出 */
    BitsSize =GetBitsSize(width, abs(height),bits);
    fprintf(AStream,"/Length %d >>/n",BitsSize);

    /* イメージデータの書き込み */
    fprintf(AStream,"stream/n");

    /* 生データを突っ込む */
    BitsData=(BYTE *)malloc(BitsSize);
    GetBitsData(BMPStream,offset,BitsData,width,height,bits);
    TurnBits(BitsData,BitsSize,width,bits);
    fwrite(BitsData,1,BitsSize,AStream);
    free(BitsData);

    fprintf(AStream,"/nendstream/n");
    fprintf(AStream,"endobj/n");
    ObjectIndex++;

    // カラーパレットの書き込み
    if (bits==4 || bits==8) {
        for (i=0;i<768;i+=3) {
            BitsPalette[i]  = red[j];
            BitsPalette[i+1]= green[j];
            BitsPalette[i+2]= blue[j];
            j++;
        }

        ObjectPosArray[ObjectIndex] =ftell(AStream);
        fprintf(AStream,"%d 0 obj/n",ObjectIndex+1);
        fprintf(AStream,"<</n");
        fprintf(AStream,"/Length 768/n");
        fprintf(AStream,"/Filter []/n");
        fprintf(AStream,">>/n");
        fprintf(AStream,"stream/n");
        fwrite(BitsPalette,1,768,AStream);
        fprintf(AStream,"/nendstream/n");
        fprintf(AStream,"endobj/n");
        ObjectIndex++;
    }

    /* Contents Stream & Object */
    Write_ContentsObject(AStream,ObjectPosArray,&ObjectIndex,width,height);

    /* CrossReferenceTable */
    ObjectPosArray[ObjectIndex] =ftell(AStream);
    Write_CrossReferenceTable(AStream,ObjectPosArray,(int)ObjectIndex);

    /* trailer */
    fprintf(AStream,"trailer/n");
    fprintf(AStream,"<</n");
    fprintf(AStream,"/Size %d/n",ObjectIndex+1);
    fprintf(AStream,"/Root 1 0 R/n");
    fprintf(AStream,">>/n");
    fprintf(AStream,"startxref/n");
    fprintf(AStream,"%d/n",ObjectPosArray[ObjectIndex]);
    fprintf(AStream,"%%%%EOF/n");

    fclose(BMPStream);
    fclose(AStream);

    printf("/nSuccess!/n");

    return (0);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值