// BMP2PDF (8bit/24bitのみ対応)
#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],"c:\\bmppdf.pdf"));
else
{
printf("Not Found!\n");
return(0);
}
}
/* 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);
}
上記のプログラムを低水準ファイル入出力で書き換えたいのですがうまくいきません。
どうすれば良いでしょうか
なにが/どう うまくいきません なのでしょうか?
これだけ長いコードを晒して"うまくいきません"の一言てのはないと思うぞ。
ふ・ざ・け・ん・な
このコードって
http://madia.world.coocan.jp/vc/vc_bbs/200307_03070030.html
ここで出てるやつまんまかな??
だとしたら3年近く前の話!?
> 低水準ファイル入出力
って何を想定してるんだろ・・・。
fopenとか普通に使ってるみたいだし。
_openとかを想定してるのかな??
…僕のハンドルを騙る阿呆がいるな。
デバッグというものはされているんでしょうか。
まず問題の切り分けありきだと思うのですが。
# 途中まで読んだけど工数が勿体無く断念。
色々やってみてできました。
επιστημη様、じゃんぬねっと様ご迷惑をおかけしました。
> 色々やってみてできました。
その色々やったことを載せてください。
でないとカナリ失礼です。(これでおわったらあらしだろ)
ツイート | ![]() |