I'm currently trying to use a CMP decompressor: https://web.archive.org/web/20070113004119/http://rewiki.regengedanken.de:80/wiki/.CMP
It does in fact decompress the cmp, but it does not write it into a file.
So i tried myself.
int main(int argc, char** argv)
{
int length, dstLength;
unsigned char* fileInMem; //compressed data
unsigned char* dstFile; //decompressed data
if (argc < 2) {
fprintf(stderr, "give filename.cmp as parameter\n");
return 1;
}
printf("%s", argv[1]);
fileInMem = loadFile(argv[1], &length); //compressed data read
if (fileInMem == NULL) {
return 1;
}
dstFile = parseCmp(fileInMem, length, &dstLength); //decompress and assign data to dstFile
if (dstFile) {
/* Now we can save the file from dstFile, dstLength bytes */
printf("%d bytes depacked\n", dstLength);
for (int i = 0; i < 16; i++) {
dataArray[i] = fileInMem[i];
}
FILE *writer = fopen(argv[2], "r+");
//fputs(fileInMem, writer);
//fputs(dstFile, writer);
fclose(writer);
free(dstFile);
}
free(fileInMem);
return 0;
}
As you can see the decompressed data is a pointer to an unsigned char (according to the website a bitstream) and I tried fputs() from stdio.h, but the resulting file contains only 4 Bytes when viewed in a hex-editor.
If you need more information, please comment.
Thank you in advance.
Edit: This is what I was able to change thanks to your help, but when I open the file, it is still empty:
FILE* writer = fopen(argv[2], "wb");
fwrite(dstFile, 192, 192, writer);
192, because the length of the first decompressed Image is 192 Bytes large.
This is a common issue.
First, you need to open the output file writer for writing in binary mode ("wb").
FILE *writer = fopen(argv[2], "wb");
Second, you can't use fputs to write arbitrary data to a file, since it expects a string. Use fwrite instead: (assuming writer is the output file, dstFile the decompressed data and dstLength the amount of bytes to write)
fwrite(dstFile, 1, dstLength, writer);
If you examine the resulting file with an hex editor, you will see it is identical to the decompressed data.
Test-update
I wrote some test-code to see what is wrong, share your results so we can help you.
Add these functions to your code:
void printDataToScreen(unsigned char *dataptr, int datalen)
{
if (dataptr == NULL)
{
printf("[!] ERROR, NULL POINTER PROVIDED!\n");
return;
}
printf("> Dumping %d bytes of data into the terminal...\n", datalen);
for (int i = 0; i < datalen; i++)
{
if (i % 16 == 0)
printf("\n ");
printf("%02X ", dataptr[i]);
}
printf("\n\n");
}
void writeDataToFile(char *fileName, unsigned char *dataptr, int datalen)
{
FILE *file = fopen(fileName, "wb");
if (dataptr == NULL)
{
printf("[!] ERROR, NULL POINTER PROVIDED!\n");
return;
} else if (file == NULL)
{
printf("[!] ERROR WHILE OPENING FILE '%s'!\n", fileName);
return;
}
printf("> Writting %d bytes of data to '%s'...\n", datalen, fileName);
int writtenBytes = fwrite(dataptr, 1, datalen, file);
printf(" Done, %d bytes written!\n\n", writtenBytes);
fclose(file);
}
void runTest(char *fileName, unsigned char *dataptr, int datalen)
{
printf("Running tests... [0/2 done]\n");
printDataToScreen(dataptr, datalen);
printf("Running tests... [1/2 done]\n");
writeDataToFile(fileName, dataptr, datalen);
printf("Finished! [2/2 done]\n");
}
Call it like this:
runTest(argv[2], dstFile, dstLength);
Add the call to this place in your code (comment this code, also the line where you close writer):
FILE *writer = fopen(argv[2], "r+");
//fputs(fileInMem, writer);
//fputs(dstFile, writer);
Please share your results.
Related
i'm a little puzzled about binary files and how to read from them, so if someone could help that would be great.
i have a file that contains the following bits:
00000000000000000000000000000111
(32 bits. i counted)
now i have written this code:
int main()
{
FILE * f1;
f1 = fopen("file2", "rb");
int i = 0;
fread(&i, sizeof(int), 1, f1);
printf("%d", i);
fclose(f1);
return 0;
}
that prints me 808464432.
why? shouldnt it print 7?
thank you for reading.
That is not a binary file, it's a text file, try this instead
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *file;
int value;
char text[33];
char *endptr;
file = fopen("file2", "r");
if (file == NULL) /* check that the file was actually opened */
return -1;
if (fread(text, 1, sizeof(text) - 1, f1) != sizeof(text) - 1)
{
fclose(file);
return -1;
}
text[32] = '\0';
value = strtol(text, &endptr, 2);
if (*endptr == '\0')
printf("%d", value);
fclose(file);
return 0;
}
To write a binary file you need this
#include <stdio.h>
void hexdump(const char *const filename)
{
FILE *file;
unsigned char byte;
file = fopen(filename, "rb");
if (file == NULL)
return;
fprintf(stdout, "hexdump of `%s': ", filename);
while (fread(&byte, 1, 1, file) == 1)
fprintf(stdout, "0x%02x ", byte);
fprintf(stdout, "\n");
}
int main()
{
const char *filename;
FILE *file;
int value;
filename = "file.bin";
file = fopen(filename, "wb");
if (file == NULL)
return -1;
value = 7;
if (fwrite(&value, sizeof(value), 1, file) != 1)
fprintf(stderr, "error writing to binary file\n");
fclose(file);
/* check that the content of the file is not printable, i.e. not text */
hexdump(filename);
file = fopen(filename, "rb");
if (file == NULL)
return -1;
value = 0;
if (fread(&value, sizeof(value), 1, file) != 1)
fprintf(stderr, "error writing to binary file\n");
else
fprintf(stdout, "The value read was %d\n", value);
fclose(file);
return 0;
}
as you will see from the example above, the stored data in file.bin is not in text format, you cannot inspect it with a text editor because the bytes 0x00 and 0x07 are not printable, in fact 0x00 is the nul byte which is used in c to mark the end of a string.
This is one way you can write and read to a binary file. you should know the difference between a binary and ASCII file, before reading from them.
Read this once https://stackoverflow.com/a/28301127/3095460 and understand what is type of file you are reading using your code.
if you open a file in an editor and see 00000000000000000000000000000111 it does not mean its a binary file, most of the editor process files as ascii text file only. you need a binary editor to open a binary file and read meaningful data from them.
#include <stdio.h>
int main()
{
FILE *Read_fptr = NULL;
FILE *Write_fptr = NULL;
int data = 20;
size_t nElement = 1;
if ( (Write_fptr = fopen("data.bin", "wb")) != NULL ) {
if ( fwrite(data, nElement, sizeof data, Write_fptr) != sizeof data ) {
fprintf(stderr,"Error: Writing to file\n");
fclose(Write_fptr);
return -1;
}
} else {
fprintf(stderr,"Error: opening file for writing\n");
return -1;
}
fclose(Write_fptr);
data = 0;
if ( (Read_fptr = fopen("data.bin", "rb")) != NULL ) {
if ( fread(data, nElement, sizeof data, Read_fptr) != sizeof data) {
if( !feof(Read_fptr) ) {
fprintf(stderr,"Error: Reading from file\n");
fclose(Read_fptr);
return -1;
}
}
} else {
fprintf(stderr,"Error: opening file for reading\n");
return -1;
}
fclose(Read_fptr);
printf("%d\n",data);
return 0;
}
I am trying to get the data from an array of longs that I have just created but I got different data.
please see code below :
#include <string.h>
#include "readfile.h"
int main()
{
long wr_data [6] ;
wr_data[0] = 11;
wr_data[1] = 1100;
wr_data[2] = 1122323;
wr_data[3] = 11333;
wr_data[4] = 11434243;
wr_data[5] = 1166587;
writeFile(wr_data);
readFile();
return(0);
}
int readFile()
{
FILE *file;
long * data
printf("Error Reading File\n");;
/* Open file for both reading and writing */
file = fopen(fileName, "r");
if (file == NULL)
{
printf("Error Reading File\n");
return -1;
}
for (int i = 0; i < 5; i++)
{
fscanf(file, "%ld", &data[i] );
printf("data[%d]: %ld \n",i, data[i]);
}
fclose(file);
return 0;
}
int writeFile(long * data)
{
FILE *fp;
if (data != NULL)
{
if ((fp = fopen(fileName,"w")) == NULL)
return -1;
if (*data !=0 )
fwrite(data,sizeof(long),6,fp);
printf("Write data\n");
fclose(fp);
}
return 0;
}
the result I get is as follows :
Write data
data[0]: 140526045102081
data[1]: 47
data[2]: 197764
data[3]: 140526045102080
data[4]: 4096
I want to preserve the write function as it is as it comes from an existing code. I tried also the function fread but without success
fread(data, sizeof(long ), 6, file);
Thanks in advance for help.
It's working here. I made the following changes to your code:
//needed for malloc
#include <stdio.h>
//needed for output
#include <stdlib.h>
...
char *fileName = "so";
...
//allocate memory to store the values
long *data = (long *)malloc(sizeof(long)*6);
...
//read the stored longs
fread(data, sizeof(long ), 6, file);
int i;
for(i=0; i<6; i++)
printf("%ld\n", data[i]);
what do you think?
edit:
Well the main change was the memory allocation. When you want to store values of any kind, your program needs to be granted by the operating system a memory zone to store those values.
In this case we had two options, either create a staticly allocated array with a fixed size, or allocate the needed memory in a dynamic fashion with the malloc function or equivalent.
Don't forget, if you want to store something, first make sure you have a place for it to be stored (i.e. allocated memory). If you don't you will most likely get an error "Segmentation Fault" aka "SIGSEGV" which means that you tried to access memory that didn't belong to you.
Also, the "fscanf(file, "%ld", &data[i] );" will read "file" as text and will try to parse floats out of that same text. Since you're storing the longs as longs and not as text, this will not work, since you're writing and reading different things.
You are writing the binary content of the array to the file and afterwards try to interpret this as a long value which can obviously not work. If you want to store the numbers as text you must convert them to text before writing or print them to file by using the fprintf(FILE *, const char *, ...) function.
It is working as expected using the following code using a text file (you might want to change the filename). Otherwise you could just fwrite and fread the whole content, depending on your needs.
#include <stdio.h>
const char *filename = "yourfile";
int readFile()
{
FILE *file;
long data[6];
int i;
printf("Error Reading File\n");;
/* Open file for both reading and writing */
file = fopen(filename, "r");
if (file == NULL)
{
printf("Error Reading File\n");
return -1;
}
for (i = 0; i < 6; i++)
{
fscanf(file, "%ld", &data[i] );
printf("data[%d]: %ld \n",i, data[i]);
}
fclose(file);
return 0;
}
int writeFile(long * data)
{
FILE *fp;
int i;
if (data != NULL)
{
if ((fp = fopen(filename,"w")) == NULL)
return -1;
if (*data !=0 )
{
for(i = 0; i != 6; ++i)
fprintf(fp, "%ld ", data[i]);
}
printf("Write data\n");
fclose(fp);
}
return 0;
}
int main()
{
long wr_data [6] ;
wr_data[0] = 11;
wr_data[1] = 1100;
wr_data[2] = 1122323;
wr_data[3] = 11333;
wr_data[4] = 11434243;
wr_data[5] = 1166587;
writeFile(wr_data);
readFile();
return(0);
}
So the assignment is to implement a substring search program using an input file to be searched from and an input to be searched. I created the following code:
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{
FILE *fp;
fp = fopen(argv[1],"r");
if (fp == NULL)
{
printf("Error");
return 0;
}
char* tmpp[100];
int count = 0;
char* nexts = argv[2];
char* tmp = fgets(tmpp,100,fp);
while(tmp = strstr(tmp,nexts))
{
count++;
tmp++;
}
printf("%d\n\n",count);
fclose(fp);
return 0;
}
The program compiles but when i go to implement it in the ubuntu terminal as:
echo "aabb" >beta
./a.out beta a
1
Why isnt the program using the first argument (argv[1]) as beta and the second argument (argv[2]) as a correctly?
You should open a file and then read bytes from that file into temporary buffer:
FILE *file = fopen("file", "r");
while (1) {
char buffer[BUFSIZ+1];
size_t nread = fread(buffer, 1, sizeof(buffer)-1, file);
if (nread == 0) break; // read error or EOF
buffer[nread] = 0;
// chunk with BUFSIZ amount of bytes is available via buffer (and is zero-terminated)
}
If you want to search for string/pattern in a file, be aware that looked pattern in file may cross your chunk-size boundary, for example: you look for "hello", and BUFSIZ is 512. File contains "hello" at byte 510. Obviously, if you read by 512, you will get the first chunk ending with "he", and the second chunk starting with "llo". Probability of this situation is nonzero for all chunk sizes (except SIZE_MAX, but that buffer size is impossible by other reasons). Dealing with borders may be very complicated.
Close...but this is closer:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "Usage: %s file pattern\n", argv[0]);
return 1;
}
FILE *fp = fopen(argv[1], "r");
if (fp == NULL)
{
fprintf(stderr, "Error: failed to open file %s for reading\n", argv[1]);
return 1;
}
char tmpp[1000];
int count = 0;
char* nexts = argv[2];
while (fgets(tmpp, sizeof(tmpp), fp) != 0)
{
char *tmp = tmpp;
while ((tmp = strstr(tmp, nexts)) != 0)
{
count++;
tmp++;
}
}
printf("%d\n", count);
fclose(fp);
return 0;
}
The main difference is that this loops reading multiple lines from the input file. Yours would only work on files with a single line of input.
how i can read ppm image that have magic code P3. in c language?
this code reading ppm image that have magic code P3 but there a problem with loading method,this code enters into in infinite loop when reading the value of pixles?
/* This is for reading and Writing images file in PPM
Also example of making Negative images
- Use this file as an example of reading (loading) and writing (storing) images files.
- This program loads an PPM image and store a new image that is the negative of the original image.
*/
typedef struct pdata {
int red;
int green;
int blue;
} pdata;
typedef struct ppm {
int w;
int h;
int max;
pdata *pData;
} ppm;
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
//#define kernelW 3
//#define kernelH 3
//#define imageW 403
//#define imageH 332
char filename[256];
/*
This LoadPGM function is an updated version that will deal with
comments in file headers and do at least some basic checking if the
file can be opened or is the correct format. It does assume the file
is actually a valid length once the header has been read.
You are of course free to use your own file reading functions.
*/
void LoadPGM( char* filename, ppm* pPgm ) {
FILE* ifp;
int word;
int nRead = 0;
char readChars[256];
//open the file, check if successful
ifp = fopen( filename, "r" );
if (!ifp) {
printf("Error: Unable to open file %s.\n\n", filename);
exit(1);
}
//read headers from file
printf ("Reading PPM file: %s...\n", filename);
fscanf (ifp, "%s", readChars);
if (strcmp(readChars, "P3") == 0) {
//valid file type
//get a word from the file
fscanf (ifp, "%s", readChars);
while (readChars[0] == '#') {
//if a comment, get the rest of the line and a new word
fgets (readChars, 255, ifp);
fscanf (ifp, "%s", readChars);
}
//ok, comments are gone
//get width, height, color depth
sscanf (readChars, "%d", &pPgm->w);
fscanf (ifp, "%d", &pPgm->h);
fscanf (ifp, "%d", &pPgm->max);
// allocate some memory, note that on the HandyBoard you want to
// use constant memory and NOT use calloc/malloc
pPgm = (ppm *)malloc(sizeof(ppm));
pPgm->pData = (pdata*)malloc(pPgm->w *pPgm->h * sizeof(pPgm->pData));
fscanf(ifp, "%d" ,&word);
pPgm->pData[0].red = word;
printf (" %d \n", word);
for (nRead = 0; nRead < pPgm->w * pPgm->h; nRead++) {
fscanf(ifp, "%d" ,&word);
// printf (" %d \n",word);
pPgm->pData[nRead].red = word;
fscanf(ifp, "%d" ,&word);
pPgm->pData[nRead].green = word;
fscanf(ifp, "%d" ,&word);
pPgm->pData[nRead].blue = word;
}
printf ("Loaded PPM. Size: %dx%d, Greyscale: %d \n",
pPgm->w, pPgm->h, pPgm->max + 1);
}
else {
printf ("Error: Read file type %s. Format unsupported.\n\n", readChars);
exit(1);
}
fclose(ifp);
}
/* Simply saves the PGM file to a file whose name is in filename */
void WritePGM( char* filename, ppm* pPgm ) {
FILE* ofp;
int w, h, max;
int nWrite = 0;
int i,j;
strcat(filename, ".out.ppm");
ofp = fopen(filename, "w");
if (!ofp) {
printf("Error: Unable to open file %s.\n\n", filename);
exit(1);
}
printf ("Writing ouput PPM: %s\n\n", filename);
//write the header
fprintf( ofp, "P3\n" );
fprintf( ofp, "%d %d\n", pPgm->w, pPgm->h );
// printf("Done. Have a nice day...\n\n");
fprintf( ofp, "%d\n", pPgm->max );
//write the image data
for (i = 0; i < pPgm->h;i++) {
for (j = 0; j < pPgm->w; j++)
fprintf(ofp,"%d ",*(pPgm->pData + i * pPgm->w + j));
fprintf(ofp,"\n");
}
fclose(ofp);
}
int main(int argc, char * argv[]) {
ppm* image, *r1,*r2;
// char filename[256];
int val;
int errchk;
char f1[256];
//check if a filename was given, if not, ask for one
if (argc > 1) {
strcpy(filename, argv[1]);
}
else {
printf ("Enter filename: ");
scanf ("%s", filename);
}
//allocate memory for the pgm struct
image = (ppm *) malloc (sizeof(ppm));
//read the file
LoadPGM(filename, image);
int h,w;
w=image->w;
h=image->h;
int* pBuff1;
int* pBuff2;
int size;
int sum=0;
WritePGM(filename, image);
// end of the program
}
This line
malloc(pPgm->w *pPgm->h * sizeof(pPgm->pData))
allocates the wrong size. It allocates sizeof(pointer) while you need it sizeof(pdata), your own RGB struct.
Typically, one only needs RGB as 3 unsigned char, and had you used that the error would have been invisible, since pointers are usually 4 bytes long (and nowadays can even be longer). But since you made your values each an int, the structure uses 12 bytes in total. Somewhere after the first third has been read (give or take), your code starts overwriting other stuff in memory and you get toasted.
How do I read the bytes from a bmp file using C?
Here's a general-purpose skeleton to just load a binary file, and return a pointer to the first byte. This boils down to "fopen() followed by fread()", but is a ... bit more verbose. There's no error-handling, although errors are checked for and I believe this code to be correct. This code will reject empty files (which, by definition, don't contain any data to load anyway).
#include <stdio.h>
#include <stdlib.h>
static int file_size(FILE *in, size_t *size)
{
if(fseek(in, 0, SEEK_END) == 0)
{
long len = ftell(in);
if(len > 0)
{
if(fseek(in, 0, SEEK_SET) == 0)
{
*size = (size_t) len;
return 1;
}
}
}
return 0;
}
static void * load_binary(const char *filename, size_t *size)
{
FILE *in;
void *data = NULL;
size_t len;
if((in = fopen(filename, "rb")) != NULL)
{
if(file_size(in, &len))
{
if((data = malloc(len)) != NULL)
{
if(fread(data, 1, len, in) == len)
*size = len;
else
{
free(data);
data = NULL;
}
}
}
fclose(in);
}
return data;
}
int main(int argc, char *argv[])
{
int i;
for(i = 1; argv[i] != NULL; i++)
{
void *image;
size_t size;
if((image = load_binary(argv[i], &size)) != NULL)
{
printf("Loaded BMP from '%s', size is %u bytes\n", argv[i], (unsigned int) size);
free(image);
}
}
}
You can easily add the code to parse the BMP header to this, using links provided in other answers.
Use fopen and fread as suggested by others. For the format of the bmp header take a look here
fopen followed by fread
ImageMagick supports BMP. You can use either of two C APIs, the low-level MagickCore or the more high level Magick Wand.
make sure this file is not compressed using RLE method. otherwise, you'll have to read from the file and dump into a buffer to reconstruct the image, after reading the header file and knowing it's dimensions.