I have a input file which has a header like this:
P6\n
width\n
height\n
depth\n
and then a struct is writen, pixel*, into this file, which is going to be mapped.
So, I want to skip the header and make my mmap function return the ptr to that structure. How can I do this? with lseek perhaps? Could you please exemplify?
I will leave part of my code here:
printf("Saving header to output file\n");
if (writeImageHeader(h, fpout) == -1) {
printf("Could not write to output file\n");
return -1;
}
last_index = (int)ftell(fpout);
//printf("offset after header= %d\n",last_index);
//alloc mem space for one row (width * size of one pixel struct)
row = malloc(h->width * sizeof (pixel));
/*Create a copy of the original image to the output file, which will be inverted*/
printf("Starting work\n");
for (i = 0; i < h->height; i++) {
printf("Reading row... ");
if (getImageRow(h->width, row, fpin) == -1) {
printf("Error while reading row\n");
}
printf("Got row %d || ", (i + 1));
printf("Saving row... ");
if (writeRow(h->width, row, fpout) == -1) {
printf("Error while reading row\n");
}
printf("Done\n");
}
/*Open file descriptor of the ouput file.
* O_RDWR - Read and Write operations both permitted
* O_CREAT - Create file if it doesn't already exist
* O_TRUNC - Delete existing contents of file*/
if ((fdout = open(argv[2], O_RDWR, FILE_MODE)) < 0) {
fprintf(stderr, "Can't create %s for writing\n", argv[2]);
exit(1);
}
/*Get size of the output file*/
if (fstat(fdout, &sbuf) == -1) {
perror("Stat error ---------->\n");
exit(1);
}
//printf("Size of output file: %d\n",(int)sbuf.st_size);
/*Maps output file to memory*/
if ((data = mmap((caddr_t) 0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, 0)) == (caddr_t) (-1)) {
perror("Error mmaping");
exit(EXIT_FAILURE);
}
As you see, right now my ppm image is mapped to char*
data, but I want to skip the header and map just to the pixel*
part.
Here's my code with the suggestion of using 2 pointers, a char* from mmap and another one equals that + offset.
If you read the man page for mmap
, you wil find that its final parameter is off_t offset
. The description:
... continuing or at most 'len' bytes to be mapped from the object described by 'fd', starting at byte offset 'offset'.
I suspect if you pass your offset in as that parameter, it will do what you want.
如果您需要跳过的数量小于系统页面大小,则不能,因为在某些系统上, offset
必须是页面大小的倍数。
You just need to keep 2 pointers - the pointer to the start of the mmap
'd block, and the pointer to the start of the data you want inside there. As in:
unsigned char *block = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, 0);
unsigned char *data = block + offset;
where offset
is the offset in the file to the data you want.
So, from what I understand, can I do something like this?
off_t offset_after_header = lseek(fdout, last_index, SEEK_SET);
printf("Pointer is on %d\n",(int)offset_after_header);
/*Maps output file to memory*/
if ((data = mmap((caddr_t) 0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, offset_after_header)) == (caddr_t) (-1)) {
perror("Error mmaping");
exit(EXIT_FAILURE);
}
and, from that, I could map my file to whatever type I want, in this case the pixel*
If this is ok, what cautions should I take? For example, like those Ignacio Vazquez-Abrams said
Um, you did notice the 'offset' parameter that you are supplying with a zero? Assuming you know the absolute offset of what you want, you pass it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.