在Fortran中保存PPM

时间:2018-10-31 13:33:06

标签: fortran

因此,作为学习Fortran的练习,我决定从我的并行编程类中重新实现一个分配,该分配的目的是加载,水平模糊然后保存PPM(P3)图像文件。我的code可以读取(具有适当的深度和尺寸),但是当我保存数据时,图像显示为乱码,几乎一半的数据丢失。

subroutine loadppm( this, filename )
        class( ppmfile )                   :: this
        character( len = * ), intent( in ) :: filename

        integer              :: funit, cdepth, cwidth, cheight, x, y, cr, cg, cb, reason
        character( 2 )       :: header

        open( newunit = funit, file = filename, status = 'old', action = 'read', access = 'stream', form = 'formatted' )

        read( funit, '(a2)' ) header
        if ( header /= 'P3' ) then
            print *, "Invalid file type detected."
            stop
        end if

        read( funit, * ) cwidth, cheight
        read( funit, * ) cdepth

        if ( cdepth /= 255 ) then
            print *, "Invalid colour depth detected."
            stop
        end if

        this%width  = cwidth
        this%height = cheight
        this%depth  = cdepth

        allocate( this%data( 3, this%width, this%height ) )

        do y = 1, this%width
            do x = 1, this%height
                read( funit, *, IOSTAT = reason ) cr, cg, cb

                if ( reason < 0 ) then
                    ! EOF reached
                    exit
                    exit
                end if

                this%data( 1, y, x ) = cr
                this%data( 2, y, x ) = cg
                this%data( 3, y, x ) = cb
            end do
        end do

        close( funit )
    end subroutine loadppm

我将其范围缩小到loadppm()方法。由于某种原因,它会正确读取第一个像素。由于某种原因,每隔一个读入的像素是错误的。我尝试读取的格式可以归结为:

P3
2 2
255
232 112 255 255 255 255
112 212 2 97 12 112

第一行是标题,第二行是尺寸,第三行是颜色深度(始终为255)。之后的所有行都是像素数据,每个三元组都是给定像素的RGB值。当我输出读取的内容时,第一个三元组是正确的(例如,它匹配文件中的内容),但是之后的所有内容都是错误的;例如,它与文件中的内容不匹配。文件中会忽略换行符,但任何给定值之间都只有一个空格。

1 个答案:

答案 0 :(得分:1)

Erik,

您遇到的问题是您使用read语句。在fortran中,即使该行上仍有数据,读语句也会在完成后始终前进到下一行。这就是为什么您正确读取某些数据的原因,它是该行开头的数据。

如果PPM中的所有整数正好是3个字符,则可以使用advance='no'来解决此问题:

READ( funit, '(I3)', IOSTAT = reason, advance='no' ) cr
READ( funit, '(I3)', IOSTAT = reason, advance='no' ) cg
READ( funit, '(I3)', IOSTAT = reason, advance='no' ) cb

但是对于更一般的情况,您需要将整个行作为字符串读取,然后手动将其拆分为数组。