Silverfrost Forums

Welcome to our forums

how to work with bmp graphics

19 Jul 2007 7:55 #2080

I am trying to write a subroutine that can import for instance a bmp figure into a graphics region. The graphics region is defined according to the size of the image (for instance 800x600). The I need to read each pixel in order to see if it is white or black (the image is in B&W, by the way). If it finds a black point, then put a '1' in a matrix (or a '0' if it is white). In this way I am trying to transform a B&W picture into a binary matrix, so I can take distances from the center of the image or measure the border of the image, etc. I see that there is a subroutine like GET_PIXEL@ that allows to get the colour of the pixel, however, I do not see how can I create a graphics region where I can import, paste or insert the bitmap and then proceed with the identification of the pixels and the transformation to a matrix. Any ideas? Thanks a lot in advance!

Agustin

20 Jul 2007 4:22 #2087

Graphics regions are normally created by using %gr in a winio@ statement. Details can be found in the FTN95 help file under Win32 Platform->ClearWin+->Graphics.

24 Jul 2007 1:12 #2103

Thank you Paul for your answer. I looked at Clearwin+ and found some hints for importing my bmp file in a window. However, the problem now is that I cannot read the colour of the pixels in my image. This is a short version of my program


Program Imagine USE MSWIN implicit none CHARACTER*50 file CHARACTER a(3,1024,1024) INTEGER hres,vres,nb_colours,ier,i,k,control,red,white,black,j,green integer colour1,colour2,colour3 type coordenate integer x integer y end type coordenate type(coordenate),dimension(:),allocatable :: matrix file='c:\imagen640.bmp'

  CALL set_rgb_colours_default@(1)
  CALL get_dib_size@(file,hres,vres,nb_colours,ier)
  IF(ier.NE.0.OR.hres.GT.1024.OR.vres.GT.1024) STOP 'TROUBLE: file not found'
  CALL get_dib_block@(file,a,1024,1024,0,0,hres,vres,0,0,ier)
  IF(ier.NE.0) STOP 'TROUBLE'
  allocate(matrix(hres*vres))
  k=1
  
  i=winio@('%gr%lw',hres,vres,control)
  CALL display_dib_block@(0,0,a,1024,1024,0,0,hres,vres,0,0,ier)
  red=  get_matched_colour@(RGB@(255,0,0))
  black=get_matched_colour@(RGB@(0,0,0))
  white=get_matched_colour@(RGB@(255,255,255))
  green=get_matched_colour@(RGB@(0,255,0))

! check the bitmap to find the limits of the black figure on a white background
! the limiting point are saved in an array for plotting latter DO i=1,hres do j=1,vres CALL get_rgb_value@(i,j,colour1) CALL get_rgb_value@(i,j-1,colour2) CALL get_rgb_value@(i,j+1,colour3)
if(colour1 == black.and.colour2 /= black.and.colour3 ==black) then matrix(k)%x=i; matrix(k)%y=j k=k+1 call draw_point@(i,j,red) elseif(colour1 == black.and.colour2 == black.and.colour3 /= black) then matrix(k)%x=i; matrix(k)%y=j k=k+1 call draw_point@(i,j,red) else call draw_point@(i,j,green) endif END DO end do
open(87,file='c:\entorno') do i=1,k write (87,*) matrix(i)%x, matrix(i)%y end do close(87) !c--- Write the image away to another file
file='c:\temp\junk.bmp' CALL put_dib_block@(file,a,1024,1024,0,0,hres,vres,24,ier) END


The idea is to sweep the image along the pixels and check if the pixel is black or white and if it is in the border of the figure (i.e. for instance, the pixel at the border should be black but the previous should also be black and the next should be white if you are leaving the figure or the previous should be white and the next black if you are entering into the figure). For this purpose I call the subroutine CALL get_rgb_value@ and change the colour of the pixel to red if I am in the border (just for marking the border). However, what I get is the same whole figure in red instead of black! Am I misunderstanding the meaning of the subroutine CALL get_rgb_value@?. Any clue would be greatly appreciated!!

Thanks a lot!

Agustin

24 Jul 2007 6:48 #2104

Not sure about this, but I think you might want simply:

red= RGB@(255,0,0) black=RGB@(0,0,0) white=RGB@(255,255,255) green=RGB@(0,255,0)

rather than:

red= get_matched_colour@(RGB@(255,0,0)) black=get_matched_colour@(RGB@(0,0,0)) white=get_matched_colour@(RGB@(255,255,255)) green=get_matched_colour@(RGB@(0,255,0))

and is your input image 24-bit?

Andy

24 Jul 2007 12:31 #2108

Thanks Andy!, but the problem persists!. No change with your suggestion. I do not get the contour but the full figure. The figure is B&W and according to Irfanview is has 16.7 million colours and 24 bitsperpixel. I was searching the forums and there is no information about problems with get_rgb_value@, so I guess I am doing something wrong but I do not see where the mistake is!

Agustin

24 Jul 2007 12:46 #2109

It's not obvious to me either. I guess you have to resort to debugging. The first thing I would do would be to use a different colour in the first two branches of your IF construct (both use red at the moment, and that's the problem colour).

Have you used SDBG yet?

Andy

24 Jul 2007 1:25 #2110

Well, I used the debugger looking for mistakes in the program from the very begining. Now I changed the colour of the second if to green and the figure is still completely red!. When I follow the colour1,2,3 variables, at some point colour1 appears as 13750737 and colour2 and 3 take the value 16777215!!!. If the figure is B&W I would expect only 0 and 255, isn't it?.

Agustin

24 Jul 2007 2:44 #2111

So if the figure is still completely red, that tells you that the logic is wrong at the first IF rather than the second. The program 'thinks' that every pixel is right hand margin. There's a bug in your double DO loop, because you're trying to access pixels outside the image, but I don't know if that would be the problem - don't think so. As far as colours are concerned, if your image really is B+W but 24 bit, then yes B = 0 but W = 255 + 255x256 + 255x256^2 = 16777215. So it seems your image isn't actually B+W.

24 Jul 2007 3:36 #2112

You are right, the logic seems wrong according to the results, but: where the wrong statement is? I do not see where it is. The only problem seems to be a bug in the FNT95 subroutines o a mishandling of the subroutines by me. About the colours I noticed my mistake as soon I posted my previous message: white is 16777215 as you said! However, the get_rgb_value@ subroutine sometimes reports something different from 0 or 16777215. Is the picture only B&W? Imaging software say yes, but...On the other hand, this should not be an issue if one makes the comparison between black and not black. One should at least obtain a contour that would be not perfect but a contour!. I will continue investigating a little more, but it seems that the problem is not easy and probably comes from the compiler itself.

Thanks a lot for your time and suggestions!

Agustin

24 Jul 2007 5:31 #2113

I don't think the values returned by get_rgb_colour@ are the issue here. The issue is why the program always flows into the first branch of the IF statement. In an earlier post you said:

'When I follow the colour1,2,3 variables, at some point colour1 appears as 13750737 and colour2 and 3 take the value 16777215!!!'

so at that point the program should definitely not flow as it does - two of the three ANDs should be false. Matter of interest, 13750737 = 209 + 209x256 + 209x256^2 which is a light grey.

You've used SDBG, but what compile options did you use? If you compile using /CHECKMATE I imagine you will find the problem - certainly it ought to complain about you trying to access pixels outside the image in your double DO loop, if nothing else.

24 Jul 2007 6:21 #2114

Here is an example that may contribute to the debate:

      winapp
c---------------------------------------------------------------
      integer i,winio@
      external fill_func,start_cb

      i=winio@('%ww[no_maxminbox]&')
      i=winio@('%mn[&Exit]&','EXIT')
      i=winio@('%^gr[black,rgb_colours]&',100,250,fill_func)
      i=winio@('%sc',start_cb)
      end
c---------------------------------------------------------------      
      integer function start_cb()
      include <clearwin.ins>
      integer i,w
      call set_line_width@(2)
      w=RGB@(200,200,200)
      call rectangle@(1,1,99,249,w)
      do i=50,200,75                     
        call ellipse@(50,i,32,32,w)
      enddo
      start_cb=1
      end
c-------------------------------------------------------------
      integer function fill_func()
      include <clearwin.ins>
      integer x,y,v,r,a,g,w
      call get_mouse_info@(x,y,v)
      call get_rgb_value@(x,y,v)
      r=get_matched_colour@(RGB@(255,0,0))
      g=get_matched_colour@(RGB@(0,255,0))
      a=get_matched_colour@(RGB@(255,168,0))
      w=get_matched_colour@(RGB@(200,200,200))

      if(v.eq.0)then
        call fill_surface@(x,y,v,r)
      elseif(v.eq.r)then
        call fill_surface@(x,y,v,a)
      elseif(v.eq.a)then
        call fill_surface@(x,y,v,g)
      else
        call fill_to_border@(x,y,0,w)
      endif  

      fill_func=1
      end 
26 Jul 2007 2:32 #2115

I tried your program with a .bmp file i found in windows (bliss.bmp) and it did something !

  1. You should be careful with your do loop range.
  2. Why don't you see what colour values you are getting from the file, eg include the following in your code.

.... open (98,file='trace') write (98,) red, ' red' write (98,) black, ' black' write (98,) white, ' white' write (98,) green, ' green' ! DO i=0,hres-1 do j=0,vres -1 CALL get_rgb_value@(i,j,colour1) write (98,*) i,j,colour1 ...

Then think about what you want.

I also didn't change the pixel to green, but left it to display what was in the .bmp file.

! else ! call draw_point@(i,j,green)

You may get some clues from this ?

26 Jul 2007 7:02 #2116

I was hoping my program would give you some clues. Here are two points that are significant:

  1. %gr needs to have [rgb_colours] (there is also a function to do set this).
  2. get_matched_colours@ is only needed when you are not using a hi colour resolution.

In theory you should be able to replace the image in my sample code with your bitmap. Then when you click on the bitmap you should get the colour of the pixel at that point on the screen.

26 Jul 2007 8:05 #2118

Well, thanks a lot for all the comments and suggestions. I have added the suggestions of Paul ([rgb_colours] and removed get_matched_colour and put white=rgb@(255,255,255) instead,etc) and that of John. Yes! the figure is not purely b&W!!! I found that some pixels are quite different from that! In some cases the value is -1! (what colour is this?). Now the program gets almost all the contour, except of course where the colour is different from B&W, and when the contour is a straight line that is parallel to the x axis. This is reasonable because all the points in the column are black!. I think that this problem can be overcome by reading first a double do loop i,j and then a do double loop j,i, so I can cover the figure in two directions and avoid any problem of 'paralelism' with respecto to the reading direction. What I did not get is how to insert the figure in the graphic window and read the pixels or colours using Paul's program (as he suggested), but I guess I should read more deeply the manuals!

Now I will try the program with some figures. Hope all will run fine!

Best wishes,

Agustin

P.D. by the way, when the point is inside the contour, I cannot change the colour from black to white using draw_point@(i,j,white) (or green as posted in a preliminary message). Why? Who knows!.

27 Jul 2007 2:40 #2123

In hex, red is 0xff Green is 0xff00 Blue is 0xff0000

White is all of these 0xffffff.

-1 is 0xffffffff which is white with 0xff000000.

The top ff is used in modern grahics for transparency control (the alpha value).

I guess 0xff000000 means fully opaque but you should check this out.

Please login to reply.