-
Notifications
You must be signed in to change notification settings - Fork 0
/
simple_bmp.c
167 lines (144 loc) · 4.62 KB
/
simple_bmp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/**
Created by jmorales on 4/22/20.
*/
#include "simple_bmp.h"
/**
* Initialize a new image
*
* Initialize a new BMP image: 24 bits, without compression, without color pallet (2^BitsPerPixel colors are use)
* @param [out] image Clear (not null) sbmp_image to initialize
* @param [in] height in pixels (>0)
* @param [in] width in pixels (>0)
* @return The result of the Initialization, begin SBMP_OK if all worked OK \n
* or SBMP_ERROR_PARAM if the parameters are not valid
*/
enum sbmp_codes sbmp_initialize_bmp (sbmp_image *image, uint32_t height, uint32_t width)
{
if ( image == NULL || height == 0 || width == 0
|| height > INT32_MAX || width > INT32_MAX )
{
return SBMP_ERROR_PARAM;
}
// Headerd
image->type.file_type = TIFF_MAGIC_NUMBER;
image->type.data_offset = sizeof (sbmp_ftype_data) + BITMAPINFOHEADER; // arreglar sizeof + size of
image->type.file_size = (uint32_t) image->type.data_offset;
image->type.file_size += (((uint32_t) sizeof (sbmp_raw_data)) * width + width % 4) * height;
image->type.reserved = 0;
image->info.header_size = BITMAPINFOHEADER;
image->info.image_width = (int32_t) width;
image->info.image_height = (int32_t) height;
image->info.planes = 1;
image->info.bit_per_pixel = 24;
image->info.compression = 0;
image->info.image_size = 0;
image->info.xpix_per_meter = 0;
image->info.ypix_per_meter = 0;
image->info.total_colors = 0;
image->info.important_colors = 0;
image->data = calloc (height, sizeof (sbmp_raw_data *));
if (image->data == NULL)
{
fprintf (stderr, "Error alocando memoria");
exit (EXIT_FAILURE);
}
for (uint32_t i = 0; i < height; i++)
{
image->data[i] = calloc (width, sizeof (sbmp_raw_data));
if (image->data[i] == NULL) /* Meeh ?*/
{
fprintf (stderr, "Error alocando memoria");
exit (EXIT_FAILURE);
}
}
return SBMP_OK;
}
/**
* Save image in the filesystem
* @param [in] filename File path
* @param [in] image Image to save
* @return begin SBMP_OK if all worked OK or SBMP_ERROR_FILE if you can't create the file
*/
enum sbmp_codes sbmp_save_bmp (const char *filename, const sbmp_image *image)
{
FILE *fd = fopen (filename, "w");
if (fd == NULL)
{
fprintf (stderr, "Error: %s\n", strerror (errno));
return SBMP_ERROR_FILE;
}
// Write the headers
fwrite (&image->type, sizeof (image->type), 1, fd);
fwrite (&image->info, sizeof (image->info), 1, fd);
// Padding is necessary
size_t padd_size = ((size_t) image->info.image_width * sizeof (sbmp_raw_data)) % PADDINGSIZE;
uint8_t *zero_pad = NULL;
if (0 != padd_size)
{ // Yes
padd_size = PADDINGSIZE - padd_size;
zero_pad = (uint8_t *) calloc (PADDINGSIZE, sizeof (uint8_t));
}
for (int32_t i = image->info.image_height - 1; i >= 0; i--)
{
fwrite (image->data[i],
sizeof (sbmp_raw_data),
(uint32_t) image->info.image_width,
fd);
if (NULL != zero_pad)
fwrite (zero_pad, sizeof (uint8_t), padd_size, fd);
}
if (NULL != zero_pad)
free (zero_pad);
return SBMP_OK;
}
/**
* Load image from the disk in sbmp_image
* @param [in] filename File path to be load
* @param [out] image Not null pointer where image to be load
* @return begin SBMP_OK if all worked OK or SBMP_ERROR_FILE if you can't read the file
*/
enum sbmp_codes sbmp_load_bmp (const char *filename, sbmp_image *image)
{
FILE *fd = fopen (filename, "r");
if (fd == NULL)
{
fprintf (stderr, "Error: %s\n", strerror (errno));
return SBMP_ERROR_FILE;
}
fread (&image->type, sizeof (image->type), 1, fd);
fread (&image->info, sizeof (image->info), 1, fd);
image->data = calloc ((size_t) image->info.image_height, sizeof (sbmp_raw_data *));
if (image->data == NULL)
{
fprintf (stderr, "Error: %s\n", strerror (errno));
fclose (fd);
return SBMP_ERROR_FILE;
}
for (int32_t i = image->info.image_height - 1; i >= 0; i--)
{
image->data[i] = calloc ((size_t) image->info.image_width, sizeof (sbmp_raw_data));
fread (image->data[i],
sizeof (sbmp_raw_data),
(uint32_t) image->info.image_width, fd);
}
fclose (fd);
return SBMP_OK;
}
/**
* Release the pixel memory and clean scruct of the image
* @param [in] image
* @return
*/
enum sbmp_codes sbmp_free (sbmp_image *image)
{
if (NULL == image)
return SBMP_ERROR_PARAM;
for (int32_t i = 0; i < image->info.image_height; i++)
{
free (image->data[i]);
}
free (image->data);
image->info = (sbmp_iinfo_data) {0};
image->type = (sbmp_ftype_data) {0};
return SBMP_OK;
}