How to combine ppm image files in C using only system calls? - c

I've found some similar questions on the internet, but not with system calls.
I'm doing an exercise in my system programming class. It asks you to combine ppm image files in binary form(P6, not P3) using only system calls. Input is taken from command line. The first input is the larger image file, the second input is the smaller image file, and after the inputs the files are combined and written into a third file, which you can specify the name of as a third input. The smaller file is written into the top-right of the larger file.
Since we're using system calls, I'm assuming we're mainly using open/read/write/lseek. I know that my ppm files will store the magic number P6 at the beginning, and then the width and height of the file. I know that I can use lseek by writing from the left side of row 1 of the larger ppm file, then stopping when my pointer reaches the difference in size between the two files, and writing the remaining pixels for the line from the smaller file. Then continuing, line by line...
However, I have no idea how to implement this. I'm not sure how to even read the width and height of the file, either. I'm sort of lost. Can someone help me get on the right track? I'd post my code if I actually had anything meaningful, but I just created file descriptors for the files and opened them so far.
EDIT:
I combine them by overwriting the top right of the larger file with the smaller file. I'm not guaranteed anything about the images, so I have to somehow pull the width and height from both files and compare them, to make sure the first file has both a larger width and height than the second.
I think they want us to loop through the files, pixel by pixel, reading each rgb group of values for each pixel using read. Then writing in a loop, pixel by pixel, using write.
EDIT2:
Here's a list of unix system calls. They're available in the c library, but this is all I'm allowed to use: http://www.di.uevora.pt/~lmr/syscalls.html

Related

C - drawing in a bitmap

I have to calculate the flight path of a projectile and draw the result in a bitmap file. So far I'm pretty clueless how to do that.
Would it be a good idea to safe the values of the flight path in a struct and transfer it to the bitmap file?
Do you have any other suggestions how it could be done in a better way?
The simplest way to produce an image file without much hassle with only standard C library tools is most likely writing a bmp file. For start, check the Wikipedia article on this file format, it gives a quite complete description of it.
If you don't want to go too deep in that, save for example a 640x480 or so empty 24 bit ("truecolor") .bmp image, and rip out it's header for your use. Depending on the program you use to save your image, you might end up with varying header size, however since the data is not compressed, it is fairly easy isolate the header. For a 640x480 image the data will be exactly 921600 bytes long, anything preceding it is the header.
From here the colors are (usually) in RGB order, bottom to top row, left to right. Experimenting a little should give you the proper results.
If you only have the standard C libraries to work with, it is unlikely there is anything much simpler to implement. Of course this case you will have to write a pixel matrix (so no much assistance for solving the actual problem you want to image), but that's true for any image format (maybe except if you rather aim for creating an SVG for a twist, it is neither too hard, just XML).

Why Vlfeat generates same number of descriptors for different images?

I notice that Vlfeat/Sift generates same number of descriptors for different images, why?
And what is the aim of orientation assignment? It seems there is a similar process in the descriptor formation process.
I am quite new to the SIFT and confused about a lot of stuff in SIFT. Thanks for your help.
Vlfeat/Sift generates same number of descriptors for different images, why?
Except if you explicitly pass a file with given input keypoints (*) the number of descriptors is NOT the same and clearly depends on the input image content.
For example, if you compare the Starbucks logo with Lena:
./sift --frames starbucks.pgm; wc -l starbucks.frame
601 starbucks.frame
./sift --frames lena.pgm; wc -l lena.frame
1769 lena.frame
Here I used 300x300 pixels images. The --frames outputs the keypoints found with one position, scale and orientation per line.
(*) This means you ask VLFeat to describe a set of pre-defined interest points. With the sift VLFeat command line tool, you can do that with the --read-frames option.
What is the aim of orientation assignment?
This is to achieve rotation invariance. If you refer to the original paper:
One or more orientations are assigned to each keypoint location based on local
image gradient directions. All future operations are performed on image data that
has been transformed relative to the assigned orientation, scale, and location
for each feature, thereby providing invariance to these transformations.

Text files edit C

I have a program which takes data(int,floats and strings) given by the user and writes it in a text file.Now I have to update a part of that written data.
For example:
At line 4 in file I want to change the first 2 words (there's an int and a float). How can I do that?
With the information I found out, fseek() and fputs() can be used but I don't know exactly how to get to a specific line.
(Explained code will be appreciated as I'm a starter in C)
You can't "insert" characters in a file. You will have to create program, which will read whole file, then copy part before insert to a new file, your edition, rest of file.
You really need to read all the file, and ignore what is not needed.
fseek is not really useful: it positions the file at some byte offset (relative to the start or the end of the file) and don't know about line boundaries.
Actually, lines inside a file are an ill defined concept. Often a line is a sequence of bytes (different from the newline character) ended by a newline ('\n'). Some operating systems (Windows, MacOSX) read in a special manner text files (e.g. the real file contains \r\n to end each line, but the C library gives you the illusion that you have read \n).
In practice, you probably want to use line input routines notably getline (or perhaps fgets).
if you use getline you should care about free-ing the line buffer.
If your textual file has a very regular structure, you might fscanf the data (ignoring what you need to skip) without caring about line boundaries.
If you wanted to absolutely use fseek (which is a mistake), you would have to read the file twice: a first time to remember where each line starts (or ends) and a second time to fseek to the line start. Still, that does not work for updates, because you cannot insert bytes in the middle of a file.
And in practice, the most costly operation is the actual disk read. Buffering (partly done by the kernel and <stdio.h> functions, and partly by you when you deal with lines) is negligible.
Of course you cannot change in place some line in a file. If you need to do that, process the file for input, produce some output file (containing the modified input) and rename that when finished.
BTW, you might perhaps be interested in indexed files like GDBM etc... or even in databases like SqlLite, MariaDb, mongodb etc.... and you might be interested in standard textual serialization formats like JSON or YAML (both have many libraries, even for C, to deal with them).
fseek() is used for random-access files where each record of data has the same size. Typically the data is binary, not text.
To solve your particular issue, you will need to read one line at a time to find the line you want to change. A simple solution to make the change is to write these lines to a temporary file, write the changes to the same temporary file, then skip the parts from the original file that you want to change and copy the reset to the temporary file. Finally, close the original file, copy the temporary file to it, and delete the temporary file.
With that said, I suggest that you learn more about random-access files. These are very useful when storing records all of the same size. If you have control over creating the orignal file, these might be better for your current purpose.

Copy sparse files

I'm trying to understand Linux (UNIX) low-level interfaces and as an exercise want to write a code which will copy a file with holes into a new file (again with holes).
So my question is, how to read from the first file not till the first hole, but till the very end of the file?
If I'm not mistaken, read() returns 0 when reaches the first hole(EOF).
I was thinking about seeking right byte by byte and trying to read this byte, but then I have to know the number of holes in advance.
If by holes you mean sparse files, then you have to find the holes in the input file and recreate them using lseek when writing the output file. Since Linux 3.1, you can even use lseek to jump to the beginning or end of a hole, as described in great detail in the man page.
As ThiefMaster already pointed out, normal file operations will treat holes simply as sequences of zero bytes, so you won't see the EOF you mention.
For copies of sparse files, from the cp manual;
By default, sparse SOURCE files are detected by a crude heuristic and the corresponding DEST file is made sparse as well. That is the behavior selected by --sparse=auto. Specify --sparse=always to create a sparse DEST file whenever the SOURCE file contains a long enough sequence of zero bytes. Use --sparse=never to inhibit creation of sparse files.
Thus, try --sparse=always if you need to copy a sparse file 'as-is' (still seems affected by an algo)
A file is not presented as if it has any gaps. If your intention is to say that the file has sections on one area of the disk, then more on another, etc., you are not going to be able to see this through a call to open() on that file and a series of read() calls. You would instead need to open() and read() the raw disk instead, seeking to sectors on your own.
If your meaning of "holes" in a file is as #ThiefMaster says, just areas of 0 bytes -- these are only "holes" according to your application use of the data; to the file system they're just bytes in a file, no different than any other. In this case, you can copy it through a simple read of the data source and write to the data target, and you will get a full copy (along with what you're calling holes).

ARM binary and hexedit

I have an ARM binary file and want to change some text.
I remove couple of text-symbols from comment.
But the binary won't start, with log:
link_image[1710]: 3013 missing essential tables CANNOT LINK EXECUTABLE
Does anybody have an idea how to edit ARM binary files?
I remove couple of text-symbols
Stop right there. If I am reading what you wrote correctly, you removed some characters, instead of replacing them with other characters.
This would shift the whole rest of the file. But binary files often have tables or offsets which point to other parts of the file. Shifting the contents of the file, even by a single byte, means these tables or offsets no longer point where they should. The code trying to read the file was rightly confused after that.
When editing binary files, you must never move the contents, unless you know what you are doing. If you are editing the text, your changes must not change the size of the text. If the new text is smaller, you must pad it so it keeps the same size; if the new text is larger, it will not fit and you must find a shorter text.
Of course, this assumes that the file format does not have checksums which would notice the change, or that you know how to recompute them.
Also, make sure you are using a proper editor. Normal text editors can silently add, remove, or replace characters, which could break the file, possibly in a hard-to-detect way.

Resources