@@ -150,6 +150,11 @@ static avifBool isAvifError(avifResult result, const char *msg) {
150
150
}
151
151
152
152
153
+ typedef struct avifIOCtxReader {
154
+ avifIO io ; // this must be the first member for easy casting to avifIO*
155
+ avifROData rodata ;
156
+ } avifIOCtxReader ;
157
+
153
158
/*
154
159
<readfromCtx> implements the avifIOReadFunc interface by calling the relevant functions
155
160
in the gdIOCtx. Our logic is inspired by avifIOMemoryReaderRead() and avifIOFileReaderRead().
@@ -165,8 +170,8 @@ static avifBool isAvifError(avifResult result, const char *msg) {
165
170
*/
166
171
static avifResult readFromCtx (avifIO * io , uint32_t readFlags , uint64_t offset , size_t size , avifROData * out )
167
172
{
168
- void * dataBuf = NULL ;
169
173
gdIOCtx * ctx = (gdIOCtx * ) io -> data ;
174
+ avifIOCtxReader * reader = (avifIOCtxReader * ) io ;
170
175
171
176
// readFlags is unsupported
172
177
if (readFlags != 0 ) {
@@ -182,28 +187,34 @@ static avifResult readFromCtx(avifIO *io, uint32_t readFlags, uint64_t offset, s
182
187
if (!ctx -> seek (ctx , (int ) offset ))
183
188
return AVIF_RESULT_IO_ERROR ;
184
189
185
- dataBuf = avifAlloc (size );
186
- if (!dataBuf ) {
190
+ if (size > reader -> rodata .size ) {
191
+ reader -> rodata .data = gdRealloc ((void * ) reader -> rodata .data , size );
192
+ reader -> rodata .size = size ;
193
+ }
194
+ if (!reader -> rodata .data ) {
187
195
gd_error ("avif error - couldn't allocate memory" );
188
196
return AVIF_RESULT_UNKNOWN_ERROR ;
189
197
}
190
198
191
199
// Read the number of bytes requested.
192
200
// If getBuf() returns a negative value, that means there was an error.
193
- int charsRead = ctx -> getBuf (ctx , dataBuf , (int ) size );
201
+ int charsRead = ctx -> getBuf (ctx , ( void * ) reader -> rodata . data , (int ) size );
194
202
if (charsRead < 0 ) {
195
- avifFree (dataBuf );
196
203
return AVIF_RESULT_IO_ERROR ;
197
204
}
198
205
199
- out -> data = dataBuf ;
206
+ out -> data = reader -> rodata . data ;
200
207
out -> size = charsRead ;
201
208
return AVIF_RESULT_OK ;
202
209
}
203
210
204
211
// avif.h says this is optional, but it seemed easy to implement.
205
212
static void destroyAvifIO (struct avifIO * io ) {
206
- gdFree (io );
213
+ avifIOCtxReader * reader = (avifIOCtxReader * ) io ;
214
+ if (reader -> rodata .data != NULL ) {
215
+ gdFree ((void * ) reader -> rodata .data );
216
+ }
217
+ gdFree (reader );
207
218
}
208
219
209
220
/* Set up an avifIO object.
@@ -217,21 +228,23 @@ static void destroyAvifIO(struct avifIO *io) {
217
228
218
229
// TODO: can we get sizeHint somehow?
219
230
static avifIO * createAvifIOFromCtx (gdIOCtx * ctx ) {
220
- avifIO * io ;
231
+ struct avifIOCtxReader * reader ;
221
232
222
- io = gdMalloc (sizeof (* io ));
223
- if (io == NULL )
233
+ reader = gdMalloc (sizeof (* reader ));
234
+ if (reader == NULL )
224
235
return NULL ;
225
236
226
237
// TODO: setting persistent=FALSE is safe, but it's less efficient. Is it necessary?
227
- io -> persistent = AVIF_FALSE ;
228
- io -> read = readFromCtx ;
229
- io -> write = NULL ; // this function is currently unused; see avif.h
230
- io -> destroy = destroyAvifIO ;
231
- io -> sizeHint = 0 ; // sadly, we don't get this information from the gdIOCtx.
232
- io -> data = ctx ;
233
-
234
- return io ;
238
+ reader -> io .persistent = AVIF_FALSE ;
239
+ reader -> io .read = readFromCtx ;
240
+ reader -> io .write = NULL ; // this function is currently unused; see avif.h
241
+ reader -> io .destroy = destroyAvifIO ;
242
+ reader -> io .sizeHint = 0 ; // sadly, we don't get this information from the gdIOCtx.
243
+ reader -> io .data = ctx ;
244
+ reader -> rodata .data = NULL ;
245
+ reader -> rodata .size = 0 ;
246
+
247
+ return (avifIO * ) reader ;
235
248
}
236
249
237
250
@@ -576,6 +589,9 @@ void gdImageAvifCtx(gdImagePtr im, gdIOCtx *outfile, int quality, int speed)
576
589
577
590
if (avifOutput .data )
578
591
avifRWDataFree (& avifOutput );
592
+
593
+ if (avifIm )
594
+ avifImageDestroy (avifIm );
579
595
}
580
596
581
597
void gdImageAvifEx (gdImagePtr im , FILE * outFile , int quality , int speed )
0 commit comments