Silverfrost Forums

Welcome to our forums

Importing BMP images: how can I determine their dpi?

1 Sep 2010 4:01 #6873

I am facing a terrible problem: my program makes some analysis of B&W images that are imported as bmp. The analysis depends, for instance, on the number of pixels in the image contour. The problem that appeared today is that, while one of the images was saved as 300 dpi, another was saved as 200 dpi resolution. The point is that I cannot know a priori which is the resolution of each image, and as I have to compare, for instance, the size of them, the results will be wrong as they are not in the same scale!. I was investigating the Clearwin+ subroutines but found no way to extract the information of dpi that is included in the bmp file. Is there any 'un-documented' information in the clearwin library that could help me?

Thanks!

Agustin

1 Sep 2010 6:35 #6874

Try using GET_DIB_SIZE@.

1 Sep 2010 7:07 #6875

Quoted from PaulLaidler Try using GET_DIB_SIZE@.

GET_DIB_SIZE gives you the number of pixels in vertical and horizontal directions but not the DPI, so if you have an image that should be greater in pixel size but it was exported al lower dpi, the result will be wrong! I think that the solution could be to open the bmp file as binary and read the record where the information of the dpi is allocated, but I do not know how to do this.......at the moment...

Agustin

2 Sep 2010 3:18 #6879

http://en.wikipedia.org/wiki/BMP_file_format might be easier to find ....

Eddie

2 Sep 2010 3:46 #6880

Quoted from brucebowler But the ugly URL already has fortran code to do what the OP wants 😃

well, more or less.....the statement

 open(10,file='gary.bmp',iostat=ios,status='old',form='binary')

is wrong and the derived types are using dots instead of %....

I am still investigating the case.....

Agustin Holmes...

2 Sep 2010 10:59 #6889

To read the header information of a BMP file, it might be better to open it like

      character*1    buffer1(max_size_of_file)

      call openr@(ifile,handle_i,rtc)
      if (rtc .ne. 0) goto ...
      call readf@(buffer1,handle_i,2000,i,rtc)   
      if (rtc .ne. 0) goto ...
      call r_bmp_head(rows,cols,bits,buffer1,hdlen)

and then use something like

      subroutine r_bmp_head(rows,cols,bits,buffer1,hdlen)
c
c     reads BMP header
c
      IMPLICIT NONE

      integer*4      j,k,l,m,n,rows,cols,bits,hdlen
      character*1    buffer1(*)

      hdlen = ichar(buffer1(11))+256*ichar(buffer1(12))   
      cols  = ichar(buffer1(19))+256*ichar(buffer1(20))
      rows  = ichar(buffer1(23))+256*ichar(buffer1(24))
      bits  = ichar(buffer1(29))
     ...

     return
     end

Regards, Wilfried

5 Sep 2010 5:11 #6901

Bruce,

It wasn't a case of URL aesthetics, more a case of the URL leading to a login for Google Groups,and not directly to the information requested that made me suggest the Wikipedia reference.

Eddie

.

5 Sep 2010 11:01 #6905

It seems that the BMP files do not have to specify their resolution, and the appropriate places in the DIB header are then set to zero.
Have a look at this link http://msdn.microsoft.com/en-us/library/ms969901.aspx If you open up such a BMP in Paint, it seems to default to 72dpi.
The values are stored as dpm i.e. metres not inches. e.g. 2835dpm=72dpi

Here is a badly written program to print the data for a specified BMP file.

winapp
program BMP_test
call BMP_Properties('myfile.bmp')
end
subroutine BMP_Properties(file)
character*(*) file
integer*1 iheader(0:45)
  character*2 id
  integer*4 isize,data_start,header_size
  integer*4 width,height,compression_method
  integer*4 image_size,horiz_rez,vert_res
  integer*2 planes,colour_depth
equivalence (iheader,id)
equivalence (iheader(2),isize)
equivalence (iheader(10),data_start)
equivalence (iheader(14),header_size)
equivalence (iheader(18),width)
equivalence (iheader(22),height)
equivalence (iheader(26),planes)
equivalence (iheader(28),colour_depth)
equivalence (iheader(30),compression_method)
equivalence (iheader(34),image_size)
equivalence (iheader(38),horiz_rez)
equivalence (iheader(42),vert_res)
open(unit=10,file=file,access='direct',recl=1)
do i=0,45
  read(10,rec=i+1)iheader(i)
enddo
print '(16(z2,1x))',iheader
close(unit=10)
print *,id,isize,data_start,header_size,width,height
print *,planes,colour_depth
print *,compression_method,image_size,horiz_rez,vert_res

end
6 Sep 2010 12:26 #6912

An update, and some programs seem to default the dpi to 96.

winapp
program getfiles 
character*1000 lv_items
common/bmp_text/lv_items(0:1000)
common/bmp_numb/isel(1000),iview
external iget_files
lv_items = ' '
lv_items(0) = '|Name_120|Id_30|FileSize_60|Starts at_60|Width_60|Height_60'// &
              '|Planes_60|Bit/pix_60|Comp_60|Size_60|Hres_60|Vres_60'
isel = 0
isel(1) = 1
iview = 1
i=winio@('%ca[BMP file properties]&')
i=winio@('%bg[btnface]%ww&')
i=winio@('%mn[Files]&',iget_files)
i=winio@('%ff%lv&',760,250,lv_items,1001,isel,iview)
i=winio@(' ')
end


integer*4 function iget_files()
C_EXTERNAL GET_MULTIPLE_FILENAMES@ 'get_multiple_file_names'(VAL,INSTRING,STRING,VAL,INSTRING,INSTRING,VAL):LOGICAL 
logical L,next 
character*256 filename,filter,defpath 
character*1000 lv_items
common/bmp_text/lv_items(0:1000)
common/bmp_numb/isel(1000),iview
iget_files = 1
filter = 'Bitmap files (*.bmp)'//char(0)//'*.bmp'//char(0)//char(0) 
defpath = char(0) 
L = .TRUE. 
next = .FALSE.
ifile = 0
lv_items(1:1000) = ' '
do while(L) 
 filename = char(0) 
 L=GET_MULTIPLE_FILENAMES@(0,'Dialog Title',filename,256,filter,defpath,next) 
 next = .TRUE. 
  if(L) then
    ifile = ifile + 1
    call BMP_Properties(filename,ifile)
  endif
end do
end


subroutine BMP_Properties(file,i)
character*(*) file
type bmp_header
  sequence
  character*2 id
  integer*4 isize
  integeR*4 reserved
  integer*4 data_start
  integer*4 header_size
  integer*4 width
  integer*4 height
  integer*2 planes
  integer*2 colour_depth
  integer*4 compression_method
  integer*4 image_size
  integer*4 horiz_rez
  integer*4 vert_res
end type bmp_header
type (BMP_header) bmp
character*1000 lv_items
common/bmp_text/lv_items(0:1000)
common/bmp_numb/isel(1000),iview
open(unit=10,file=file,access='transparent')
read(10)bmp
close(unit=10)
ipos_slash = max(1,index(file,'\',BACK=.true.))+1
lv_items(i) = '|'//file(ipos_slash:)
ipos=leng(lv_items(i))+1
write(lv_items(i)(ipos:),1000)bmp%id, bmp%isize, bmp%data_start, &
   bmp%width, bmp%height, bmp%planes, bmp%colour_depth, bmp%compression_method, &
   bmp%image_size, bmp%horiz_rez, bmp%vert_res
1000 format('|',a,11('|',i8))
end
6 Sep 2010 5:52 #6915

Ian,

I have just four words: your program is brilliant!

It is what I was looking for! I will see to implement your code in my program to check the bmp file properties before it is loaded. By the way: very nice the implementaion of %lv .....I guess I will use %lv to present a report of output data instead of writting characters and characters along the main window of my program!

Thanks a lot!

Agustin

12 Sep 2010 1:41 #6934

Yes, this was cool example, Ian

13 Sep 2010 8:15 #6935

Ian,

Nice code, linking elegantly to the 'get multiplefiles' call.

Is the 96 dpi related to the normal fonts setting in Windows? (120dpi for Large Fonts).

Eddie

14 Sep 2010 11:56 #6938

Eddie, I'm sorry, I don't know the answer to that question Ian

Please login to reply.