new space utilization strategy

pull/2/head
cosmonaut 2022-07-26 12:17:02 -07:00
parent e9452a7aef
commit b0265a0372
1 changed files with 51 additions and 21 deletions

View File

@ -35,6 +35,7 @@
#define INITIAL_DATA_CAPACITY 8 #define INITIAL_DATA_CAPACITY 8
#define INITIAL_FREE_RECTANGLE_CAPACITY 16 #define INITIAL_FREE_RECTANGLE_CAPACITY 16
#define INITIAL_DIMENSION 256
/* Structures */ /* Structures */
@ -60,8 +61,6 @@ struct Cram_Image
typedef struct Cram_Internal_Context typedef struct Cram_Internal_Context
{ {
char *name; char *name;
int32_t width;
int32_t height;
int32_t padding; int32_t padding;
uint8_t trim; uint8_t trim;
@ -74,6 +73,11 @@ typedef struct Cram_Internal_Context
Cram_ImageData *imageDatas; Cram_ImageData *imageDatas;
int32_t imageDataCount; int32_t imageDataCount;
int32_t maxDimension;
int32_t packedWidth;
int32_t packedHeight;
} Cram_Internal_Context; } Cram_Internal_Context;
typedef struct RectPackContext typedef struct RectPackContext
@ -199,7 +203,7 @@ static int8_t Cram_Internal_CopyPixels(
/* Packing functions */ /* Packing functions */
RectPackContext* Cram_Internal_InitRectPacker(uint32_t width, uint32_t height) RectPackContext* Cram_Internal_InitRectPacker(int32_t width, int32_t height)
{ {
RectPackContext *context = malloc(sizeof(RectPackContext)); RectPackContext *context = malloc(sizeof(RectPackContext));
@ -476,9 +480,6 @@ Cram_Context* Cram_Init(Cram_ContextCreateInfo *createInfo)
context->name = strdup(createInfo->name); context->name = strdup(createInfo->name);
context->width = createInfo->maxDimension;
context->height = createInfo->maxDimension;
context->padding = createInfo->padding; context->padding = createInfo->padding;
context->trim = createInfo->trim; context->trim = createInfo->trim;
@ -490,6 +491,11 @@ Cram_Context* Cram_Init(Cram_ContextCreateInfo *createInfo)
context->imageDatas = NULL; context->imageDatas = NULL;
context->imageDataCount = 0; context->imageDataCount = 0;
context->packedWidth = 0;
context->packedHeight = 0;
context->maxDimension = createInfo->maxDimension;
return (Cram_Context*) context; return (Cram_Context*) context;
} }
@ -632,20 +638,18 @@ int8_t Cram_Pack(Cram_Context *context)
{ {
RectPackContext *rectPackContext; RectPackContext *rectPackContext;
Cram_Internal_Context *internalContext = (Cram_Internal_Context*) context; Cram_Internal_Context *internalContext = (Cram_Internal_Context*) context;
uint32_t numNodes = internalContext->width;
Rect *packerRects; Rect *packerRects;
uint32_t numRects = 0; uint32_t numRects = 0;
Rect *packerRect; Rect *packerRect;
Rect dstRect, srcRect; Rect dstRect, srcRect;
Cram_Image *image; Cram_Image *image;
int32_t maxWidth = 0; uint8_t increaseX = 1;
int32_t maxHeight = 0;
int32_t i; int32_t i;
internalContext->imageDataCount = internalContext->imageCount; internalContext->imageDataCount = internalContext->imageCount;
internalContext->imageDatas = realloc(internalContext->imageDatas, sizeof(Cram_ImageData) * internalContext->imageDataCount); internalContext->imageDatas = realloc(internalContext->imageDatas, sizeof(Cram_ImageData) * internalContext->imageDataCount);
rectPackContext = Cram_Internal_InitRectPacker(internalContext->width, internalContext->height); rectPackContext = Cram_Internal_InitRectPacker(INITIAL_DIMENSION, INITIAL_DIMENSION);
for (i = 0; i < internalContext->imageCount; i += 1) for (i = 0; i < internalContext->imageCount; i += 1)
{ {
@ -671,8 +675,37 @@ int8_t Cram_Pack(Cram_Context *context)
} }
} }
if (Cram_Internal_PackRects(rectPackContext, packerRects, numRects) < 0) /* If packing fails, increase a dimension by power of 2 and retry until we hit max dimensions. */
while (Cram_Internal_PackRects(rectPackContext, packerRects, numRects) < 0)
{ {
if (increaseX)
{
rectPackContext->width *= 2;
increaseX = 0;
}
else
{
rectPackContext->height *= 2;
increaseX = 1;
}
rectPackContext->freeRectangles[0].x = 0;
rectPackContext->freeRectangles[0].y = 0;
rectPackContext->freeRectangles[0].w = rectPackContext->width;
rectPackContext->freeRectangles[0].h = rectPackContext->height;
rectPackContext->freeRectangleCount = 1;
rectPackContext->newFreeRectangleCount = 0;
if (rectPackContext->width > internalContext->maxDimension || rectPackContext->height > internalContext->maxDimension)
{
break;
}
}
if (rectPackContext->width > internalContext->maxDimension || rectPackContext->height > internalContext->maxDimension)
{
/* Can't pack into max dimensions, abort! */
return -1; return -1;
} }
@ -688,18 +721,15 @@ int8_t Cram_Pack(Cram_Context *context)
internalContext->images[i]->packedRect.w = internalContext->images[i]->trimmedRect.w; internalContext->images[i]->packedRect.w = internalContext->images[i]->trimmedRect.w;
internalContext->images[i]->packedRect.h = internalContext->images[i]->trimmedRect.h; internalContext->images[i]->packedRect.h = internalContext->images[i]->trimmedRect.h;
maxWidth = max(maxWidth, packerRect->x + packerRect->w);
maxHeight = max(maxHeight, packerRect->y + packerRect->h);
numRects += 1; numRects += 1;
} }
} }
internalContext->width = Cram_Internal_NextPowerOfTwo(maxWidth); internalContext->packedWidth = rectPackContext->width;
internalContext->height = Cram_Internal_NextPowerOfTwo(maxHeight); internalContext->packedHeight = rectPackContext->height;
internalContext->pixels = realloc(internalContext->pixels, internalContext->width * internalContext->height * 4); internalContext->pixels = realloc(internalContext->pixels, internalContext->packedWidth * internalContext->packedHeight * 4);
memset(internalContext->pixels, 0, internalContext->width * internalContext->height * 4); memset(internalContext->pixels, 0, internalContext->packedWidth * internalContext->packedHeight * 4);
for (i = 0; i < internalContext->imageCount; i += 1) for (i = 0; i < internalContext->imageCount; i += 1)
{ {
@ -717,7 +747,7 @@ int8_t Cram_Pack(Cram_Context *context)
Cram_Internal_CopyPixels( Cram_Internal_CopyPixels(
(uint32_t*) internalContext->pixels, (uint32_t*) internalContext->pixels,
internalContext->width, internalContext->packedWidth,
(uint32_t*) internalContext->images[i]->pixels, (uint32_t*) internalContext->images[i]->pixels,
internalContext->images[i]->trimmedRect.w, internalContext->images[i]->trimmedRect.w,
&dstRect, &dstRect,
@ -756,8 +786,8 @@ void Cram_GetPixelData(Cram_Context *context, uint8_t **pPixels, int32_t *pWidth
{ {
Cram_Internal_Context *internalContext = (Cram_Internal_Context*) context; Cram_Internal_Context *internalContext = (Cram_Internal_Context*) context;
*pPixels = internalContext->pixels; *pPixels = internalContext->pixels;
*pWidth = internalContext->width; *pWidth = internalContext->packedWidth;
*pHeight = internalContext->height; *pHeight = internalContext->packedHeight;
} }
void Cram_GetMetadata(Cram_Context *context, Cram_ImageData **pImage, int32_t *pImageCount) void Cram_GetMetadata(Cram_Context *context, Cram_ImageData **pImage, int32_t *pImageCount)