Search code examples
image-processingoctaveimread

Octave thinks, that image I want to imread() doesn't exist


I'm writing a function in Octave to easily add particles on an image, but I have a problem.

function [ out ] = enparticle( mainImg, particleNames, particleData, frames, fpp, sFrame, eFrame )

  %particleData format:
  % [ p1Xline p1StartHeight p1EndHeight;
  %   p2Xline p2StartHeight p2EndHeight;
  %   p3Xline p3StartHeight p3EndHeight;
  % ... ]
  %particleNames format:
  % [ p1Name;
  %   p2Name;
  %   p3Name;
  % ... ]

  pAmount = size(particleData, 1);

  for i= 1:pAmount
    tmp = particleNames(i,:) 
    [ pIMG pMAP pALPHA ] = imread( tmp );
  end

end

When I run this simple code with

enparticle( "ffield.png", [ "p_dot.png"; "p_star.png"; "p_dot.png" ], [ 100 50 100; 200 50 100; 300 50 100 ], 30, 10, 5, 25 )

I get this written in console

tmp = p_dot.png
error: imread: unable to find file p_dot.png
error: called from
    imageIO at line 71 column 7
    imread at line 106 column 30
    enparticle at line 24 column 23

When I try to imread() file this way, Octave thinks, that there is no file named like this. But it is actually. In the same folder as script file.

The most curious thing is that, when I change

    tmp = particleNames(i,:) 

to

    tmp = particleNames(:,:)

and Octave assigns all names to tmp as array, it magically find all the files with passed names.

But it's not the way I want it to work, because all files will be replaced, or merged, or sth along image processing then.

Why I'm trying to do it that way is corelated with fact, that I want to put every frame (of image and alpha) separately into a cell array later.

I totally don't have any clue, about what I do wrong there and can't google it anywhere also :(


Solution

  • The code:

    filenames = [ "p_dot.png"; "p_star.png"; "p_dot.png" ]
    

    does not do what you think it does. This will create a 2 dimensional array of characters. See

    octave> size (filenames)
    ans =
    
        3   10
    

    Of interest note is that it lists 10 columns. Take a look at your filenames and you will notice that their file names are of different lengths, two have length 9 and one has length 10. But this is just like a numeric matrix, the only difference is you have ascii characters. And like a numeric matrix, all rows must have the length. What is happening, is that the shortest rows get padded with whitespace. You can confirm this by checking the ascii decimal code of your filenames:

    octave> int8 (filenames)
    ans =
    
      112   95  100  111  116   46  112  110  103   32
      112   95  115  116   97  114   46  112  110  103
      112   95  100  111  116   46  112  110  103   32
    

    Note how the first and third row end in '32'. In ASCII, that's the space character (see the wikipedia article about ASCII which has the tables)

    So the problem is not that imread does not find a file named 'p_dot.png', the problem is that it does not find a file named 'p_dot.png '.

    You should not be using character arrays for this. Instead, use a cell array. In a cell array of char arrays. Like so:

    filenames = {"p_dot.png", "p_start.png", "p_dot.png"}
    for i = 1:numel (filenames)
      fname = filenames{i};
      [pIMG, pMAP, pALPHA] = imread (fname);
      ## do some stuff
    endfor