-
Notifications
You must be signed in to change notification settings - Fork 0
/
image.c
155 lines (118 loc) · 3.07 KB
/
image.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
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <SDL/SDL.h>
#include "imgproc.h"
Image * imgNew(unsigned int width, unsigned int height)
{
// Allocate for the image container
Image * img = malloc(sizeof(*img));
if(img == NULL){
fprintf(stderr, "Failed to allocate memory for image container\n");
return NULL;
}
// Set the width and height
img->width = width;
img->height = height;
// allocate for image data, 3 byte per pixel, aligned to an 8 byte boundary
img->mem_ptr = malloc(img->width * img->height * 3 + 8);
if(img->mem_ptr == NULL){
fprintf(stderr, "Memory allocation of image data failed\n");
free(img);
return NULL;
}
// make certain it is aligned to 8 bytes
unsigned int remainder = ((size_t)img->mem_ptr) % 8;
if(remainder == 0){
img->data = img->mem_ptr;
} else {
img->data = img->mem_ptr + (8 - remainder);
}
// Fill the SDL_Surface container
img->sdl_surface = SDL_CreateRGBSurfaceFrom(
img->data,
img->width,
img->height,
24,
img->width * 3,
0xff0000,
0x00ff00,
0x0000ff,
0x000000
);
// check the surface was initialised
if(img->sdl_surface == NULL){
fprintf(stderr, "Failed to initialise RGB surface from pixel data\n");
SDL_FreeSurface(img->sdl_surface);
free(img->mem_ptr);
free(img);
return NULL;
}
// return the image
return img;
}
Image * imgFromBitmap(const char * filename)
{
// Load the Bitmap
SDL_Surface * bitmap = SDL_LoadBMP(filename);
// Allocate for the image container
Image * img = malloc(sizeof(*img));
if(img == NULL){
fprintf(stderr, "Failed to allocate memory for image container\n");
return NULL;
}
// set the image surface to the bitmap
img->sdl_surface = bitmap;
// Set the width and height
img->width = bitmap->w;
img->height = bitmap->h;
// set the data pointer
img->data = bitmap->pixels;
// set the memory pointer to NULL, so we don't cause mayhem trying to free it
img->mem_ptr = NULL;
// return the new image
return img;
}
Image * imgCopy(Image * img)
{
// Create a new empty image
Image * copy = imgNew(img->width, img->height);
// Copy the data between the images
copy = memcpy(copy->data, img->data, img->width * img->height * 3 );
// return the copy
return copy;
}
unsigned int imgGetWidth(Image * img)
{
return img->width;
}
unsigned int imgGetHeight(Image * img)
{
return img->height;
}
void imgSetPixel(Image * img, unsigned int x, unsigned int y, char r, char g, char b)
{
// calculate the offset into the image array
uint32_t offset = 3 * (x + (y * img->width));
// set the rgb value
img->data[offset + 2] = b;
img->data[offset + 1] = g;
img->data[offset + 0] = r;
}
// returns a pointer to the rgb tuple
char * imgGetPixel(Image * img, unsigned int x, unsigned int y)
{
uint32_t offset = 3 * (x + (y * img->width));
return (char *)(img->data + offset);
}
// Destroys the image
void imgDestroy(Image * img)
{
// Free the SDL surface
SDL_FreeSurface(img->sdl_surface);
if(img->mem_ptr != NULL){
free(img->mem_ptr);
}
// Free the image container, Python will handle the memoryview + buffer
free(img);
}