1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 *
1616 */
17-
1817#include < cstdio>
1918#include < cstring>
2019#include < memory>
2120#include < inttypes.h>
2221
2322#include " grok.h"
24-
2523#include " core.h"
2624
27- struct WriteStreamInfo
25+ /* *
26+ * @struct WriteCallbackInfo
27+ * @brief used by write callbacks to get information about stream
28+ *
29+ */
30+ struct WriteCallbackInfo
2831{
29- explicit WriteStreamInfo (grk_stream_params* streamParams)
32+ explicit WriteCallbackInfo (grk_stream_params* streamParams)
3033 : streamParams_(streamParams), data_(nullptr ), dataLen_(0 ), offset_(0 )
3134 {}
3235 grk_stream_params* streamParams_;
@@ -35,17 +38,33 @@ struct WriteStreamInfo
3538 size_t offset_;
3639};
3740
41+ /* *
42+ * @brief stream write callback
43+ *
44+ * @param buffer //buffer of data to write
45+ * @param numBytes // number of bytes to write
46+ * @param user_data // user data
47+ * @return size_t // number of bytes written
48+ */
3849size_t stream_write_fn (const uint8_t * buffer, size_t numBytes, void * user_data)
3950{
40- auto sinfo = (WriteStreamInfo *)user_data;
51+ auto sinfo = (WriteCallbackInfo *)user_data;
4152 if (sinfo->offset_ + numBytes <= sinfo->dataLen_ )
4253 memcpy (sinfo->data_ + sinfo->offset_ , buffer, numBytes);
4354
4455 return numBytes;
4556}
57+
58+ /* *
59+ * @brief stream seek callback
60+ *
61+ * @param offset //offset to seek to
62+ * @param user_data // user dat
63+ * @return true if seek successful, otherwise false
64+ */
4665bool stream_seek_fn (uint64_t offset, void * user_data)
4766{
48- auto sinfo = (WriteStreamInfo *)user_data;
67+ auto sinfo = (WriteCallbackInfo *)user_data;
4968 if (offset <= sinfo->dataLen_ )
5069 sinfo->offset_ = offset;
5170 else
@@ -62,52 +81,58 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] const char** argv)
6281 const uint32_t precision = 8 ;
6382 const char * outFile = " test.jp2" ;
6483
84+ grk_object* codec = nullptr ;
85+ grk_image* inputImage = nullptr ;
86+ int32_t rc = EXIT_FAILURE;
87+
6588 uint64_t compressedLength = 0 ;
6689
67- // initialize compress parameters
90+ // 1. initialize library
91+ grk_initialize (nullptr , 0 );
92+
93+ // 2. initialize compress parameters
6894 grk_cparameters compressParams;
6995 grk_compress_set_default_params (&compressParams);
7096 compressParams.cod_format = GRK_FMT_JP2;
7197 compressParams.verbose = true ;
7298
73- grk_object* codec = nullptr ;
74- grk_image* image = nullptr ;
75- int32_t rc = EXIT_FAILURE;
76-
77- bool outputToBuffer = false ;
78- bool useCallbacks = true ;
79-
80- // initialize library
81- grk_initialize (nullptr , 0 );
99+ // 3.initialize output stream
100+ enum eStreamOutput
101+ {
102+ STREAM_OUTPUT_BUFFER, // output to buffer
103+ STREAM_OUTPUT_CALLBACK, // output using user-defined callback
104+ STREAM_OUTPUT_FILE // output to file
105+ };
106+ eStreamOutput output = STREAM_OUTPUT_BUFFER;
82107
83- grk_stream_params streamParams = {};
84- WriteStreamInfo sinfo (&streamParams );
108+ grk_stream_params outputStreamParams = {};
109+ WriteCallbackInfo writeCallbackInfo (&outputStreamParams );
85110
86111 std::unique_ptr<uint8_t []> data;
87112 size_t bufLen = (size_t )numComps * ((precision + 7 ) / 8 ) * dimX * dimY;
88- if (useCallbacks || outputToBuffer )
113+ if (output != STREAM_OUTPUT_FILE )
89114 {
90115 data = std::make_unique<uint8_t []>(bufLen);
91116 }
92- if (useCallbacks )
117+ if (output == STREAM_OUTPUT_CALLBACK )
93118 {
94- streamParams .seek_fn = stream_seek_fn;
95- streamParams .write_fn = stream_write_fn;
96- streamParams .user_data = &sinfo ;
97- sinfo .data_ = data.get ();
98- sinfo .dataLen_ = bufLen;
119+ outputStreamParams .seek_fn = stream_seek_fn;
120+ outputStreamParams .write_fn = stream_write_fn;
121+ outputStreamParams .user_data = &writeCallbackInfo ;
122+ writeCallbackInfo .data_ = data.get ();
123+ writeCallbackInfo .dataLen_ = bufLen;
99124 }
100- else if (outputToBuffer )
125+ else if (output == STREAM_OUTPUT_BUFFER )
101126 {
102- streamParams .buf = data.get ();
103- streamParams .buf_len = bufLen;
127+ outputStreamParams .buf = data.get ();
128+ outputStreamParams .buf_len = bufLen;
104129 }
105130 else
106131 {
107- safe_strcpy (streamParams .file , outFile);
132+ safe_strcpy (outputStreamParams .file , outFile);
108133 }
109134
110- // create blank image
135+ // 4. create input image (blank)
111136 auto components = std::make_unique<grk_image_comp[]>(numComps);
112137 for (uint32_t i = 0 ; i < numComps; ++i)
113138 {
@@ -119,13 +144,12 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] const char** argv)
119144 c->prec = precision;
120145 c->sgnd = false ;
121146 }
122- image = grk_image_new (numComps, components.get (), GRK_CLRSPC_SRGB, true );
147+ inputImage = grk_image_new (numComps, components.get (), GRK_CLRSPC_SRGB, true );
123148
124- // fill in component data
125- // see grok.h header for full details of image structure
126- for (uint16_t compno = 0 ; compno < image->numcomps ; ++compno)
149+ // fill in component data: see grok.h header for full details of image structure
150+ for (uint16_t compno = 0 ; compno < inputImage->numcomps ; ++compno)
127151 {
128- auto comp = image ->comps + compno;
152+ auto comp = inputImage ->comps + compno;
129153 auto compWidth = comp->w ;
130154 auto compHeight = comp->h ;
131155 auto compData = (int32_t *)comp->data ;
@@ -148,26 +172,25 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] const char** argv)
148172 delete[] srcData;
149173 }
150174
151- // initialize compressor
152- codec = grk_compress_init (&streamParams , &compressParams, image );
175+ // 5. initialize compressor
176+ codec = grk_compress_init (&outputStreamParams , &compressParams, inputImage );
153177 if (!codec)
154178 {
155179 fprintf (stderr, " Failed to initialize compressor\n " );
156180 goto beach;
157181 }
158182
159- // compress
183+ // 6. compress
160184 compressedLength = grk_compress (codec, nullptr );
161185 if (compressedLength == 0 )
162186 {
163187 fprintf (stderr, " Failed to compress\n " );
164188 goto beach;
165189 }
166-
167190 printf (" Compression succeeded: %" PRIu64 " bytes used.\n " , compressedLength);
168191
169- // write buffer to file
170- if (outputToBuffer )
192+ // 7. write buffer to file if needed
193+ if (output == STREAM_OUTPUT_FILE )
171194 {
172195 auto fp = fopen (outFile, " wb" );
173196 if (!fp)
@@ -176,7 +199,7 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] const char** argv)
176199 }
177200 else
178201 {
179- size_t written = fwrite (streamParams .buf , 1 , compressedLength, fp);
202+ size_t written = fwrite (outputStreamParams .buf , 1 , compressedLength, fp);
180203 if (written != compressedLength)
181204 {
182205 fprintf (stderr, " Buffer compress: only %" PRIu64 " bytes written out of %" PRIu64 " total" ,
@@ -188,9 +211,10 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] const char** argv)
188211
189212 rc = EXIT_SUCCESS;
190213beach:
214+
191215 // cleanup
192216 grk_object_unref (codec);
193- grk_object_unref (&image ->obj );
217+ grk_object_unref (&inputImage ->obj );
194218 grk_deinitialize ();
195219
196220 return rc;
0 commit comments