Skip to content

Commit f72532b

Browse files
authored
Merge pull request #127 from saxbophone/develop
v0.21.0 - Render Backends Refactor
2 parents 7444fb7 + d5d46b2 commit f72532b

File tree

8 files changed

+260
-11
lines changed

8 files changed

+260
-11
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
# begin basic metadata
2424
cmake_minimum_required(VERSION 3.0)
2525

26-
project(libsaxbospiral VERSION 0.20.1 LANGUAGES C)
26+
project(libsaxbospiral VERSION 0.21.0 LANGUAGES C)
2727

2828
# set default C standard to use (C99)
2929
set(SAXBOSPIRAL_C_STANDARD "99")

saxbospiral/render.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ static void get_bounds(sxbp_spiral_t spiral, sxbp_co_ord_t* bounds) {
8383
* - That image->pixels is NULL
8484
* - That spiral.lines is not NULL
8585
*/
86-
sxbp_status_t sxbp_render_spiral(sxbp_spiral_t spiral, sxbp_bitmap_t* image) {
86+
sxbp_status_t sxbp_render_spiral_raw(
87+
sxbp_spiral_t spiral, sxbp_bitmap_t* image
88+
) {
8789
// preconditional assertions
8890
assert(image->pixels == NULL);
8991
assert(spiral.lines != NULL);
@@ -159,6 +161,40 @@ sxbp_status_t sxbp_render_spiral(sxbp_spiral_t spiral, sxbp_bitmap_t* image) {
159161
return result;
160162
}
161163

164+
/*
165+
* given a spiral struct, a pointer to a blank buffer and a pointer to a
166+
* function with the appropriate signature, render the spiral as a bitmap and
167+
* then call the pointed-to function to render the image to the buffer (in
168+
* whatever format the function pointer is written for)
169+
* returns a status struct with error information (if any)
170+
*
171+
* Asserts:
172+
* - That spiral.lines is not NULL
173+
* - That buffer->bytes is NULL
174+
* - That the function pointer is not NULL
175+
*/
176+
sxbp_status_t sxbp_render_spiral_image(
177+
sxbp_spiral_t spiral, sxbp_buffer_t* buffer,
178+
sxbp_status_t(* image_writer_callback)(
179+
sxbp_bitmap_t image, sxbp_buffer_t* buffer
180+
)
181+
) {
182+
// preconditional assertions
183+
assert(spiral.lines != NULL);
184+
assert(buffer->bytes == NULL);
185+
assert(image_writer_callback != NULL);
186+
// create bitmap to render raw image to
187+
sxbp_bitmap_t raw_image = {0, 0, NULL};
188+
// render spiral to raw image (and store success/failure)
189+
sxbp_status_t result = sxbp_render_spiral_raw(spiral, &raw_image);
190+
// check return status
191+
if(result != SXBP_OPERATION_OK) {
192+
return result;
193+
}
194+
// render to buffer using callback (and return its status code)
195+
return image_writer_callback(raw_image, buffer);
196+
}
197+
162198
#ifdef __cplusplus
163199
} // extern "C"
164200
#endif

saxbospiral/render.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,28 @@ typedef struct sxbp_bitmap_t {
4848
* - That image->pixels is NULL
4949
* - That spiral.lines is not NULL
5050
*/
51-
sxbp_status_t sxbp_render_spiral(sxbp_spiral_t spiral, sxbp_bitmap_t* image);
51+
sxbp_status_t sxbp_render_spiral_raw(
52+
sxbp_spiral_t spiral, sxbp_bitmap_t* image
53+
);
54+
55+
/*
56+
* given a spiral struct, a pointer to a blank buffer and a pointer to a
57+
* function with the appropriate signature, render the spiral as a bitmap and
58+
* then call the pointed-to function to render the image to the buffer (in
59+
* whatever format the function pointer is written for)
60+
* returns a status struct with error information (if any)
61+
*
62+
* Asserts:
63+
* - That spiral.lines is not NULL
64+
* - That buffer->bytes is NULL
65+
* - That the function pointer is not NULL
66+
*/
67+
sxbp_status_t sxbp_render_spiral_image(
68+
sxbp_spiral_t spiral, sxbp_buffer_t* buffer,
69+
sxbp_status_t(* image_writer_callback)(
70+
sxbp_bitmap_t image, sxbp_buffer_t* buffer
71+
)
72+
);
5273

5374
#ifdef __cplusplus
5475
} // extern "C"
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* This source file forms part of libsaxbospiral, a library which generates
3+
* experimental 2D spiral-like shapes based on input binary data.
4+
*
5+
* This compilation unit provides functionality to render a bitmap struct to a
6+
* PBM image (binary version, stored in a buffer).
7+
*
8+
* Reference materials used for the PBM format are located at
9+
* <http://netpbm.sourceforge.net/doc/pbm.html>
10+
*
11+
*
12+
*
13+
* Copyright (C) 2016, Joshua Saxby [email protected]
14+
*
15+
* This program is free software: you can redistribute it and/or modify
16+
* it under the terms of the GNU Affero General Public License (version 3),
17+
* as published by the Free Software Foundation.
18+
*
19+
* This program is distributed in the hope that it will be useful,
20+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22+
* GNU Affero General Public License for more details.
23+
*
24+
* You should have received a copy of the GNU Affero General Public License
25+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
26+
*/
27+
#include <assert.h>
28+
#include <inttypes.h>
29+
#include <math.h>
30+
#include <stddef.h>
31+
#include <stdint.h>
32+
#include <stdio.h>
33+
#include <stdlib.h>
34+
#include <string.h>
35+
36+
#include "../saxbospiral.h"
37+
#include "../render.h"
38+
#include "backend_pbm.h"
39+
40+
41+
#ifdef __cplusplus
42+
extern "C"{
43+
#endif
44+
45+
/*
46+
* given a bitmap_t struct and a pointer to a blank buffer_t, write the bitmap
47+
* data as a PBM image to the buffer
48+
* returns a status struct containing error information, if any
49+
*
50+
* Asserts:
51+
* - That bitmap.pixels is not NULL
52+
* - That buffer->bytes is NULL
53+
*/
54+
sxbp_status_t sxbp_render_backend_pbm(
55+
sxbp_bitmap_t bitmap, sxbp_buffer_t* buffer
56+
) {
57+
// preconditional assertsions
58+
assert(bitmap.pixels != NULL);
59+
assert(buffer->bytes == NULL);
60+
/*
61+
* allocate two char arrays for the width and height strings - these may be
62+
* up to 19 characters each (max uint64_t is 19 digits long), so allocate 2
63+
* char arrays of 20 chars each (1 extra char for null-terminator)
64+
*/
65+
char width_string[20], height_string[20];
66+
// these are used to keep track of how many digits each is
67+
int width_string_length, height_string_length = 0;
68+
// convert width and height to a decimal string, store lengths
69+
width_string_length = sprintf(width_string, "%" PRIu64, bitmap.width);
70+
height_string_length = sprintf(height_string, "%" PRIu64, bitmap.height);
71+
/*
72+
* now that we know the length of the image dimension strings, we can now
73+
* calculate how much memory we'll have to allocate for the image buffer
74+
*/
75+
// calculate number of bytes per row - this is ceiling(width / 8)
76+
size_t bytes_per_row = (size_t)ceil((double)bitmap.width / 8.0);
77+
// calculate number of bytes for the entire image pixels (rows and columns)
78+
size_t image_bytes = bytes_per_row * bitmap.height;
79+
// finally put it all together to get total image buffer size
80+
size_t image_buffer_size = (
81+
3 // "P4" magic number + whitespace
82+
+ width_string_length + 1 // width of image in decimal + whitespace
83+
+ height_string_length + 1 // height of image in decimal + whitespace
84+
+ image_bytes // lastly, the bytes which make up the image pixels
85+
);
86+
// try and allocate the data for the buffer
87+
buffer->bytes = calloc(image_buffer_size, sizeof(uint8_t));
88+
// check fo memory allocation failure
89+
if(buffer->bytes == NULL) {
90+
return SXBP_MALLOC_REFUSED;
91+
} else {
92+
// set buffer size
93+
buffer->size = image_buffer_size;
94+
// otherwise carry on
95+
size_t index = 0; // this index is used to index the buffer
96+
// construct magic number + whitespace
97+
memcpy(buffer->bytes + index, "P4\n", 3);
98+
index += 3;
99+
// image width
100+
memcpy(buffer->bytes + index, width_string, width_string_length);
101+
index += width_string_length;
102+
// whitespace
103+
memcpy(buffer->bytes + index, "\n", 1);
104+
index += 1;
105+
// image height
106+
memcpy(buffer->bytes + index, height_string, height_string_length);
107+
index += height_string_length;
108+
// whitespace
109+
memcpy(buffer->bytes + index, "\n", 1);
110+
index += 1;
111+
// now for the image data, packed into rows to the nearest byte
112+
for(size_t y = 0; y < bitmap.height; y++) { // row loop
113+
for(size_t x = 0; x < bitmap.width; x++) {
114+
// byte index is index + floor(x / 8)
115+
size_t byte_index = index + (x / 8);
116+
// bit index is x mod 8
117+
uint8_t bit_index = x % 8;
118+
// write bits most-significant-bit first
119+
buffer->bytes[byte_index] |= (
120+
// black pixel = bool true = 1, just like in PBM format
121+
bitmap.pixels[x][y] << (7 - bit_index)
122+
);
123+
}
124+
// increment index so next row is written in the correct place
125+
index += bytes_per_row;
126+
}
127+
return SXBP_OPERATION_OK;
128+
}
129+
}
130+
131+
#ifdef __cplusplus
132+
} // extern "C"
133+
#endif
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* This source file forms part of libsaxbospiral, a library which generates
3+
* experimental 2D spiral-like shapes based on input binary data.
4+
*
5+
* This compilation unit provides functionality to render a bitmap struct to a
6+
* PBM image (binary version, stored in a buffer).
7+
*
8+
* Reference materials used for the PBM format are located at
9+
* <http://netpbm.sourceforge.net/doc/pbm.html>
10+
*
11+
*
12+
*
13+
* Copyright (C) 2016, Joshua Saxby [email protected]
14+
*
15+
* This program is free software: you can redistribute it and/or modify
16+
* it under the terms of the GNU Affero General Public License (version 3),
17+
* as published by the Free Software Foundation.
18+
*
19+
* This program is distributed in the hope that it will be useful,
20+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22+
* GNU Affero General Public License for more details.
23+
*
24+
* You should have received a copy of the GNU Affero General Public License
25+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
26+
*/
27+
#ifndef SAXBOPHONE_SAXBOSPIRAL_BACKEND_PBM_H
28+
#define SAXBOPHONE_SAXBOSPIRAL_BACKEND_PBM_H
29+
30+
#include "../saxbospiral.h"
31+
#include "../render.h"
32+
33+
34+
#ifdef __cplusplus
35+
extern "C"{
36+
#endif
37+
38+
/*
39+
* given a bitmap_t struct and a pointer to a blank buffer_t, write the bitmap
40+
* data as a PBM image to the buffer
41+
* returns a status struct containing error information, if any
42+
*
43+
* Asserts:
44+
* - That bitmap.pixels is not NULL
45+
* - That buffer->bytes is NULL
46+
*/
47+
sxbp_status_t sxbp_render_backend_pbm(
48+
sxbp_bitmap_t bitmap, sxbp_buffer_t* buffer
49+
);
50+
51+
#ifdef __cplusplus
52+
} // extern "C"
53+
#endif
54+
55+
// end of header file
56+
#endif

saxbospiral/render_backends/png_backend.c renamed to saxbospiral/render_backends/backend_png.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
* This source file forms part of libsaxbospiral, a library which generates
33
* experimental 2D spiral-like shapes based on input binary data.
44
*
5-
* This compilation unit provides functionality to render a bitmap struct to PNG
5+
* This compilation unit provides functionality to render a bitmap struct to a
6+
* PNG image (stored in a buffer).
67
*
78
*
89
*
@@ -28,7 +29,7 @@
2829

2930
#include "../saxbospiral.h"
3031
#include "../render.h"
31-
#include "png_backend.h"
32+
#include "backend_png.h"
3233

3334

3435
#ifdef __cplusplus
@@ -89,7 +90,7 @@ static void cleanup_png_lib(
8990
* - That bitmap.pixels is not NULL
9091
* - That buffer->bytes is NULL
9192
*/
92-
sxbp_status_t sxbp_write_png_image(
93+
sxbp_status_t sxbp_render_backend_png(
9394
sxbp_bitmap_t bitmap, sxbp_buffer_t* buffer
9495
) {
9596
// preconditional assertsions

saxbospiral/render_backends/png_backend.h renamed to saxbospiral/render_backends/backend_png.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
* This source file forms part of libsaxbospiral, a library which generates
33
* experimental 2D spiral-like shapes based on input binary data.
44
*
5-
* This compilation unit provides functionality to render a bitmap struct to PNG
5+
* This compilation unit provides functionality to render a bitmap struct to a
6+
* PNG image (stored in a buffer).
67
*
78
*
89
*
@@ -20,8 +21,8 @@
2021
* You should have received a copy of the GNU Affero General Public License
2122
* along with this program. If not, see <http://www.gnu.org/licenses/>.
2223
*/
23-
#ifndef SAXBOPHONE_SAXBOSPIRAL_PNG_BACKEND_H
24-
#define SAXBOPHONE_SAXBOSPIRAL_PNG_BACKEND_H
24+
#ifndef SAXBOPHONE_SAXBOSPIRAL_BACKEND_PNG_H
25+
#define SAXBOPHONE_SAXBOSPIRAL_BACKEND_PNG_H
2526

2627
#include "../saxbospiral.h"
2728
#include "../render.h"
@@ -40,7 +41,9 @@ extern "C"{
4041
* - That bitmap.pixels is not NULL
4142
* - That buffer->bytes is NULL
4243
*/
43-
sxbp_status_t sxbp_write_png_image(sxbp_bitmap_t bitmap, sxbp_buffer_t* buffer);
44+
sxbp_status_t sxbp_render_backend_png(
45+
sxbp_bitmap_t bitmap, sxbp_buffer_t* buffer
46+
);
4447

4548
#ifdef __cplusplus
4649
} // extern "C"

saxbospiral/solve.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include <stdbool.h>
2727
#include <stddef.h>
2828
#include <stdint.h>
29-
#include <stdio.h>
3029

3130
#include "saxbospiral.h"
3231
#include "plot.h"

0 commit comments

Comments
 (0)