C言語で画像ファイルが作れません

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ユーキ

C言語で画像ファイルが作れません

#1

投稿記事 by ユーキ » 10年前

修士論文作成のために(x, y, z) のテキストデータを画像にすることが必要でネットから下記のプログラムを見つけて、そのプログラム(プログラム名は1.c)と試しに作った
0 0 0
0 1 0
0 2 3
0 3 0
1 0 0
1 1 2
1 2 2
1 3 1
2 0 3
2 1 0
2 2 1
2 2 2
という内容のテキストデータ(プログラム名は1.txt)を同じディレクトリに入れgccでコンパイルして実行しても、コンパイルはされるのですが最初のvoid usage(void)関数内の内容を表示するだけで画像データができません。
自分はC言語初心者なのでどこをどうやってなおしていいのかが全くわかりません。
OSはLinuxを使っています。
どこをなおしていいのかまたはこれ以外に数字を画像化する方法がありましたら、助言をお願いいたします。
下記のプログラムを紹介しているサイトのURLはこちらです。
http://www.kk.iij4u.or.jp/~kondo/bmp/

コード:

/***************************************************************/
/* データ → 画像変換ソフト                                    */
/* 出力画像フォーマット: bitmap 形式                           */
/*                                                             */
/* データフォーマット                                          */
/* gnuplot で                                                  */
/* set data style lines                                        */
/* splot で表示できる形式                                      */
/*                                                             */
/* ("%f %f %f\n", x, y, z)                                     */
/* ("\n")                                                      */
/*                                                             */
/* kondo@kk.iij4u.or.jp                                        */
/* 2000.08.03                                                  */
/***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#define BITCOUNT (8)
#define BUF_SIZE (1000)
#ifndef _MAX_PATH
#define _MAX_PATH (255)
#endif
#ifndef UCHAR_MAX
#define UCHAR_MAX (255)
#endif
#ifndef UCHAR_MIN
#define UCHAR_MIN (0)
#endif

static char cmdname[] = "txt2bmp";

int optind = 1; // オプションでない最初の引数までの文字列数
int optopt;     // オプション文字 
char *optarg;   // オプション引数

double max = 0.0, min = 0.0;
int maxopt = 0, minopt = 0;

void usage(void)
{
  fprintf(stderr,
          "\n"
          "ASCIIテキストデータ ---> BMP フォーマット変換プログラム\n"
          "usage : %s [option] <text_file> [bitmap_file]\n"
          "  bitmap_file の指定が無い場合"
          " text_file.bmp のファイルが作成されます\n"
          "\n"
          "option :\n"
          "  -M : 最大値を指定します\n"
          "  -m : 最小値を指定します\n"
          "\n"
          "データ形式 : X座標 Y座標 Z値\n"
          "\tx y z\n"
          "\tx y z\n"
          "\t: : :\n"
          "\t      (改行のみでラインの区切り)\n"
          "\tx y z\n"
          "\t: : :\n"
          "\n", cmdname);
  exit(1);
}

void openerror(char *filename)
{
  fprintf(stderr, "Can't open file: %s\n", filename);
  exit(1);
}

void allocerror(void)
{
  fprintf(stderr, "memory allocation error.\n");
  exit(1);
}

/*----------------*/
/* ファイル名取得 */
/*----------------*/
int getbasename(char *dest, char *src)
{
  int i, start, end, ret;

  i = -1;
  start = 0;
  end = 0;

  // ファイル名のはじめと終わりを検出 
  while (src[++i]) {
    if (src[i] == '\\' || src[i] == ':') {
      start = i + 1;
      end = 0;
    }
    if (src[i] == '.') {
      end = i;
    }
  }
  if (end == 0) {
    end = i;
  }

  // ファイル名が有る場合 
  if (start < end) {
    for (i = 0; i < end; i++) {
      dest[i] = src[i];
    }
    dest[i] = '\0';
    ret = 1;
  }
  else {
    dest[0] = '\0';
    ret = 0;
  }

  return ret;
}

/*----------------------*/
/* コメント行読み飛ばし */
/*----------------------*/
void commentskip(FILE * fp)
{
  int c;

  do {
    while ((c = fgetc(fp)) == '\n') {
      ;
    }
    // # ; / があれば読み飛ばし 
    if ((c == '#') || (c == ';') || (c == '/')) {
      while ((c = fgetc(fp)) != '\n') {
        ;
      }
    }
    else {
      break;
    }
  } while (1);

  ungetc(c, fp);
}

/*------------------*/
/* 最大値最小値検索 */
/*------------------*/
void maxmin(FILE * fp,
            double *maxx, double *minx,
            double *maxy, double *miny,
            int *sx, int *sy)
{
  int n, cx, cy, maxcx, flag;
  double x, y, z, xrange, yrange, xunit, yunit;
  char s[2], buf[BUF_SIZE];

  cx = 0;                       // x 方向のデータ数 
  cy = 0;                       // y 方向のデータ数 
  maxcx = 0;                    // x 方向のデータ数最大値 
  flag = 0;

  rewind(fp);
  commentskip(fp);

  // 値の初期化 
  if (fgets(buf, BUF_SIZE, fp) != NULL) {
    n = sscanf(buf, "%lf %lf %lf %1s", &x, &y, &z, s);
    if (n >= 3) {
      *maxx = x;
      *minx = x;
      *maxy = y;
      *miny = y;
      if (maxopt == 0) {
        max = z;
      }
      if (minopt == 0) {
        min = z;
      }
    }
  }

  rewind(fp);

  while (fgets(buf, BUF_SIZE, fp) != NULL) {
    n = sscanf(buf, "%lf %lf %lf %1s", &x, &y, &z, s);

    // EOF で終了 
    if (feof(fp)) {
      break;
    }
    // データ数3個以上の場合 
    else if (n >= 3) {
      cx++;
      if (flag == 0) {
        cy++;
      }
      flag = 1;

      // 最大値検索 
      if (z < min) {
        if (minopt == 0) {
          min = z;
    }
      }
      if (z > max) {
        if (maxopt == 0) {
          max = z;
    }
      }

      if (x < *minx) {
        *minx = x;
      }
      else if (x > *maxx) {
        *maxx = x;
      }

      if (y < *miny) {
        *miny = y;
      }
      else if (y > *maxy) {
        *maxy = y;
      }
    }
    // 改行のみの場合 
    else {
      if (flag == 1) {
        if (cx > maxcx) {
          maxcx = cx;
        }
      }

      flag = 0;
      cx = 0;
    }
  }

  // データ範囲 
  xrange = *maxx - *minx;
  yrange = *maxy - *miny;

  printf("Horizontal : min = %g, max = %g, range = %g\n",
         *minx, *maxx, xrange);
  printf("Vertical   : min = %g, max = %g, range = %g\n",
         *miny, *maxy, yrange);
  printf("Data       : min = %g, max = %g\n", min, max);

  if (max <= min) {
    fprintf(stderr, "最大値よりも最小値が大きい\n");
    exit(1);
  }

  // 1画素あたりの単位 
  xunit = xrange / maxcx;
  yunit = yrange / cy;

  // 画素数 
  *sx = (int) (xrange / xunit);
  *sy = (int) (yrange / yunit);
}

/*----------------*/
/* データ読み込み */
/*----------------*/
void dataread(FILE * fp,
              unsigned char **data,
              double maxx, double minx,
              double maxy, double miny,
              int sx, int sy)
{
  int n;
  double x, y, z,
         xrange, yrange, zrange,
         value;
  char s[2], buf[BUF_SIZE];

  xrange = maxx - minx;
  yrange = maxy - miny;
  zrange = max - min;

  rewind(fp);
  commentskip(fp);

  while (fgets(buf, BUF_SIZE, fp) != NULL) {
    n = sscanf(buf, "%lf %lf %lf %1s", &x, &y, &z, s);

    if (feof(fp)) {
      break;
    }
    else if (n >= 3) {
      int ix, iy;

      // 座標変換 
      ix = (int) (0.5 + (x - minx) * (double) (sx - 1) / xrange);
      iy = (int) (0.5 + (y - miny) * (double) (sy - 1) / yrange);

      value = (unsigned char) (255.9 * (z - min) / zrange);
      if (value > UCHAR_MAX) {
        value = UCHAR_MAX;
      }
      else if (value < UCHAR_MIN) {
        value = UCHAR_MIN;
      }
      data[ix][iy] = value;
    }
  }
}

/*---------------------------------*/
/* ファイルヘッダ BITMAPFILEHEADER */
/*---------------------------------*/
int fileheader(FILE * fp,
               long size, long offset)
{
  long count, filesize;
  short reserved = 0;
  char s[2];

  rewind(fp);

  // 識別文字 BM 
  s[0] = 'B';
  s[1] = 'M';
  fwrite(s, sizeof(char), 2, fp);

  printf("[BITMAPFILEHEADER]\n");
  // ファイルサイズ bfSize 
  filesize = size + offset;
  printf("  File Size          = %ld[Bytes]\n", filesize);
  fwrite(&filesize, sizeof(long), 1, fp);
  // 予約エリア bfReserved1 
  fwrite(&reserved, sizeof(short), 1, fp);
  // 予約エリア bfReserved2 
  fwrite(&reserved, sizeof(short), 1, fp);
  // データ部までのオフセット bfOffBits 
  printf("  Bitmap Data Offset = %ld [Bytes]\n", offset);
  fwrite(&offset, sizeof(long), 1, fp);

  // ファイルヘッダサイズ 14 Byte 
  if ((count = ftell(fp)) != 14) {
    fprintf(stderr, "BITMAPFILEHEADER write error : %ld\n", count);
    exit(1);
  }

  return count;
}

/*-----------------------------*/
/* 情報ヘッダ BITMAPINFOHEADER */
/*-----------------------------*/
int bitmapheader(FILE * fp,
                 long width, long height, long size)
{
  long count, var_long;
  short var_short;

  fseek(fp, 14, SEEK_SET);

  printf("[BITMAPINFOHEADER]\n");
  // 情報ヘッダのサイズ biSize (Windows BMP は 40) 
  var_long = 40;
  fwrite(&var_long, sizeof(long), 1, fp);
  // 画像の幅 biWidth 
  var_long = width;
  printf("  Width              = %ld [pixels]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // 画像の高さ biHeight 
  // (正数ならば左下から右上, マイナスならば左上から右下) 
  var_long = height;
  printf("  Height             = %ld [pixels]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // プレーン数 biPlanes (必ず 1) 
  var_short = 1;
  printf("  Planes             = %hd\n", var_short);
  fwrite(&var_short, sizeof(short), 1, fp);
  // 1ピクセルのデータ数 biBitCount (1, 4, 8, 24, 32) 
  var_short = BITCOUNT;
  printf("  Bits Per Pixel     = %hd [bits]\n", var_short);
  fwrite(&var_short, sizeof(short), 1, fp);

  // 圧縮 biCompression (無圧縮ならば 0) 
  var_long = 0;
  printf("  Compression        = %ld\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // 画像のサイズ biSizeImage 
  var_long = size;
  printf("  Bitmap Data Size   = %ld [Bytes]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // 横方向解像度 pixel/m biXPelPerMeter 
  // (96dpi, 1inch = 0.0254m のとき 96/0.0254 = 3780) 
  var_long = 3780;
  printf("  HResolution        = %ld [pixel/m]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // 縦方向解像度 pixel/m biYPelPerMeter 
  // (96dpi, 1inch = 0.0254m のとき 96/0.0254 = 3780) 
  var_long = 3780;
  printf("  VResolution        = %ld [pixel/m]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // パレット数 biClrUsed 
  var_long = 1 << BITCOUNT;
  printf("  Colors             = %ld [colors]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // パレット中の重要な色  biClrImportant 
  var_long = 0;
  printf("  Important Colors   = %ld\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);

  // ファイルヘッダ(14 Byte) + 情報ヘッダサイズ(40 Byte) 
  if ((count = ftell(fp)) != 54) {
    fprintf(stderr, "BITMAPINFOHEADER write error : %ld\n", count);
    exit(1);
  }

  return count;
}

/*------------------------*/
/* パレットデータ RGBQUAD */
/*------------------------*/
long rgbquad(FILE * fp)
{
  long i, color, count;

  fseek(fp, 54, SEEK_SET);

  color = 1 << BITCOUNT;

  printf("  Pallete            = %ld [colors] (%ld [Bytes])\n",
         color, 4 * color);
  for (i = 0; i < color; i++) {
    unsigned char red, green, blue, reserved = 0;

    // グレイスケール red = green = blue 
    blue = (unsigned char) i;
    green = (unsigned char) i;
    red = (unsigned char) i;

    fputc(blue, fp);
    fputc(green, fp);
    fputc(red, fp);
    fputc(reserved, fp);
  }

  if ((count = ftell(fp)) != 54 + 4 * color) {
    fprintf(stderr, "RGBQUAD write error : %ld\n", count);
    exit(1);
  }

  return count;
}

/*------------*/
/* 画像データ */
/*------------*/
long imagedata(FILE * fp,
               int x, int y,
               unsigned char **data,
               long offset)
{
  long i, j;
  unsigned char index;

  fseek(fp, offset, SEEK_SET);

  for (j = 0; j < y; j++) {
    for (i = 0; i < x; i++) {
      index = data[i][j];
      fwrite(&index, sizeof(char), 1, fp);
    }
    // 1ラインは 4Byte(long) 境界にあわせる 
    if ((x % 4) != 0) {
      for (i = 0; i < ((x / 4 + 1) * 4) - x; i++) {
        unsigned char zero = 0;

        fwrite(&zero, sizeof(char), 1, fp);
      }
    }
  }

  return ftell(fp);
}

/*-----------------*/
/* BITMAP 書き込み */
/*-----------------*/
void bmpwrite(char *txtfile, char *bmpfile)
{
  int i, j, sx, sy;
  long size, offset;
  double maxx, minx, maxy, miny;
  unsigned char **data;
  FILE *fp1, *fp2;

  // テキストファイル 
  if ((fp1 = fopen(txtfile, "r")) == NULL) {
    openerror(txtfile);
  }

  // 最大値最小値検索 
  maxmin(fp1, &maxx, &minx, &maxy, &miny, &sx, &sy);

  // メモリ確保 
  if ((data = malloc(sx * sizeof(char *))) == NULL) {
    allocerror();
  }
  for (i = 0; i < sx; i++) {
    if ((data[i] = malloc(sy * sizeof(char))) == NULL) {
      allocerror();
    }
    for (j = 0; j < sy; j++) {
      data[i][j] = 0;
    }
  }

  // データ取得 
  dataread(fp1, data, maxx, minx, maxy, miny, sx, sy);

  fclose(fp1);

  if ((fp2 = fopen(bmpfile, "wb")) == NULL) {
    openerror(bmpfile);
  }

  // 画像サイズ (1ラインは4Byte(long)境界にあわせる) 
  if (sx % 4 != 0) {
    size = ((sx / 4 + 1) * 4) * sy;
  }
  else {
    size = sx * sy;
  }
  // 画像データまでのオフセット(ヘッダサイズ) 
  offset = 14 + 40 + 4 * (1 << BITCOUNT);

  // ファイルヘッダ 
  fileheader(fp2, size, offset);
  // 情報ヘッダ 
  bitmapheader(fp2, (long) sx, (long) sy, size);
  // パレットデータ 
  rgbquad(fp2);
  // 画像データ 
  imagedata(fp2, sx, sy, data, offset);

  free(data);
  fclose(fp2);
}

/*----------------------*/
/* オプション引数の解析 */
/*----------------------*/
int getopt(int nargc, char **nargv, char *ostr)
{
  static char *place = "",
              *lastostr = (char *) 0;
  char *oli;

  if (ostr != lastostr) {
    lastostr = ostr;
    place = "";
  }
  if (!*place) {
    if ((optind >= nargc) 
        || (*(place = nargv[optind]) != '-')
        || !*++place) {
      place = "";
      return (EOF);
    }
    if (*place == '-') {
      ++optind;
      return (EOF);
    }
  }
  // オプション文字のチェック 
  if ((optopt = (int) *place++) == (int) ':'
      || !(oli = strchr(ostr, optopt))) {
    if (!*place) {
      ++optind;
    }

    fprintf(stderr, "%s : オプションが違います -- %c\n", *nargv, optopt);
    return (int) '?';
  }
  // オプション引数のチェック 
  if (*++oli != ':') {
    optarg = NULL;
    if (!*place) {
      ++optind;
    }
  }
  // オプション引数が必要な場合 
  else {
    if (*place) {
      optarg = place;
    }
    // 引数が無い場合 
    else if (nargc <= ++optind) {
      place = "";
      fprintf(stderr, "%s : オプションには引数が必要です -- %c\n",
              *nargv, optopt);
      return (int) '?';
    }
    // 引数がある場合 
    else {
      optarg = nargv[optind];
    }
    place = "";
    ++optind;
  }
  return (optopt);
}

/**************/
/* メイン関数 */
/**************/
int main(int argc, char *argv[])
{
  int c;
  char txtfile[_MAX_PATH], bmpfile[_MAX_PATH], basename[_MAX_PATH];

  while ((c = getopt(argc, argv, "M:m:")) != EOF) {
    switch (c) {
    case 'M':                  // 最大値 
      max = strtod(optarg, (char **) NULL);
      maxopt = 1;
      break;
    case 'm':                  // 最小値 
      min = strtod(optarg, (char **) NULL);
      minopt = 1;
      break;
    case '?':
      usage();
      break;
    default:
      usage();
      break;
    }
  }

  if (argc - optind < 1) {
    usage();
  }
  else if (argc - optind == 1) {
    strcpy(txtfile, argv[optind]);
    getbasename(basename, argv[optind]);
    sprintf(bmpfile, "%s.bmp", basename);
  }
  else {
    strcpy(txtfile, argv[optind]);
    strcpy(bmpfile, argv[optind + 1]);
  }

  bmpwrite(txtfile, bmpfile);

  return 0;
}


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: C言語で画像ファイルが作れません

#2

投稿記事 by softya(ソフト屋) » 10年前

単に座標をプロットしたいのであれば、Gnuplotで事が足りると思うのですが。
http://dsl4.eee.u-ryukyu.ac.jp/DOCS/gnu ... uplot.html
リンク先サイトのある様に3次元のデータを2次元のBMPにしたいということでしょうか?

ちなみにこのプログラムは入力ファイルの指定を間違うとusageが表示されます。
必ずテキストファイル名は起動時に指定してください。
./a.out input.dat
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ユーキ

Re: C言語で画像ファイルが作れません

#3

投稿記事 by ユーキ » 10年前

softya(ソフト屋)さん
返信ありがとうございます。

さっそく、./a.outのあとにファイル名をいれたところ

Horizontal : min = 0, max = 2, range = 2
Vertical : min = 0, max = 3, range = 3
Data : min = 0, max = 3
セグメンテーション違反です

と表示されました。あとはどこを直せば画像ファイルができるのか助言をお願いいたします。
ちなみにテキストデータは前回と同じ
0 0 0
0 1 0
0 2 3
0 3 0
1 0 0
1 1 2
1 2 2
1 3 1
2 0 3
2 1 0
2 2 1
2 2 2
を使用し、rootターミナルで実行しました。

アバター
bitter_fox
記事: 607
登録日時: 10年前
住所: 大阪府

Re: C言語で画像ファイルが作れません

#4

投稿記事 by bitter_fox » 10年前

関数bmpwriteを次のように変えて実行して、セグメンテーションエラーが出た際の出力を教えてください。

コード:

/*-----------------*/
/* BITMAP 書き込み */
/*-----------------*/
void bmpwrite(char *txtfile, char *bmpfile)
{
  int i, j, sx, sy;
  long size, offset;
  double maxx, minx, maxy, miny;
  unsigned char **data;
  FILE *fp1, *fp2;
 
  // テキストファイル 
  if ((fp1 = fopen(txtfile, "r")) == NULL) {
    openerror(txtfile);
  }
 
  // 最大値最小値検索 
  maxmin(fp1, &maxx, &minx, &maxy, &miny, &sx, &sy);
printf("%d\n", __LINE__);
  // メモリ確保 
  if ((data = malloc(sx * sizeof(char *))) == NULL) {
    allocerror();
  }
printf("%d\n", __LINE__);
  for (i = 0; i < sx; i++) {
    if ((data[i] = malloc(sy * sizeof(char))) == NULL) {
      allocerror();
    }
printf("%d\n", __LINE__);
    for (j = 0; j < sy; j++) {
      data[i][j] = 0;
    }
  }
 
printf("%d\n", __LINE__);
  // データ取得 
  dataread(fp1, data, maxx, minx, maxy, miny, sx, sy);
 
printf("%d\n", __LINE__);
  fclose(fp1);
 
printf("%d\n", __LINE__);
  if ((fp2 = fopen(bmpfile, "wb")) == NULL) {
    openerror(bmpfile);
  }
 
printf("%d\n", __LINE__);
  // 画像サイズ (1ラインは4Byte(long)境界にあわせる) 
  if (sx % 4 != 0) {
    size = ((sx / 4 + 1) * 4) * sy;
  }
  else {
    size = sx * sy;
  }
printf("%d\n", __LINE__);
  // 画像データまでのオフセット(ヘッダサイズ) 
  offset = 14 + 40 + 4 * (1 << BITCOUNT);
 
printf("%d\n", __LINE__);
  // ファイルヘッダ 
  fileheader(fp2, size, offset);
printf("%d\n", __LINE__);
  // 情報ヘッダ 
  bitmapheader(fp2, (long) sx, (long) sy, size);
printf("%d\n", __LINE__);
  // パレットデータ 
  rgbquad(fp2);
printf("%d\n", __LINE__);
  // 画像データ 
  imagedata(fp2, sx, sy, data, offset);
 
printf("%d\n", __LINE__);
  free(data); // 不完全な解放
printf("%d\n", __LINE__);
  fclose(fp2);
printf("%d\n", __LINE__);
}
変更を加えたところは、明示的に字上げをしています。

また、このプログラムはC言語としてコンパイルしていますか?(C++ではなくという意味です)
もしC言語としてコンパイルしているのであれば、確か、mallocの戻り値を明示的にキャストしてあげる必要があったと思うのですが・・・
それから、dataは完全に解放できてませんのでそこも修正する必要があります。

ユーキ

Re: C言語で画像ファイルが作れません

#5

投稿記事 by ユーキ » 10年前

bitter_foxさん
ありがとうございます。
関数bmpwriteを変えた結果、下記のようになりました。

Horizontal : min = 0, max = 2, range = 2
Vertical : min = 0, max = 3, range = 3
Data : min = 0, max = 3
499
504
515
セグメンテーション違反です

と表示されます。

すいません、C言語初心者なもので質問の意味がわからないのですが、gccでコンパイルしているのでおそらくCだと思います。

アバター
bitter_fox
記事: 607
登録日時: 10年前
住所: 大阪府

Re: C言語で画像ファイルが作れません

#6

投稿記事 by bitter_fox » 10年前

ユーキ さんが書きました:関数bmpwriteを変えた結果、下記のようになりました。

Horizontal : min = 0, max = 2, range = 2
Vertical : min = 0, max = 3, range = 3
Data : min = 0, max = 3
499
504
515
セグメンテーション違反です

と表示されます。
ありがとうございます、では、515行目付近の二重forを次のように変えてみてください。

コード:

printf("%d\n", __LINE__);
  // メモリ確保 
if ((data = (unsigned char**)malloc(sx * sizeof(unsigned char *))) == NULL) { // 変更
    allocerror();
  }
  for (i = 0; i < sx; i++) {
    if ((data[i] = (unsigned char*)malloc(sy * sizeof(unsigned char))) == NULL) { // 変更
      allocerror();
    }
printf("%d\n", __LINE__);
    for (j = 0; j < sy; j++) {
      data[i][j] = '\0'; // 変更
    }
  }

ユーキ さんが書きました:すいません、C言語初心者なもので質問の意味がわからないのですが、gccでコンパイルしているのでおそらくCだと思います。
ですか。拡張子がcならばおそらくC言語としてコンパイルされていると思います。

ユーキ

Re: C言語で画像ファイルが作れません

#7

投稿記事 by ユーキ » 10年前

bitter_fox さん、たびたびありがとうございます。
プログラムの関数bmpwriteを

コード:

printf("%d\n", __LINE__);
  // メモリ確保 
  if ((data = malloc(sx * sizeof(char *))) == NULL) {
    allocerror();
  }
printf("%d\n", __LINE__);
  for (i = 0; i < sx; i++) {
    if ((data[i] = malloc(sy * sizeof(char))) == NULL) {
      allocerror();
    }
printf("%d\n", __LINE__);
    for (j = 0; j < sy; j++) {
      data[i][j] = 0;
    }
  }
からbitter_fox さんのアドバイスどおり

コード:

printf("%d\n", __LINE__);
  // メモリ確保 
if ((data = (unsigned char**)malloc(sx * sizeof(unsigned char *))) == NULL) { // 変更
    allocerror();
  }
  for (i = 0; i < sx; i++) {
    if ((data[i] = (unsigned char*)malloc(sy * sizeof(unsigned char))) == NULL) { // 変更
      allocerror();
    }
printf("%d\n", __LINE__);
    for (j = 0; j < sy; j++) {
      data[i][j] = '\0'; // 変更
    }
  }
に書き換えた結果、

Horizontal : min = 0, max = 2, range = 2
Vertical : min = 0, max = 3, range = 3
Data : min = 0, max = 3
499
514
セグメンテーション違反です

と表示されました。

アバター
bitter_fox
記事: 607
登録日時: 10年前
住所: 大阪府

Re: C言語で画像ファイルが作れません

#8

投稿記事 by bitter_fox » 10年前

ユーキ さんが書きました: bitter_fox さん、たびたびありがとうございます。
こちらこそ、たびたび申し訳ないです。。。

何回目のアクセスでそれが出るのかを知るために、次のようにしてください。(二重目のforです)

コード:

    for (j = 0; j < sy; j++) {
printf("    %d %d", j, sy);
      data[i][j] = '\0'; // 変更
    }
[hr][修正]
タグを間違えてたので修正しました。

ユーキ

Re: C言語で画像ファイルが作れません

#9

投稿記事 by ユーキ » 10年前

bitter_fox さん

コード:

for (j = 0; j < sy; j++) {
      data[i][j] = '\0'; // 変更
    }
の部分を

コード:

for (j = 0; j < sy; j++) {
printf("    %d %d", j, sy);
      data[i][j] = '\0'; // 変更
    }
に変更した結果、

Horizontal : min = 0, max = 2, range = 2
Vertical : min = 0, max = 3, range = 3
Data : min = 0, max = 3
499
515
セグメンテーション違反です

と表示されました。

アバター
bitter_fox
記事: 607
登録日時: 10年前
住所: 大阪府

Re: C言語で画像ファイルが作れません

#10

投稿記事 by bitter_fox » 10年前

ユーキ さんが書きました: Horizontal : min = 0, max = 2, range = 2
Vertical : min = 0, max = 3, range = 3
Data : min = 0, max = 3
499
515
セグメンテーション違反です

と表示されました。
ですか、、、では以下のようにしてみてください。

コード:

  if ((data = (unsigned char**)malloc(sx * sizeof(unsigned char *))) == NULL) {
    allocerror();
  }
printf("%d\n", __LINE__);
  for (i = 0; i < sx; i++) {
    if ((data[i] = (unsigned char*)calloc(sy, sizeof(unsigned char))) == NULL) {
      allocerror();
    }
  }

アバター
Justy
副管理人
記事: 122
登録日時: 10年前
住所: 神奈川県

Re: C言語で画像ファイルが作れません

#11

投稿記事 by Justy » 10年前

ユーキ さんが書きました:という内容のテキストデータ(プログラム名は1.txt)を同じディレクトリに入れgccでコンパイルして実行しても、コンパイルはされるのですが最初のvoid usage(void)関数内の内容を表示するだけで画像データができません。
 テキストデータの最後に改行は入っていますか?
 入っていなければ改行を入れてみて下さい(改行のみの行にする)。

アバター
bitter_fox
記事: 607
登録日時: 10年前
住所: 大阪府

Re: C言語で画像ファイルが作れません

#12

投稿記事 by bitter_fox » 10年前

実行環境がなかった所にいてたので、実際に再現できなかったのですが、今やったら全然違うところでのエラーでした。orz

maxmin関数で発生していました。。。

以下の部分です。

コード:


  // 1画素あたりの単位 
  xunit = xrange / maxcx; // ここ
  yunit = yrange / cy;
 
  // 画素数 
  *sx = (int) (xrange / xunit); // ここ
  *sy = (int) (yrange / yunit);
今回は、上の二点で0割りが発生していたようです。まったく違ったことを指摘してしまい大変申し訳ございませんでした。。。

ユーキ

Re: C言語で画像ファイルが作れません

#13

投稿記事 by ユーキ » 10年前

Justyさん
今、確認しましたが改行はしています。

bitter_foxさん
いえいえこちらこそ、夜遅くまで付き合わせて申し訳なく思いま す。
失礼な話なのですが、どこを訂正すればいいのかを教えていただければ助かります。

アバター
Justy
副管理人
記事: 122
登録日時: 10年前
住所: 神奈川県

Re: C言語で画像ファイルが作れません

#14

投稿記事 by Justy » 10年前

ユーキ さんが書きました:Justyさん
今、確認しましたが改行はしています。
 じゃぁ、もう1行改行のみの行を最後に追加してみて下さい。
(これでダメなら私の考えは間違っているのでしょう……)

アバター
bitter_fox
記事: 607
登録日時: 10年前
住所: 大阪府

Re: C言語で画像ファイルが作れません

#15

投稿記事 by bitter_fox » 10年前

Justy さんが書きました:
ユーキ さんが書きました:Justyさん
今、確認しましたが改行はしています。
 じゃぁ、もう1行改行のみの行を最後に追加してみて下さい。
Justyさんのおっしゃってる通りです、
以下のファイルでやると問題なくいけました。
添付ファイル
01.txt
(86 バイト) ダウンロード数: 55 回

アバター
Justy
副管理人
記事: 122
登録日時: 10年前
住所: 神奈川県

Re: C言語で画像ファイルが作れません

#16

投稿記事 by Justy » 10年前

 まず、ヒントは usageにちょろっと書いてあるのですが、改行のみの行(正確にはちょっと違いますが)をもって
横一行分のデータと扱うようになっていますので、必ず改行が必要になります。

 それがないと maxmin関数内の maxcx変数が 0のままで、結果 bitter_foxさんが指摘していたところで
0で割ることになります。

 ユーキさんの環境では0で割ってもそのまま実行が続いていたと思いますが、その結果 sxには 0が入り、
for (i = 0; i < sx; i++)の部分のループが1回も実行されなかったのではないかと思われます。

ユーキ

Re: C言語で画像ファイルが作れません

#17

投稿記事 by ユーキ » 10年前

私の初歩的な質問に親切に答えていただき重ね重ねありがとうございます。
早速、改行を二回行ったところ画像ファイルにすることができ、いい歳なのに思わず感動いたしました。
しかし、実験データをいれてみると画像が出来ませんでした。そのデータはこちらで
0 0 0.000459040400296
0 1 0.000591311534573
0 2 0.000021836899441
0 3 0.000397523777086
0 4 0.000665318351183
0 5 0.000649137067744


というファイル(ファイル名はkyoudo.txt)でx=0の座標の強度を放射線強度として表示するものです。
このファイルを用いて実行すると
Horizontal : min = 0, max = 0, range = 0
Vertical : min = 0, max = 5, range = 5
Data : min = 2.18369e-05, max = 0.000665318
499
515
セグメンテーション違反です

と表示されます。
小数を使ったのが悪かったのでしょうか?
それともxが0だけにしたのが悪かったのでしょうか。ご教授おねがいいたします。

アバター
bitter_fox
記事: 607
登録日時: 10年前
住所: 大阪府

Re: C言語で画像ファイルが作れません

#18

投稿記事 by bitter_fox » 10年前

ユーキ さんが書きました: 0 0 0.000459040400296
0 1 0.000591311534573
0 2 0.000021836899441
0 3 0.000397523777086
0 4 0.000665318351183
0 5 0.000649137067744

それともxが0だけにしたのが悪かったのでしょうか。ご教授おねがいいたします。
そのようですね、最初のデータでxをすべてゼロにした場合でも、エラーが発生しました。

[hr]
とりえず、0割が発生してしまう状況は良くないので、maxmin関数を次のようにしておきましょう。(セグメンテーション違反を表示させなくするだけなのであって根本的なこの問題の解決ではありません。)

コード:

	// 1画素あたりの単位 
	if (maxcx == 0 || cx == 0)
	{
		printf("0割りが発生しました。%d\n", __LINE__);
		exit(1);
	}
	xunit = xrange / maxcx;
	yunit = yrange / cy;
 
	// 画素数 
	if (xunit == 0 || yunit == 0)
	{
		printf("0割りが発生しました。%d\n", __LINE__);
		exit(1);
	}
	*sx = (int) (xrange / xunit);
	*sy = (int) (yrange / yunit);

ユーキ

Re: C言語で画像ファイルが作れません

#19

投稿記事 by ユーキ » 10年前

bitter_foxさん
ありがとうございます。
変更したところ

Horizontal : min = 0, max = 2, range = 2
Vertical : min = 0, max = 3, range = 3
Data : min = 0, max = 3
0割りが発生しました。 255

と表示されました。実行したテキストファイルは上の方にに添付していただいた01.txtです。
どのあたりを訂正すればいいのか、またデータ点数を1000個以上の点を取りたいときはどのように変更すればいいのか御指摘お願いします。
私の変更場所が間違えた可能性が高いので変更したプログラムを再び張らせていただきます。

コード:

/***************************************************************/
/* データ → 画像変換ソフト                                    */
/* 出力画像フォーマット: bitmap 形式                           */
/*                                                             */
/* データフォーマット                                          */
/* gnuplot で                                                  */
/* set data style lines                                        */
/* splot で表示できる形式                                      */
/*                                                             */
/* ("%f %f %f\n", x, y, z)                                     */
/* ("\n")                                                      */
/*                                                             */
/* <!-- e --><a href=\"mailto:kondo@kk.iij4u.or.jp\">kondo@kk.iij4u.or.jp</a><!-- e -->                                        */
/* 2000.08.03                                                  */
/***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
 
#define BITCOUNT (8)
#define BUF_SIZE (1000)
#ifndef _MAX_PATH
#define _MAX_PATH (255)
#endif
#ifndef UCHAR_MAX
#define UCHAR_MAX (255)
#endif
#ifndef UCHAR_MIN
#define UCHAR_MIN (0)
#endif
 
static char cmdname[] = "txt2bmp";
 
int optind = 1; // オプションでない最初の引数までの文字列数
int optopt;     // オプション文字 
char *optarg;   // オプション引数
 
double max = 0.0, min = 0.0;
int maxopt = 0, minopt = 0;
 
void usage(void)
{
  fprintf(stderr,
          "\n"
          "ASCIIテキストデータ ---> BMP フォーマット変換プログラム\n"
          "usage : %s [option] <text_file> [bitmap_file]\n"
          "  bitmap_file の指定が無い場合"
          " text_file.bmp のファイルが作成されます\n"
          "\n"
          "option :\n"
          "  -M : 最大値を指定します\n"
          "  -m : 最小値を指定します\n"
          "\n"
          "データ形式 : X座標 Y座標 Z値\n"
          "\tx y z\n"
          "\tx y z\n"
          "\t: : :\n"
          "\t      (改行のみでラインの区切り)\n"
          "\tx y z\n"
          "\t: : :\n"
          "\n", cmdname);
  exit(1);
}
 
void openerror(char *filename)
{
  fprintf(stderr, "Can't open file: %s\n", filename);
  exit(1);
}
 
void allocerror(void)
{
  fprintf(stderr, "memory allocation error.\n");
  exit(1);
}
 
/*----------------*/
/* ファイル名取得 */
/*----------------*/
int getbasename(char *dest, char *src)
{
  int i, start, end, ret;
 
  i = -1;
  start = 0;
  end = 0;
 
  // ファイル名のはじめと終わりを検出 
  while (src[++i]) {
    if (src[i] == '\\' || src[i] == ':') {
      start = i + 1;
      end = 0;
    }
    if (src[i] == '.') {
      end = i;
    }
  }
  if (end == 0) {
    end = i;
  }
 
  // ファイル名が有る場合 
  if (start < end) {
    for (i = 0; i < end; i++) {
      dest[i] = src[i];
    }
    dest[i] = '\0';
    ret = 1;
  }
  else {
    dest[0] = '\0';
    ret = 0;
  }
 
  return ret;
}
 
/*----------------------*/
/* コメント行読み飛ばし */
/*----------------------*/
void commentskip(FILE * fp)
{
  int c;
 
  do {
    while ((c = fgetc(fp)) == '\n') {
      ;
    }
    // # ; / があれば読み飛ばし 
    if ((c == '#') || (c == ';') || (c == '/')) {
      while ((c = fgetc(fp)) != '\n') {
        ;
      }
    }
    else {
      break;
    }
  } while (1);
 
  ungetc(c, fp);
}
 
/*------------------*/
/* 最大値最小値検索 */
/*------------------*/
void maxmin(FILE * fp,
            double *maxx, double *minx,
            double *maxy, double *miny,
            int *sx, int *sy)
{
  int n, cx, cy, maxcx, flag;
  double x, y, z, xrange, yrange, xunit, yunit;
  char s[2], buf[BUF_SIZE];
 
  cx = 0;                       // x 方向のデータ数 
  cy = 0;                       // y 方向のデータ数 
  maxcx = 0;                    // x 方向のデータ数最大値 
  flag = 0;
 
  rewind(fp);
  commentskip(fp);
 
  // 値の初期化 
  if (fgets(buf, BUF_SIZE, fp) != NULL) {
    n = sscanf(buf, "%lf %lf %lf %1s", &x, &y, &z, s);
    if (n >= 3) {
      *maxx = x;
      *minx = x;
      *maxy = y;
      *miny = y;
      if (maxopt == 0) {
        max = z;
      }
      if (minopt == 0) {
        min = z;
      }
    }
  }
 
  rewind(fp);
 
  while (fgets(buf, BUF_SIZE, fp) != NULL) {
    n = sscanf(buf, "%lf %lf %lf %1s", &x, &y, &z, s);
 
    // EOF で終了 
    if (feof(fp)) {
      break;
    }
    // データ数3個以上の場合 
    else if (n >= 3) {
      cx++;
      if (flag == 0) {
        cy++;
      }
      flag = 1;
 
      // 最大値検索 
      if (z < min) {
        if (minopt == 0) {
          min = z;
    }
      }
      if (z > max) {
        if (maxopt == 0) {
          max = z;
    }
      }
 
      if (x < *minx) {
        *minx = x;
      }
      else if (x > *maxx) {
        *maxx = x;
      }
 
      if (y < *miny) {
        *miny = y;
      }
      else if (y > *maxy) {
        *maxy = y;
      }
    }
    // 改行のみの場合 
    else {
      if (flag == 1) {
        if (cx > maxcx) {
          maxcx = cx;
        }
      }
 
      flag = 0;
      cx = 0;
    }
  }
 
  // データ範囲 
  xrange = *maxx - *minx;
  yrange = *maxy - *miny;
 
  printf("Horizontal : min = %g, max = %g, range = %g\n",
         *minx, *maxx, xrange);
  printf("Vertical   : min = %g, max = %g, range = %g\n",
         *miny, *maxy, yrange);
  printf("Data       : min = %g, max = %g\n", min, max);
 
  if (max <= min) {
    fprintf(stderr, "最大値よりも最小値が大きい\n");
    exit(1);
  }
 
  // 1画素あたりの単位 
    if (maxcx == 0 || cx == 0)
    {
        printf("0割りが発生しました。%d\n", __LINE__);
        exit(1);
    }
    xunit = xrange / maxcx;
    yunit = yrange / cy;
 
    // 画素数 
    if (xunit == 0 || yunit == 0)
    {
        printf("0割りが発生しました。%d\n", __LINE__);
        exit(1);
    }
    *sx = (int) (xrange / xunit);
    *sy = (int) (yrange / yunit);
 }
/*----------------*/
/* データ読み込み */
/*----------------*/
void dataread(FILE * fp,
              unsigned char **data,
              double maxx, double minx,
              double maxy, double miny,
              int sx, int sy)
{
  int n;
  double x, y, z,
         xrange, yrange, zrange,
         value;
  char s[2], buf[BUF_SIZE];
 
  xrange = maxx - minx;
  yrange = maxy - miny;
  zrange = max - min;
 
  rewind(fp);
  commentskip(fp);
 
  while (fgets(buf, BUF_SIZE, fp) != NULL) {
    n = sscanf(buf, "%lf %lf %lf %1s", &x, &y, &z, s);
 
    if (feof(fp)) {
      break;
    }
    else if (n >= 3) {
      int ix, iy;
 
      // 座標変換 
      ix = (int) (0.5 + (x - minx) * (double) (sx - 1) / xrange);
      iy = (int) (0.5 + (y - miny) * (double) (sy - 1) / yrange);
 
      value = (unsigned char) (255.9 * (z - min) / zrange);
      if (value > UCHAR_MAX) {
        value = UCHAR_MAX;
      }
      else if (value < UCHAR_MIN) {
        value = UCHAR_MIN;
      }
      data[ix][iy] = value;
    }
  }
}
 
/*---------------------------------*/
/* ファイルヘッダ BITMAPFILEHEADER */
/*---------------------------------*/
int fileheader(FILE * fp,
               long size, long offset)
{
  long count, filesize;
  short reserved = 0;
  char s[2];
 
  rewind(fp);
 
  // 識別文字 BM 
  s[0] = 'B';
  s[1] = 'M';
  fwrite(s, sizeof(char), 2, fp);
 
  printf("[BITMAPFILEHEADER]\n");
  // ファイルサイズ bfSize 
  filesize = size + offset;
  printf("  File Size          = %ld[Bytes]\n", filesize);
  fwrite(&filesize, sizeof(long), 1, fp);
  // 予約エリア bfReserved1 
  fwrite(&reserved, sizeof(short), 1, fp);
  // 予約エリア bfReserved2 
  fwrite(&reserved, sizeof(short), 1, fp);
  // データ部までのオフセット bfOffBits 
  printf("  Bitmap Data Offset = %ld [Bytes]\n", offset);
  fwrite(&offset, sizeof(long), 1, fp);
 
  // ファイルヘッダサイズ 14 Byte 
  if ((count = ftell(fp)) != 14) {
    fprintf(stderr, "BITMAPFILEHEADER write error : %ld\n", count);
    exit(1);
  }
 
  return count;
}
 
/*-----------------------------*/
/* 情報ヘッダ BITMAPINFOHEADER */
/*-----------------------------*/
int bitmapheader(FILE * fp,
                 long width, long height, long size)
{
  long count, var_long;
  short var_short;
 
  fseek(fp, 14, SEEK_SET);
 
  printf("[BITMAPINFOHEADER]\n");
  // 情報ヘッダのサイズ biSize (Windows BMP は 40) 
  var_long = 40;
  fwrite(&var_long, sizeof(long), 1, fp);
  // 画像の幅 biWidth 
  var_long = width;
  printf("  Width              = %ld [pixels]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // 画像の高さ biHeight 
  // (正数ならば左下から右上, マイナスならば左上から右下) 
  var_long = height;
  printf("  Height             = %ld [pixels]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // プレーン数 biPlanes (必ず 1) 
  var_short = 1;
  printf("  Planes             = %hd\n", var_short);
  fwrite(&var_short, sizeof(short), 1, fp);
  // 1ピクセルのデータ数 biBitCount (1, 4, 8, 24, 32) 
  var_short = BITCOUNT;
  printf("  Bits Per Pixel     = %hd [bits]\n", var_short);
  fwrite(&var_short, sizeof(short), 1, fp);
 
  // 圧縮 biCompression (無圧縮ならば 0) 
  var_long = 0;
  printf("  Compression        = %ld\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // 画像のサイズ biSizeImage 
  var_long = size;
  printf("  Bitmap Data Size   = %ld [Bytes]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // 横方向解像度 pixel/m biXPelPerMeter 
  // (96dpi, 1inch = 0.0254m のとき 96/0.0254 = 3780) 
  var_long = 3780;
  printf("  HResolution        = %ld [pixel/m]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // 縦方向解像度 pixel/m biYPelPerMeter 
  // (96dpi, 1inch = 0.0254m のとき 96/0.0254 = 3780) 
  var_long = 3780;
  printf("  VResolution        = %ld [pixel/m]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // パレット数 biClrUsed 
  var_long = 1 << BITCOUNT;
  printf("  Colors             = %ld [colors]\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
  // パレット中の重要な色  biClrImportant 
  var_long = 0;
  printf("  Important Colors   = %ld\n", var_long);
  fwrite(&var_long, sizeof(long), 1, fp);
 
  // ファイルヘッダ(14 Byte) + 情報ヘッダサイズ(40 Byte) 
  if ((count = ftell(fp)) != 54) {
    fprintf(stderr, "BITMAPINFOHEADER write error : %ld\n", count);
    exit(1);
  }
 
  return count;
}
 
/*------------------------*/
/* パレットデータ RGBQUAD */
/*------------------------*/
long rgbquad(FILE * fp)
{
  long i, color, count;
 
  fseek(fp, 54, SEEK_SET);
 
  color = 1 << BITCOUNT;
 
  printf("  Pallete            = %ld [colors] (%ld [Bytes])\n",
         color, 4 * color);
  for (i = 0; i < color; i++) {
    unsigned char red, green, blue, reserved = 0;
 
    // グレイスケール red = green = blue 
    blue = (unsigned char) i;
    green = (unsigned char) i;
    red = (unsigned char) i;
 
    fputc(blue, fp);
    fputc(green, fp);
    fputc(red, fp);
    fputc(reserved, fp);
  }
 
  if ((count = ftell(fp)) != 54 + 4 * color) {
    fprintf(stderr, "RGBQUAD write error : %ld\n", count);
    exit(1);
  }
 
  return count;
}
 
/*------------*/
/* 画像データ */
/*------------*/
long imagedata(FILE * fp,
               int x, int y,
               unsigned char **data,
               long offset)
{
  long i, j;
  unsigned char index;
 
  fseek(fp, offset, SEEK_SET);
 
  for (j = 0; j < y; j++) {
    for (i = 0; i < x; i++) {
      index = data[i][j];
      fwrite(&index, sizeof(char), 1, fp);
    }
    // 1ラインは 4Byte(long) 境界にあわせる 
    if ((x % 4) != 0) {
      for (i = 0; i < ((x / 4 + 1) * 4) - x; i++) {
        unsigned char zero = 0;
 
        fwrite(&zero, sizeof(char), 1, fp);
      }
    }
  }
 
  return ftell(fp);
}
 
/*-----------------*/
/* BITMAP 書き込み */
/*-----------------*/
void bmpwrite(char *txtfile, char *bmpfile)
{
  int i, j, sx, sy;
  long size, offset;
  double maxx, minx, maxy, miny;
  unsigned char **data;
  FILE *fp1, *fp2;
 
  // テキストファイル 
  if ((fp1 = fopen(txtfile, "r")) == NULL) {
    openerror(txtfile);
  }
 
  // 最大値最小値検索 
  maxmin(fp1, &maxx, &minx, &maxy, &miny, &sx, &sy);
printf("%d\n", __LINE__);
  // メモリ確保 
  if ((data = malloc(sx * sizeof(char *))) == NULL) {
    allocerror();
  }
printf("%d\n", __LINE__);
  for (i = 0; i < sx; i++) {
    if ((data[i] = malloc(sy * sizeof(char))) == NULL) {
      allocerror();
    }
printf("%d\n", __LINE__);
    for (j = 0; j < sy; j++) {
printf("    %d %d", j, sy);
      data[i][j] = '\0'; // 変更
    }
  }
 
printf("%d\n", __LINE__);
  // データ取得 
  dataread(fp1, data, maxx, minx, maxy, miny, sx, sy);
 
printf("%d\n", __LINE__);
  fclose(fp1);
 
printf("%d\n", __LINE__);
  if ((fp2 = fopen(bmpfile, "wb")) == NULL) {
    openerror(bmpfile);
  }
 
printf("%d\n", __LINE__);
  // 画像サイズ (1ラインは4Byte(long)境界にあわせる) 
  if (sx % 4 != 0) {
    size = ((sx / 4 + 1) * 4) * sy;
  }
  else {
    size = sx * sy;
  }
printf("%d\n", __LINE__);
  // 画像データまでのオフセット(ヘッダサイズ) 
  offset = 14 + 40 + 4 * (1 << BITCOUNT);
 
printf("%d\n", __LINE__);
  // ファイルヘッダ 
  fileheader(fp2, size, offset);
printf("%d\n", __LINE__);
  // 情報ヘッダ 
  bitmapheader(fp2, (long) sx, (long) sy, size);
printf("%d\n", __LINE__);
  // パレットデータ 
  rgbquad(fp2);
printf("%d\n", __LINE__);
  // 画像データ 
  imagedata(fp2, sx, sy, data, offset);
 
printf("%d\n", __LINE__);
  free(data); // 不完全な解放
printf("%d\n", __LINE__);
  fclose(fp2);
printf("%d\n", __LINE__);
}
 
/*----------------------*/
/* オプション引数の解析 */
/*----------------------*/
int getopt(int nargc, char **nargv, char *ostr)
{
  static char *place = "",
              *lastostr = (char *) 0;
  char *oli;
 
  if (ostr != lastostr) {
    lastostr = ostr;
    place = "";
  }
  if (!*place) {
    if ((optind >= nargc) 
        || (*(place = nargv[optind]) != '-')
        || !*++place) {
      place = "";
      return (EOF);
    }
    if (*place == '-') {
      ++optind;
      return (EOF);
    }
  }
  // オプション文字のチェック 
  if ((optopt = (int) *place++) == (int) ':'
      || !(oli = strchr(ostr, optopt))) {
    if (!*place) {
      ++optind;
    }
 
    fprintf(stderr, "%s : オプションが違います -- %c\n", *nargv, optopt);
    return (int) '?';
  }
  // オプション引数のチェック 
  if (*++oli != ':') {
    optarg = NULL;
    if (!*place) {
      ++optind;
    }
  }
  // オプション引数が必要な場合 
  else {
    if (*place) {
      optarg = place;
    }
    // 引数が無い場合 
    else if (nargc <= ++optind) {
      place = "";
      fprintf(stderr, "%s : オプションには引数が必要です -- %c\n",
              *nargv, optopt);
      return (int) '?';
    }
    // 引数がある場合 
    else {
      optarg = nargv[optind];
    }
    place = "";
    ++optind;
  }
  return (optopt);
}
 
/**************/
/* メイン関数 */
/**************/
int main(int argc, char *argv[])
{
  int c;
  char txtfile[_MAX_PATH], bmpfile[_MAX_PATH], basename[_MAX_PATH];
 
  while ((c = getopt(argc, argv, "M:m:")) != EOF) {
    switch (c) {
    case 'M':                  // 最大値 
      max = strtod(optarg, (char **) NULL);
      maxopt = 1;
      break;
    case 'm':                  // 最小値 
      min = strtod(optarg, (char **) NULL);
      minopt = 1;
      break;
    case '?':
      usage();
      break;
    default:
      usage();
      break;
    }
  }
 
  if (argc - optind < 1) {
    usage();
  }
  else if (argc - optind == 1) {
    strcpy(txtfile, argv[optind]);
    getbasename(basename, argv[optind]);
    sprintf(bmpfile, "%s.bmp", basename);
  }
  else {
    strcpy(txtfile, argv[optind]);
    strcpy(bmpfile, argv[optind + 1]);
  }
 
  bmpwrite(txtfile, bmpfile);
 
  return 0;
}

アバター
bitter_fox
記事: 607
登録日時: 10年前
住所: 大阪府

Re: C言語で画像ファイルが作れません

#20

投稿記事 by bitter_fox » 10年前

ユーキさんが挿入した場所は間違ってません。僕のコードのミスでした。。。

cyとすべき所をcxとしてしまっていましたので、以下のようにしてください。

コード:

    // 1画素あたりの単位 
    if (maxcx == 0 || cy == 0)
    {
        printf("0割りが発生しました。%d\n", __LINE__);
        exit(1);
    }
    xunit = xrange / maxcx;
    yunit = yrange / cy;
 
    // 画素数 
    if (xunit == 0 || yunit == 0)
    {
        printf("0割りが発生しました。%d\n", __LINE__);
        exit(1);
    }
    *sx = (int) (xrange / xunit);
    *sy = (int) (yrange / yunit);
[hr][追記]
1000個以上を扱いたければ
#define BUF_SIZE (1000)
の1000を任意の数に変更すれば可能かと思います。

ユーキ

Re: C言語で画像ファイルが作れません

#21

投稿記事 by ユーキ » 10年前

bitter_foxさん
丁寧な説明ありがとうございます。
無事、画像を出すことができました。ほんとうにありがとうございます。

次にもう1つ試しとして下記のようなテキストファイル(ファイル名は02.txt)をつくりました。
0 0 0
0 1 0
0 2 0
1 0 0
1 1 1
1 2 0
2 0 0
2 1 0
2 2 0


私の予想では真ん中(x,y)=(1,1)の部分だけ明るさが違う正方形がでるのを予想していたのですが、実際にできた図は黒い長方形ができただけでした。
私はこのプログラムをxy座標にzの大きさを明るさで表示するプログラムだと思っていたのですが違っていたのでしょうか?
実行結果は以下のようになります。

Horizontal : min = 0, max = 2, range = 2
Vertical : min = 0, max = 2, range = 2
Data : min = 0, max = 1
509
514
519
0 1519
0 1519
0 1519
0 1519
0 1519
0 1519
0 1519
0 1526
530
533
538
546
550
[BITMAPFILEHEADER]
File Size = 1086[Bytes]
Bitmap Data Offset = 1078 [Bytes]
553
[BITMAPINFOHEADER]
Width = 8 [pixels]
Height = 1 [pixels]
Planes = 1
Bits Per Pixel = 8 [bits]
Compression = 0
Bitmap Data Size = 8 [Bytes]
HResolution = 3780 [pixel/m]
VResolution = 3780 [pixel/m]
Colors = 256 [colors]
Important Colors = 0
556
Pallete = 256 [colors] (1024 [Bytes])
559
563
565
567

ユーキ

Re: C言語で画像ファイルが作れません

#22

投稿記事 by ユーキ » 10年前

いろいろ無茶な質問をしてすみません。
bitter_foxさんをはじめ、アドバイスをくださった皆様、ほんとうにありがとうございます。
これ以上の質問はトピックタイトルにあっていないので、別のトピックを建てたいと思います。
ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る