Skip to content

Commit 8736d1f

Browse files
committed
Supports odd dimensions images
1 parent 746f83b commit 8736d1f

File tree

1 file changed

+38
-21
lines changed

1 file changed

+38
-21
lines changed

SDWebImageAVIFCoder/Classes/SDImageAVIFCoder.m

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ static void ConvertAvifImagePlanar8ToRGB8(avifImage * avif, uint8_t * outPixels)
141141
vImage_Buffer origCb = {
142142
.data = avif->yuvPlanes[AVIF_CHAN_U],
143143
.rowBytes = avif->yuvRowBytes[AVIF_CHAN_U],
144-
.width = avif->width >> state.formatInfo.chromaShiftX,
145-
.height = avif->height >> state.formatInfo.chromaShiftY,
144+
.width = (avif->width+state.formatInfo.chromaShiftX) >> state.formatInfo.chromaShiftX,
145+
.height = (avif->height+state.formatInfo.chromaShiftY) >> state.formatInfo.chromaShiftY,
146146
};
147147

148148
if(!origCb.data) { // allocate dummy data to convert monochrome images.
@@ -159,8 +159,8 @@ static void ConvertAvifImagePlanar8ToRGB8(avifImage * avif, uint8_t * outPixels)
159159
vImage_Buffer origCr = {
160160
.data = avif->yuvPlanes[AVIF_CHAN_V],
161161
.rowBytes = avif->yuvRowBytes[AVIF_CHAN_V],
162-
.width = avif->width >> state.formatInfo.chromaShiftX,
163-
.height = avif->height >> state.formatInfo.chromaShiftY,
162+
.width = (avif->width+state.formatInfo.chromaShiftX) >> state.formatInfo.chromaShiftX,
163+
.height = (avif->height+state.formatInfo.chromaShiftY) >> state.formatInfo.chromaShiftY,
164164
};
165165
if(!origCr.data) { // allocate dummy data to convert monochrome images.
166166
dummyCr = calloc(origCr.width, sizeof(uint8_t));
@@ -282,23 +282,38 @@ static void ConvertAvifImagePlanar8ToRGB8(avifImage * avif, uint8_t * outPixels)
282282
return;
283283
}
284284

285+
((uint8_t*)origY.data)[origY.rowBytes * (origY.height-1) + origY.width ] = 255;
286+
const vImagePixelCount alignedWidth = (origY.width+1) & (~1);
285287
vImage_Buffer tmpY1 = {
286-
.data = calloc(origY.width/2 * origY.height, sizeof(uint8_t)),
287-
.width = origY.width/2,
288+
.data = calloc(alignedWidth/2 * origY.height, sizeof(uint8_t)),
289+
.width = alignedWidth/2,
288290
.height = origY.height,
289-
.rowBytes = origY.width/2 * sizeof(uint8_t),
291+
.rowBytes = alignedWidth/2 * sizeof(uint8_t),
290292
};
291293
if(!tmpY1.data) {
292294
free(argbPixels);
293295
free(dummyCb);
294296
free(dummyCr);
295297
return;
296298
}
299+
err = vImageConvert_ChunkyToPlanar8((const void*[]){origY.data},
300+
(const vImage_Buffer*[]){&tmpY1},
301+
1 /* channelCount */, 2 /* src srcStrideBytes */,
302+
alignedWidth/2, origY.height,
303+
origY.rowBytes, kvImageNoFlags);
304+
if(err != kvImageNoError) {
305+
NSLog(@"Failed to separate first Y channel: %ld", err);
306+
free(argbPixels);
307+
free(dummyCb);
308+
free(dummyCr);
309+
free(tmpY1.data);
310+
return;
311+
}
297312
vImage_Buffer tmpY2 = {
298-
.data = calloc(origY.width/2 * origY.height, sizeof(uint8_t)),
299-
.width = origY.width/2,
313+
.data = calloc(alignedWidth/2 * origY.height, sizeof(uint8_t)),
314+
.width = alignedWidth/2,
300315
.height = origY.height,
301-
.rowBytes = origY.width/2 * sizeof(uint8_t),
316+
.rowBytes = alignedWidth/2 * sizeof(uint8_t),
302317
};
303318
if(!tmpY2.data) {
304319
free(argbPixels);
@@ -307,13 +322,15 @@ static void ConvertAvifImagePlanar8ToRGB8(avifImage * avif, uint8_t * outPixels)
307322
free(tmpY1.data);
308323
return;
309324
}
310-
err= vImageConvert_ChunkyToPlanar8((const void*[]){origY.data, origY.data+1},
311-
(const vImage_Buffer*[]){&tmpY1, &tmpY2},
312-
2 /* channelCount */,2 /* src srcStrideBytes */,
325+
tmpY2.width = origY.width/2;
326+
err = vImageConvert_ChunkyToPlanar8((const void*[]){origY.data + 1},
327+
(const vImage_Buffer*[]){&tmpY2},
328+
1 /* channelCount */, 2 /* src srcStrideBytes */,
313329
origY.width/2, origY.height,
314330
origY.rowBytes, kvImageNoFlags);
331+
tmpY2.width = alignedWidth/2;
315332
if(err != kvImageNoError) {
316-
NSLog(@"Failed to separate Y channel: %ld", err);
333+
NSLog(@"Failed to separate second Y channel: %ld", err);
317334
free(argbPixels);
318335
free(dummyCb);
319336
free(dummyCr);
@@ -322,10 +339,10 @@ static void ConvertAvifImagePlanar8ToRGB8(avifImage * avif, uint8_t * outPixels)
322339
return;
323340
}
324341
vImage_Buffer tmpBuffer = {
325-
.data = calloc(avif->width * avif->height * 2, sizeof(uint8_t)),
326-
.width = avif->width/2,
342+
.data = calloc(alignedWidth * avif->height * 2, sizeof(uint8_t)),
343+
.width = alignedWidth/2,
327344
.height = avif->height,
328-
.rowBytes = avif->width / 2 * 4 * sizeof(uint8_t),
345+
.rowBytes = alignedWidth / 2 * 4 * sizeof(uint8_t),
329346
};
330347
if(!tmpBuffer.data) {
331348
free(argbPixels);
@@ -437,8 +454,8 @@ static void ConvertAvifImagePlanar16ToRGB16U(avifImage * avif, uint8_t * outPixe
437454
vImage_Buffer origCb = {
438455
.data = avif->yuvPlanes[AVIF_CHAN_U],
439456
.rowBytes = avif->yuvRowBytes[AVIF_CHAN_U],
440-
.width = avif->width >> state.formatInfo.chromaShiftX,
441-
.height = avif->height >> state.formatInfo.chromaShiftY,
457+
.width = (avif->width+state.formatInfo.chromaShiftX) >> state.formatInfo.chromaShiftX,
458+
.height = (avif->height+state.formatInfo.chromaShiftY) >> state.formatInfo.chromaShiftY,
442459
};
443460

444461
if(!origCb.data) { // allocate dummy data to convert monochrome images.
@@ -465,8 +482,8 @@ static void ConvertAvifImagePlanar16ToRGB16U(avifImage * avif, uint8_t * outPixe
465482
vImage_Buffer origCr = {
466483
.data = avif->yuvPlanes[AVIF_CHAN_V],
467484
.rowBytes = avif->yuvRowBytes[AVIF_CHAN_V],
468-
.width = avif->width >> state.formatInfo.chromaShiftX,
469-
.height = avif->height >> state.formatInfo.chromaShiftY,
485+
.width = (avif->width+state.formatInfo.chromaShiftX) >> state.formatInfo.chromaShiftX,
486+
.height = (avif->height+state.formatInfo.chromaShiftY) >> state.formatInfo.chromaShiftY,
470487
};
471488

472489
if(!origCr.data) { // allocate dummy data to convert monochrome images.

0 commit comments

Comments
 (0)