Fortran g95を使ってBMPを処理する方法

このQ&Aのポイント
  • 以前XP環境でVisual Fortran(VF)を使ってBMPファイルを読み込むプログラムを使用していましたが、PCがWin7になったため、FreeのFortran g95を使用して同様の処理を行いたいです。
  • VFでは、'test.bmp'という8bitのファイルを読み込むためにcharacter*1078 tempとinteger*1 dataを使用していますが、g95では'binary'の形式が使用できません。
  • g95で正しい輝度情報を読み込むためには、open文のformを'formatted'に変更し、read文の書式を'*'に変更する必要があります。また、読み込んだdata値をichar関数を使って数値に変換する必要があります。
回答を見る
  • ベストアンサー

fortran g95を使ってBMPを処理したい

以前XP環境でVisual Fortran(VF)を使ってBMPファイルを読み込むプログラム使っていました. PCがWin7になった為,FreeのFortran g95を使用して同様の処理を行いたいのですが,上手くできません.例えば”test.bmp”と言う8bitのファイルを読み込みたいとしたとき, VFでは character*1078 temp integer*1 data open(10,file='test.bmp',form='binary') read(10)temp read(10)data このときwrite(*,*)dataは133とします. g95では"binary"が使用できず, character*1078 temp chracter*1 data open(10,file='test.bmp',form='formatted') read(10,*)temp read(10,*)data data2=ichar(data) write(*,*)data2は32となってしまいます. 画像の輝度は133で,VFで読み込んだ値となります. 上のプログラムで何を直せば g95でも正しい輝度情報を読めるのでしょうか? どうぞ宜しくお願いします.

  • noboo
  • お礼率38% (32/83)

質問者が選んだベストアンサー

  • ベストアンサー
  • f272
  • ベストアンサー率46% (7997/17096)
回答No.2

じゃあ,こんな感じ。 character*4 t4 character*1078 temp character*1 data open(10,file='test.bmp',form='unformatted',access='direct',recl=1) do i=1,1078 read(10,rec=i)temp(i:i) enddo read(10,rec=1079)data data2=ichar(data) write(*,*)data2 end でもg95で > access='stream'を代入するとエラーが出てしまいます. というのはどうしてだろう?私の環境では $ g95 -v Using built-in specs. Target: Configured with: ../configure --prefix=/mingw --enable-languages=c --with-ld=/mi ngw/bin/ld --with-as=/mingw/bin/as --host=i386-pc-mingw32 --enable-threads --dis able-nls --disable-win32-registry --enable-sjlj-exceptions --enable-libgcj --wit hout-x Thread model: win32 gcc version 4.1.2 (g95 0.93!) Jun 16 2010 $ cat aa.f95 character*4 t4 character*1078 temp character*1 data !integer*1 data open(10,file='test.bmp',form='unformatted',access='stream') read(10)temp read(10)data !write(10)temp !write(10)data data2=ichar(data) write(*,*)data2 end $ g95 aa.f95 $ ./a 141. $ こんな感じだったよ。 で,確かにtest.bmpの1079バイト目をバイナリエディタで確認してもZ'8D'です。

noboo
質問者

お礼

たびたびコメントを頂きありがとうございます. 私の環境では, read(10,rec=i)temp(i:i) ではコンパイルを通りません. ただ, do i=1,1078 read(10,rec=i) end do read(10,rec=1079)data data2=ichar(data2) write(*,*)data2 とすると「133」が表示され,正しい値を返しているようです. ********* 教えて頂きましたプログラ中 character*4 t4 は何でしょうか? また read(10,rec=i)temp(i:i) はどう言う意味になるのでしょうか? 普段使用しない書き方なので良く意味がとらえられません ********* おそらく教えていただきましたコメントで, 私の行いたかったことができそうです. 上記に関するコメントは,お時間のある時で構いませんので ご教授頂ければと思います. 本当に有難うございました.

その他の回答 (2)

  • f272
  • ベストアンサー率46% (7997/17096)
回答No.3

> 教えて頂きましたプログラ中 > character*4 t4 > は何でしょうか? これはちょっと違うことを書いていたときに使った変数で,今となっては単なるゴミです。 消してもかまいません。 > また > read(10,rec=i)temp(i:i) > はどう言う意味になるのでしょうか? > 普段使用しない書き方なので良く意味がとらえられません 文字部分列と言われるもので,文字列の連続する部分集合を表します。 string ([ starting-position ] : [ ending-position ]) こんな感じで使用して,文字列中での開始位置と終了位置を指定します。 だからtemp(i:i)は文字列tempのi文字目を表し,10番のファイルのi番目のレコードを文字列tempのi文字目に読み込むことになります。ファイルの1バイト目から1078バイト目が必要でなければ,doループ全体が必要ではなく character*1 data open(10,file='test.bmp',form='unformatted',access='direct',recl=1) read(10,rec=1079)data data2=ichar(data) write(*,*)data2 end これでも同じ結果を返すはず。

  • f272
  • ベストアンサー率46% (7997/17096)
回答No.1

わざわざg95で確かめることはしてないけど character*1078 temp character*1 data open(10,file='test.bmp',form='unformatted',access='stream') read(10)temp read(10)data data2=ichar(data) write(*,*)data2 end こんな感じ?

noboo
質問者

お礼

コメント有難う御座います.早速試したところ, open(10,file='test.bmp',form='unformatted',access='stream') のaccess='stream'を代入するとエラーが出てしまいます. access='stream'を削除した場合, read(10)temp read(10)data でread(10)tempによりデータを読みに行った箇所でエラーが出てしまいます. 私もはじめ教えていただいたものと同等のプログラムで動くかと思ったのですが,unformatted,read(10)の記述でエラーが出てしまい,formatted, read(10,*)だと何とか動くのですが,帰ってくる値が以前のものと違い,何処に問題があるのかわからずにおります. 何かご存知でしたら教えていただければ大変助かります.

関連するQ&A

  • Fortranの'read'のVBへの書き換え方

    Fortranのread/writeをVBへの書き換え方を教えて下さい。 他の方の作られたfortran.90のprogramをvisual basicに書きなおす作業をしています。その中の下記のfileのaccessが上手出来ません。このなかに有るbinary,とかbig_endianが原因のようです。 (これの無いfile accessの箇所は問題なく出来ました。) program内でdataをfileに書込み保存して蓄積しているようで、後日このdataをreadして使うようになっていますので新しくfileを作り直すわけにもいきません。 いろいろとcodeを入れてみたが、結果は文字化けばかりで10日も費してしまいました。 binary,bigendianなどの理屈が判っていないのでどうしょうもないと感じました。 どうか下記のfortranをVisual Basicへの書き変え方をご教授お願いします。 REAL ShipDim(17) '読み込みの時   filename = 'c:\pbcal\pbcal\pushdata\'//'push04' open (3,file= filename, status='old', & & form='BINARY', convert='BIG_ENDIAN',err=930) DO 10 J= 1,17 read(3) shipDim(j) 10 CONTINUE      (中略)  '見やすいように簡略化しています。 CLOSE (3,STATUS='KEEP')   '書込みの時はopenは下記で、後readをwriteに変えただけです。 open (3,file= filename, status=pstatus,form='BINARY', convert='BIG_ENDIAN',err=940) VBでTRYしたことの一例     Dim dat() As Byte = New Byte(-1) {}   Dim sr As System.IO.Stream = Nothing   Dim br As System.IO.BinaryReader = Nothing Dim strf As String = filepath & "push04" 'filepathは適当にしている    sr = System.IO.File.Open(strf, _        System.IO.FileMode.Open, System.IO.FileAccess.Read) br = New System.IO.BinaryReader(sr) ReDim dat(sr.Length - 1) dat = br.ReadBytes(sr.Length)      dat に=572個の2-3桁の数字が入っています。encodingなどでためしてみたが文字化け     ばかりです。    (System.Text.Encoding.GetEncoding("****").GetString(dat) など)         どうかよろしくお願いします。

  • fortranの配列のreadについて

    fortran初心者です。 研究のデータ整理を行う際に 240*21のテキストデータを読み込む必要があるのですが、 自分なりに勉強してみたのですが、fortranの計算がずっとカーソルが点滅しており いつまで経っても終わらない状態のため、 ファイルopenまではいくのですが、その中身を読み込めてないようです。 プログラムですが自分としては次のように考えました。 REAL temp DIMENSION temp(21,240) DATA temp/5040*0.00/    open(11,status='unknown',file=filename)    read *,((temp(q,p),p=1,240),q=1,21)    close(11) と配列を組んで考えてみたのですが…ダメでした。 おかしなところがありましたら教えてください。 よろしくお願いします。 対象のテキストデータです。 0 32.57 32.48 32.48 32.57 32.66 32.75 32.75 32.75 33.01 33.10 32.93 32.48 32.21 32.21 32.30 32.21 32.21 32.12 32.12 32.21 1 32.57 32.57 32.48 32.48 32.57 32.66 32.66 32.75 32.93 33.01 32.84 32.39 32.21 32.21 32.21 32.21 32.12 32.12 32.21 32.21 2 32.66 32.66 32.66 32.66 32.75 32.84 32.84 32.84 32.93 33.10 32.93 32.48 32.21 32.21 32.12 32.12 32.12 32.12 32.12 32.21 … 239 37.53 37.28 36.76 36.16 35.64 35.21 34.86 34.51 34.16 33.90 33.54 33.37 33.28 33.10 32.93 32.75 32.57 32.39 32.30 32.21 よろしくお願いします。

  • fortranについて

    fortranでコンパイルしようとすると、 READ(1,FILE='syoki.txt') X0(I),Y0(I) ^ Invalid form for READ statement at (^) とエラー?が出てしまうのですが、原因としてどのようなことが考えられるでしょうか。 どなたかお願いします。

  • Fortran90で可変長ファイルを読む

    Fortran90初心者です。 実験でたとえば 時刻 温度 流速 t1   T1  v1 (CR/LF) ... ... ... tn   Tn  vn (CR/LF) のような ascii data file (FILE.dat)を得ています。 実験ごとに n の値、つまり、行数が違っており、このファイル内のデータを 次のようなFortran.90のプログラムで読み取って、その後処理を行っています。 integer :: Nl ! number of lines integer :: i character(180) :: dummy_line ! for void reading real(8), allocatable :: time(:), temp(:), velocity(:) open (5,file='FILE.dat', status='unknown',form='formatted') Nl = 0 do read(5,*, end = 99) dummy_line ! void read is absurd !! Nl = Nl + 1 end do 99 write(*,*)"eof encountered at Nl = ", Nl ! total lines in the file allocate(time(Nl), temp(Nl), velocity(Nl)) ! allocation of variables rewind(5) ! read pointer is set to the beginning of the file do i=1, Nl read(5,*) time(i), temp(i), velocity(i) end do この方法だと、元のファイルを2度読み込むことになりますので、あまり 賢い方法ではないと怒られています。実験データを出力する機器の方でファイルの 先頭にデータ数 n を吐き出させることもできません。 Fortran90だけでデータを読みながら動的配列を増やしてゆく方法があったら ご教示のほどお願いします。 Cならリスト処理やreallocで可能かとも思いますし、Linux上なら wc -lと Cのpopenとでも可能かとは思うのですが、プラットフォームはwindows7 で、intel fortranを使用しています。 (最終手段は入力部はCで、処理部はFortranで、linkするのでしょうか。) よろしくお願いします。

  • fortran77で複数のファイルの読み込み

    fortran77で複数のファイルの読み込み 現在fortran77のプログラムを勉強しております。 ファイルが複数あり、すべてのファイルを読み込みたいのですが、ファイルの数がたくさんあるため、プログラムの行数が多くなってしまいます。 do ループで次々とファイルを開くプログラムを考えているのですが、思いつきません。 どなたか考え方でもいいので、教えてください。 ちなみに私が考えたプログラムは、 open(10,file='C:\FORTRAN\100.txt',status='old') open(11,file='C:\FORTRAN\121.txt',status='old') open(12,file='C:\FORTRAN\144.txt',status='old') open(13,file='C:\FORTRAN\169.txt',status='old') open(14,file='C:\FORTRAN\196.txt',status='old') open(15,file='C:\FORTRAN\225.txt',status='old') ・・・。 これを do ループで次々に開くことを考えると、 character*3 A(10) do 100 i=1,10 A=i*i open(i,file='C:\FORTRAN\A.txt',status='old') 100 continue ・・・ みたいな感じです。 ' 'の中の一部だけを変えたい場合のcharacter 文の使い方がいまいちよく分かりません。

  • fortranで読み込んだ複数ファイルデータの見方

    また質問です。 character (13) :: fname do i = 1 , 3 write (fname ,"('sample_' , i2.2 , '.csv ')") , i enddo open (10 , file = fname) close (10) end fortranで連番のcsvファイルを上記のプログラムで読み込ませることはできたのですが、それぞれのファイルのデータの見方が分かりません。装置番号10でread文やwrite文を書くと最後に読み込んだファイルのデータしか見れません。どなたか教えてください。

  • FORTRANのプログラミングについて

    たびたび申し訳ありません。 またFORTRANに関しての質問です。 x y z 0 0 30 1 0 45 2 0 60 3 0 43 4 0 51 5 0 32 0 1 43 1 1 90 2 1 32 3 1 85 4 1 65 5 1 90 0 2 32 1 2 32 と続くファイルがあります。これをFORTRANをで書き換えて、 0 0 30 0 1 43 0 2 32 1 0 45 1 1 90 1 2 32 と続くデータにしたいのです。(これを以下目的のファイルという) 今のところ、次のようなプログラムを書き、特定のXに対しては、結果を吐き出すことに成功しています。 program dat real x1(100),h,y2(100),y1(100),z1(100) integer i,n,j,k,l,m,a(100) open(7,file='test.txt') open(9,file='af-test.dat') do i=1,100 read(7,*,end=200) x1(i),y1(i),z1(i) if(x1(i).eq.90)then write(9,*) x1(i),y1(i),z1(i) end if end do 200 close(7) close(9) end ここまではうまくいくのですが、これでは90以外の場合は出力されません。(あたりまえですが) 特定のXに限らずに例えばXを0から100まで吐き出されるような目的のファイル作るにはをどのようにしてプログラムを書けばいいかご教授ください。

  • fortranのプログラミングについてです。

    フォートランで任意のデータの総和を求めるプログラムを書きたいのですが 例えばデータファイルに2,3,6,8とあればその和19が出てくる感じです。 よくやりかたがわかりません。 始めにこのようにファイル形式でデータを取り込みます。 INTEGER n OPEN(5,FILE='test.txt') 100 READ(5,*,END=110) n WRITE(*,*) n GO TO 100 110 CONTINUE CLOSE(5) END 次に総和をはじきだしたいのですが。ここのところがよくわかりません。 どうか教えていただきたいのですが。

  • fortranについての質問です。

    fortranについての質問です。 このFortranは、頭にそれぞれ14161~14163とつく33個のファイル(1/1~12/31,欠損地あり1年分)を読んでいき、例えば1/1、1/2…と365日分の33年の平均値を導くはずなのですが、下のようなエラーがでます。おそらく、14161が2008までないからではないかと思うのですが、現在勉強中なので、なにかアドバイス、おかしいところ修正できるところがありましたらお願いします。 program sapporo_kikouchi    INTEGER :: sum, no, point INTEGER :: year, mon, day, data INTEGER :: doy REAL,dimension(365) :: temp, ndata REAL :: lon, lat CHARACTER*4 yyyy CHARACTER*5 sssss ndata(:)=0.0 temp(:)=0.0 do ispot=14161,14163 write(sssss,"(i5)") ispot do iwork=1976, 2008 write(yyyy,"(i4.4)") iwork open(50, file=''//sssss//'_temp'//yyyy//'.csv', status='old') ! write(6,*) ispot iwork    do i = 1,366 read(50,*,iostat=io) id,year,mon,day,lon,lat,data if(io < 0) exit if(mon==2 .AND. day==29) then cycle endif call date2doy(year,mon,day,doy) temp(doy) = temp(doy) + data/10.0 ndata(doy) = ndata(doy) + 1 end do close(50) enddo !!! end of year loop enddo do i=1,365 if( ndata(i) == 0 ) then temp(i) = -99999.9 else temp(i)=temp(i)/ndata(i) endif write(6,*) i, temp(i), ndata(i) enddo stop end program subroutine date2doy(iy,im,id,idoy) INTEGER,dimension(12) :: nday INTEGER :: uruu !!uruu=1: うるう年、uruu=0: 通常の年 uruu=0 DATA nday /31,28,31,30,31,30,31,31,30,31,30,31/ if(mod(iy,4)==0 .AND. mod(iy,100)/=0) then uruu=1 endif if(mod(iy,1000)==0) then uruu=1 endif !! うるう年も無視する itotal = 0 if( im /= 1 )then do m=1, im-1 itotal = itotal + nday(m) enddo endif idoy = id + itotal ! write(6,*) iy,im,id, idoy return end ------------------------------------------------------------------------------ At line 18 of file kikouchi.f90 file: "14161_temp1993.csv" Traceback: not available, compile with -ftrace=frame or -ftrace=full Fortran runtime error: 指定されたファイルが見つかりません。 -------------------------------------------------------------------------------

  • Fortranで1行飛ばして読み込む方法

    例えば次の内容が書かれているテキストファイル(data.txt)があるとします. ------------data.txt------------ time temperature 1.000E+00 5.632E+02 -------------------------------- このdata.txtに書いてある2行目の値をfortranを用いて読み込もうとすしたいのですが, fortranで open(100,file='data.txt') read(100,*) time, temperature と書くと, data.txtの1行目の'time temperature'の文字を読み込もうとし,当然エラーが出てしまいます. 読み込みたいのはdata.txtの2行目の数値のみなのですが, その方法がわかりません. 読み込む方法を教えていただけないでしょうか.

専門家に質問してみよう