Reading a .tiff file in c from inside zip - c

I have multiple tiff images stored inside a zip file and would like to read their pixel values in c. I am very new to c so please forgive the dodgy code. I have got to the point where I have a char * with the contents of the tiff file but can't seem to work out how to now process that with libtiff (or something similar). libtiff seems to require that I pass TIFFOpen a filename to open. I could write the tiff to a temporary file but it feels like there must be a more efficient way.
So far I have:
#include <stdlib.h>
#include <stdio.h>
#include <zip.h>
#include <string.h>
int main()
{
//Open the ZIP archive
int err = 0;
struct zip *z = zip_open("test.zip", 0, &err);
// Determine how many files are inside and iterate through them
int num_files = zip_get_num_entries(z, 0);
printf("%u\n", num_files);
int i;
for (i=0; i < num_files; i++)
{
const char * filename;
filename = zip_get_name(z, i, 0);
// If the file name ends in .tif
if (strlen(filename) > 4 && !strcmp(filename + strlen(filename) - 4, ".tif"))
{
printf("%s\n", filename);
// Get information about file
struct zip_stat st;
zip_stat_init(&st);
zip_stat(z, name, 0, &st);
printf("%lld\n", st.size);
// Allocate memory for decompressed contents
char *contents;
contents = (char *)malloc(st.size);
// Read the file
struct zip_file *f = zip_fopen(z, filename, 0);
zip_fread(f, contents, st.size);
zip_fclose(f);
// Do something with the contents
// Free memory
free(contents);
}
}
//And close the archive
zip_close(z);
}
EDIT: My question is similar to this one but the accepted answer there relates to c++ and I'm not sure how to translate it to straight c.

Related

listing files in a folder using C in Windows

I want to list the files in this folder "C:\home\WORK\Desktop\Communication". There are ten files in this folder. My code has no error but it's not printing anything. What is my mistake ?
#include<stdio.h>
#include<Windows.h>
#include<string.h>
int main(int argc,char *argv[])
{
char path[]="C:\\home\\WORK\\Desktop\\Communication";
strcat_s(path,sizeof(path),"\\*");
WIN32_FIND_DATA fdata;
HANDLE hFind =INVALID_HANDLE_VALUE;
int numberOfFiles=0;
char *files[10];
hFind = FindFirstFile(path,&fdata);
while((FindNextFile(hFind,&fdata))!=0)
{
files[numberOfFiles]=fdata.cFileName;
numberOfFiles++;
printf("%s\n",files[numberOfFiles]);
}
FindClose(hFind);
return 0;
}
There are a few things wrong with your code.
strcat_s can't append "\\*" to your path char array. The buffer only has enough room for storing the string literal.
I'm uncomfortable with letting you declare a buffer files that has only enough memory to fit all the file names. What happens if you add one more file? Then the buffer is overrun. However, it will still technically work in this scenario.
This line printf("%s\n",files[numberOfFiles]); is undefined behavior. You incremented numberOfFiles to a location in the array that has not been initialized, so it's not going to print the file name.
When you call FindClose, you invalidate all of those pointers that you stored in files. You can no longer use them. You need to copy the string to a new buffer.
The following code works.
#include<stdio.h>
#include<Windows.h>
#include<string.h>
int main(int argc,char *argv[])
{
char path[] = "C:\\home\\WORK\\Desktop\\Communication\\*.*";
//strcat_s(path,sizeof(path),"\\*");
WIN32_FIND_DATA fdata;
HANDLE hFind =INVALID_HANDLE_VALUE;
int numberOfFiles=0;
char* files[10]; /* you may want to expand this buffer */
hFind = FindFirstFile(path,&fdata);
while((FindNextFile(hFind,&fdata))!=0)
{
size_t len = strlen(fdata.cFileName);
files[numberOfFiles] = malloc(len + 1 * sizeof*files); // len + 1 for null-terminator
strcpy_s(files[numberOfFiles], len, fdata.cFileName);
printf("%s\n",files[numberOfFiles]);
numberOfFiles++; /* increment this AFTER you print files[numberOfFiles] */
}
FindClose(hFind);
for(int i = 0; i < (sizeof(file)/sizeof(*file)); ++i) {
free(file[i]);
}
return 0;
}
Seems, you should move
numberOfFiles++
past
printf("%s\n",files[numberOfFiles]);
Or
while((FindNextFile(hFind,&fdata))!=0)
{
files[numberOfFiles]=fdata.cFileName;
printf("%s\n", files[numberOfFiles++]);
}
Which is same as
while((FindNextFile(hFind,&fdata))!=0)
{
printf("%s\n", files[numberOfFiles++] = fdata.cFileName);
}
I don't know WinAPI well, but I feel, that all files will contain invalid pointers after FindClose(hFind) as well as all elements of files will point to *(fdata.cFileName) which will be released in FindClose(hFind). In other words, as I understand this, you should copy (or duplicate) fdata.cFileName into files[i] on each iteration.
Clear fdata struct after declaring it:
memset( &fdata, 0, sizeof fdata )

Writing Bitmap Image to File

I'm trying to read in a bitmap image from one file and write it to another just to check that the contents were transferred. However when I run my code, the image doesn't get created into the output file. Instead, whenever I click on the new file it tells me that the file couldn't be opened. Here is what my header file looks like:
//////////////////////////////////////////////////////////////////////
// RGB.h header file for bitmap BMP definitions
// adapted from <WinGDI.h>
///To get DIB header struct. winGDI.h is huge overkill for the needs here
#ifndef RGBH //don't doubly include this stuff, set a flag when first including
#define RGBH
/* structures for defining DIBs //from WinGDI.h */
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef unsigned long int LONG;
typedef unsigned char BYTE;
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
typedef PBITMAPFILEHEADER pbfh;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize; /* used to get to color table */
DWORD biWidth;
DWORD biHeight;
WORD biPlanes;
WORD biBitCount;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
typedef BITMAPINFOHEADER pbih;
typedef struct tagRGBTRIPLE { //from WinGDI.h
BYTE b; //rgbtBlue;
BYTE g; //rgbtGreen;
BYTE r; //rgbtRed;
} pix, *ppix;
#define BYTES_PER_PIX sizeof(pix)
const pix RED = {0,0,255};
const pix GREEN = {0,255,0};
const pix BLUE = {255,0,0};
#endif
////////////////////// End of RGB.h header file ////////////////////////////////
And here is the code I have written:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "RGB.h" //header file for Bitmap
BITMAPFILEHEADER *hp; //var pointer to the header file for bitmap
BITMAPINFOHEADER *p; //var pointer to the info file for bitmap
#define SIZE 100
int main(void)
{
FILE *bp, *op; //var for two file streams
char pix[SIZE]; //var for char name of input file
char out[SIZE]; //var for char name of output file
int n; //var to hold different values through out the program
unsigned char *bitmapImage; //var to store image data
printf("Enter bitmap filename: "); //prompts user to enter filename
scanf("%s", pix); //collects filename from user
//open filename in read binary mode
if((bp = fopen(pix, "rb")) == NULL) if ((bp = fopen(pix, "rb")) == NULL)
{
printf("Can't open file %s", bp); //prints if file path wasn't valid
getchar();
exit (1);
}
//malloc memory for file header
hp = (tagBITMAPFILEHEADER*)malloc(sizeof(tagBITMAPFILEHEADER));
//reads the bitmap file header
n = fread(pix, 1,SIZE, bp);
//read bitmap info header
fread(bp, sizeof(tagBITMAPINFOHEADER), 1, bp);
//allocate enough memory for the bitmap image data
p = (tagBITMAPINFOHEADER*) (pix+14);
bitmapImage = (unsigned char*) malloc(p->biSize);
//verify memory allocation
if (!bitmapImage)
{
free(bitmapImage);
fclose(bp);
puts("Memory allocation not allowed");
return NULL;
}
puts("Input File Statistics: \n");
printf("File size: %ld bytes", p->biSize); //prints out total file size
printf("\nWidth x Height = %ld x %ld", p->biWidth, p->biHeight); //prints out dimensions of image
printf("\nBits/pixel = %u\n", p->biBitCount);
printf("\nEnter an output filename for bitmap: "); //prompts user for output file name
scanf("%s", out); //collects pathway from user
//open output file
if((op = fopen(out, "wb")) == NULL)
{
puts("Invalid file");
fclose(op);
exit (2);
}
fclose(op);
return 0;
}
Any advice would be greatly appreciated! Thanks! O. Helm
Sometimes the solution is too easy to see.
Are you using the same "counter" in both for loops? I think that will not work.
Also, in your fread and fwrite, you are probably reading to and writing from the same place. You need to update the pointer of where you are reading to.
The comment for your first fread says "reads the bitmap file header". I am not sure it is doing that correctly.
Check your second fread. It might have a fatal problem. Are you sure you want to read into bp? Perhaps it will help you if you use more meaningful names for your variables.
Do you need to write BITMAPFILEHEADER and BITMAPINFOHEADER out? Check to ensure you are doing that correctly.
Since this is a class assignment, obviously it is best to not give precise help. I hope this helps enough to make progress. If there is anything more than I hope you can find them by looking closely.

Want to fill Structure for Metadata

Here i have one directory which has number of files.
I want to fill this files all information in one structure.
I have two structures which are following.
struct files {
char *file_name;
int file_size;
};
typedef struct file_header {
int file_count;
struct files file[variable as per number of files];
} metadata;
i want to make one header which contains all information regarding these files.
like if i have 3 files than i want to make this structure like this in file_count = 3 and how can i allocate second variable value? and want to store file name and file size as per file.
i want file structure like this
file_count = 3
file[0].file_name = "a.txt"
file[0].file_size = 1024
file[1].file_name = "b.txt"
file[1].file_size = 818
file[2].file_name = "c.txt"
file[2].file_size = 452
I have all logic about file name and file size but how can i fill these things in this structure.?
Code :
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
char path[1024] = "/home/test/main/Integration/testing/package_DIR";
//int count = 5;
struct files {
char *file_name;
int file_size;
};
typedef struct file_header {
int file_count;
struct files file[5];
} metadata;
metadata *create_header();
int main() {
FILE *file = fopen("/home/test/main/Integration/testing/file.txt", "w");
metadata *header;
header = create_header();
if(header != NULL)
{
printf("size of Header is %d\n",sizeof(metadata));
}
if (file != NULL) {
if (fwrite(&header, sizeof(metadata), 1, file) < 1) {
puts("short count on fwrite");
}
fclose(file);
}
file = fopen("/home/test/main/Integration/testing/file.txt", "rb");
if (file != NULL) {
metadata header = { 0 };
if (fread(&header, sizeof(header), 1, file) < 1) {
puts("short count on fread");
}
fclose(file);
printf("File Name = %s\n", header.file[0].file_name);
printf("File count = %d\n", header.file_count);
printf("File Size = %d\n", header.file[0].file_size);
}
return 0;
}
metadata *create_header()
{
int file_count = 0;
DIR * dirp;
struct dirent * entry;
dirp = opendir(path);
metadata *header = (metadata *)malloc(sizeof(metadata));
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_type == DT_REG) { /* If the entry is a regular file */
header->file[file_count].file_name = (char *)malloc(sizeof(char)*strlen(entry->d_name));
strcpy(header->file[file_count].file_name,entry->d_name);
//Put static but i have logic for this i will apply later.
header->file[file_count].file_size = 10;
file_count++;
}
}
header->file_count = file_count;
closedir(dirp);
//printf("File Count : %d\n", file_count);
return header;
}
output :
size of Header is 88
ile Name = �~8
File count = 29205120
File Size = -586425488
Its shows different output. so whats problem here?
Among other things, you are using sizeof on a pointer variable, but seem to think that gives you the size of the object being pointed to. It doesn't. To do that, use the asterisk operator to make the expression have the type that the pointer points at:
printf("size of Header is %d\n", sizeof *metadata);
As a side note, notice that sizeof is not a function, so you don't need parenthesis. When you do see parenthesis, that's when they're part of the expression (a cast).
You are not leaving enough room for the null-terminator:
header->file[file_count].file_name = (char *)malloc(sizeof(char)*strlen(entry->d_name));

fwrite not writing entire buffer

I am currently making a small test program for simple file checking. The program writes two small matrices(A and B) to files, closes and reopens them, reads in the matrices from the files, multiplies them and writes the resulting matrix(C) to a new file. It then closes and reopens this file containing the answer and prints it out for me to check if the IO operation proceeded correctly.
My problem is that the result matrix reads differently than expected.
I consider myself a beginner in C and of file input/output operations and this is the code that is causing me trouble. I am using WinXP, Codeblocks and Mingw.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define bufferA(i,k) (bufferA[i*cols+k])
#define bufferB(k,j) (bufferB[k*cols+j])
#define bufferC(i,j) (bufferC[i*cols+j])
void printMatrix(int *nMatrixToPrint, int nNumberOfElements, int nDimension) {
// This function prints out the element of an Array. This array represents a matrix in memory.
int nIndex;
printf("\n");
for (nIndex = 0; nIndex < nNumberOfElements; nIndex++) {
if (nIndex % nDimension == 0)
printf("\n");
printf("%d,",nMatrixToPrint[nIndex]);
}
return;
}
int main(int argc, char *argv[]) {
int nElements = 16, nDim = 4;
int A[4][4] = {{1,2,3,1},{2,2,1,2},{4,2,3,1},{5,1,1,3}};
int B[4][4] = {{3,2,1,4},{2,2,3,3},{4,1,3,2},{2,2,5,1}};
// Create files of A and B, delete old ones if present
FILE *fpA = fopen("A.dat", "w+");
FILE *fpB = fopen("B.dat", "w+");
// Write data to them
fwrite((int*)A, sizeof(*A), nElements, fpA);
fwrite((int*)B, sizeof(*B), nElements, fpB);
// and close them
fclose(fpA);
fclose(fpB);
// Reopen files
fpA = fopen("A.dat", "r");
fpB = fopen("B.dat", "r");
// Allocate memory
int *bufferA = (int*)malloc(nElements * sizeof(*bufferA));
int *bufferB = (int*)malloc(nElements * sizeof(*bufferB));
int *bufferC = (int*)calloc(nElements, sizeof(*bufferC));
// Read files
fread(bufferA, sizeof(int), nElements, fpA);
fread(bufferB, sizeof(int), nElements, fpB);
printf("\nA");
printMatrix(bufferA, nElements, nDim);
printf("\n\nB");
printMatrix(bufferB, nElements, nDim);
// Matrix multiplication
// Calculate and write to C
int i,j,k = 0; // Loop indices
int n = nDim,l = nDim, m = nDim, cols = nDim;
// multiply
for (i = 0; i < n; i++) { // Columns
for (j = 0; j < m; j++) { // Rows
//C(i,j) = 0;
for (k = 0; k < l; k++) {
bufferC(i,j) += bufferA(i,k) * bufferB(k,j);
}
}
}
printf("\n\nC_buffer");
printMatrix(bufferC, nElements, nDim);
// Create C and write to it
FILE* Cfile = fopen("C.dat", "w");
fwrite(bufferC, sizeof(*bufferC), nElements, Cfile);
// Close files
fclose(fpA);
fclose(fpB);
fclose(Cfile);
// reopen C for reading
Cfile = fopen("C.dat", "r");
// Obtain file size
fseek(Cfile , 0 , SEEK_END);
long lSize = ftell(Cfile);
rewind(Cfile);
printf("\nC file length is: %ld", lSize);
// read data into bufferA
fread(bufferA, sizeof(int), lSize, Cfile);
fclose(Cfile);
printf("\n\nC_file");
printMatrix(bufferA, nElements, nDim);
// Free allocated memory and remove dangling pointers
free(bufferA); bufferA = NULL;
free(bufferB); bufferB = NULL;
free(bufferC); bufferC = NULL;
exit(0);
}
Which gives me the following output:
A
1,2,3,1,
2,2,1,2,
4,2,3,1,
5,1,1,3,
B
3,2,1,4,
2,2,3,3,
4,1,3,2,
2,2,5,1,
C_buffer
21,11,21,17,
18,13,21,18,
30,17,24,29,
27,19,26,28,
C file length is: 64
C_file
21,11,21,17,
18,13,21,18,
30,17,24,29,
27,19,1,3,
As you can see, the last two elements in C_file are wrong, instead the output shows the last two elements in A as I was writing the file contents into bufferA. A switch to bufferB would swap the last two characters with the last elements in B which is still erroneous. A filecopy into another project would yield the last two integers as whatever was in ram at that malloc address.
My question is as follows: Why does not fwrite write the proper data into the file. Why does it manage the first 14 elements but not the last two? And how does this differ from my previous correct uses of fwrite and fread when I wrote and retrieved the elements of A and B?
You are writing binary data, and therefore you have to open the file in binary mode, the default is text mode. This makes a difference on windows, but not on *nix, which explains why it works for the other people here.
for all your fopen calls, include the letter 'b' in the mode argument, e.g. replace "w+" with "w+b" , replace "r" with "rb" and so on.
Your program runs just fine on my Mac.
The results would look better if printMatrix() output a final newline. Perhaps the unterminated line is causing some sort of confusion on your system?

Manage data inside a buffer

I'm using this code to read a file into a buffer. The file is full of structs of evaluacion type (including some char and int variables).
Now I have the whole file in a buffer, how can I find the values of one variable in the buffer now?
For example buf.notamedia < 4. There are supposed to be many of them inside the file.
#include <unistd.h>
#include <sys/stat.h>
int revisanotas(int fd)
{
int nbytes = 1;
int nbytese = 0;
evaluacion buf;
struct stat datos;
fstat(fd, &datos);
printf("Size of file = %d \n", datos.st_size);
char *buffer = (char *)malloc(datos.st_size);
int actual = read(fd, buffer, datos.st_size);
printf("actual = %d\n", actual);
if (buf.notamedia >= 4.5 && buf.notamedia < 5)
{
/* ... */
}
}
Any idea is very welcome
I'm doing as you said, but I'm only getting one iteration, I don't know what I'm doing wrong :(
evaluacion* buffer=(evaluacion*)malloc(datos.st_size);
int actual = read(fd,buffer,datos.st_size);
printf("Number of structs = %d", (datos.st_size/(sizeof(evaluacion))));
for (i=0;i<(datos.st_size/(sizeof(evaluacion)));i++);
{
printf("Notamedia = %f\n",buffer[i].notamedia);
if (buffer[i].notamedia >= 4.5 && buffer[i].notamedia < 5)
{
printf("Notamedia = %f\n",buffer[i].notamedia);
}
{
}
}
}
Easiest to define the buffer as a pointer to the data structure and use that to dereference the data (although you should ensure the file size is a multiple of the structure size).
i.e.
evaluacion* buffer = (evaluation*)malloc(datos.st_size);
if(buffer[0].notamedia >= 4.5)
You can then increment the index to access other structures you loaded.
Thanks for the comments, I think I solved the problem, I modified the code:
#include <unistd.h>
#include <sys/stat.h>
int revisanotas(int fd)
{
int nbytes=1;
int nbytese=0;
int i=0;
int n=0;
struct stat datos;
fstat(fd, &datos);
evaluacion buf;
printf("File size = %d \n", datos.st_size);
evaluacion* buffer=(evaluacion*)malloc(datos.st_size);
int actual = read(fd,buffer,datos.st_size);
do
{
i++;
if (buffer[i].notamedia >= 4.5 && buffer[i].notamedia < 5)
{
n=n+1;
/*printf("Notamedia = %f\n",buffer[i].notamedia);
*/
buffer[i].notamedia=5;
}
}while (i<(datos.st_size/(sizeof(evaluacion))));
nbytese=write(fd,buffer,datos.st_size);
printf("Written bytes = %d\n",nbytese);
return(n);
}
Now, If the condition is matched, I'm modifying the buffer. Once I read all the structs I write the file in the disk again, but I still have a problem, every time, instead of write the file in the same position, seems like I'm adding the same information after the old one, so if I read the file once I get 3.5Mb, two times 7MB and so on :S.
Any idea what can I do?
Thanks

Resources