output image metadata
parent
943253add1
commit
6faceb9d16
|
@ -60,6 +60,7 @@ if(BUILD_CLI)
|
|||
add_executable(cramcli
|
||||
tools/cli/lib/dirent.h
|
||||
tools/cli/lib/stb_image_write.h
|
||||
tools/cli/json_writer.h
|
||||
tools/cli/main.c
|
||||
)
|
||||
|
||||
|
|
|
@ -59,6 +59,14 @@
|
|||
#define Cram_min min
|
||||
#define Cram_max max
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SEPARATOR '\\'
|
||||
#endif
|
||||
|
||||
#ifdef __unix__
|
||||
#define SEPARATOR '/'
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
|
@ -90,28 +98,19 @@ typedef struct Cram_ContextCreateInfo
|
|||
|
||||
typedef struct Cram_ImageData
|
||||
{
|
||||
const char *path;
|
||||
char *name;
|
||||
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
|
||||
uint32_t offsetX;
|
||||
uint32_t offsetY;
|
||||
uint32_t trimmedWidth;
|
||||
uint32_t trimmedHeight;
|
||||
int32_t offsetX;
|
||||
int32_t offsetY;
|
||||
int32_t untrimmedWidth;
|
||||
int32_t untrimmedHeight;
|
||||
} Cram_ImageData;
|
||||
|
||||
typedef struct Cram_AtlasData
|
||||
{
|
||||
const char *name;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
Cram_ImageData *imageDatas;
|
||||
uint32_t imageDataCount;
|
||||
} Cram_AtlasData;
|
||||
|
||||
/* API definition */
|
||||
|
||||
CRAMAPI Cram_Context* Cram_Init(Cram_ContextCreateInfo *createInfo);
|
||||
|
@ -121,7 +120,7 @@ CRAMAPI void Cram_AddFile(Cram_Context *context, const char *path);
|
|||
CRAMAPI int8_t Cram_Pack(Cram_Context *context);
|
||||
|
||||
CRAMAPI void Cram_GetPixelData(Cram_Context *context, uint8_t **pPixelData, uint32_t *pWidth, uint32_t *pHeight);
|
||||
CRAMAPI void Cram_GetAtlasData(Cram_Context *context, Cram_AtlasData **pAtlasData);
|
||||
CRAMAPI void Cram_GetMetadata(Cram_Context *context, Cram_ImageData **pImage, uint32_t *pImageCount);
|
||||
|
||||
CRAMAPI void Cram_Destroy(Cram_Context *context);
|
||||
|
||||
|
|
140
src/cram.c
140
src/cram.c
|
@ -53,14 +53,17 @@ typedef struct Rect
|
|||
int32_t w, h;
|
||||
} Rect;
|
||||
|
||||
typedef struct Cram_Image
|
||||
typedef struct Cram_Image Cram_Image;
|
||||
|
||||
struct Cram_Image
|
||||
{
|
||||
const char *name;
|
||||
char *name;
|
||||
Rect originalRect;
|
||||
Rect rect;
|
||||
uint8_t duplicate; /* FIXME: is there a better way to do this? */
|
||||
uint8_t *pixels; /* Will be NULL if duplicate! */
|
||||
Cram_Image *duplicateOf;
|
||||
uint8_t *pixels; /* Will be NULL if duplicateOf is not NULL! */
|
||||
size_t hash;
|
||||
} Cram_Image;
|
||||
};
|
||||
|
||||
typedef struct Cram_Internal_Context
|
||||
{
|
||||
|
@ -73,11 +76,12 @@ typedef struct Cram_Internal_Context
|
|||
|
||||
uint8_t *pixels;
|
||||
|
||||
Cram_Image *images;
|
||||
Cram_Image **images;
|
||||
uint32_t imageCount;
|
||||
uint32_t imageCapacity;
|
||||
|
||||
Cram_AtlasData *atlasData;
|
||||
Cram_ImageData *imageDatas;
|
||||
uint32_t imageDataCount;
|
||||
} Cram_Internal_Context;
|
||||
|
||||
typedef struct RectPackContext
|
||||
|
@ -486,17 +490,32 @@ Cram_Context* Cram_Init(Cram_ContextCreateInfo *createInfo)
|
|||
context->padding = createInfo->padding;
|
||||
context->trim = createInfo->trim;
|
||||
|
||||
context->images = Cram_malloc(INITIAL_DATA_CAPACITY * sizeof(Cram_Image));
|
||||
context->images = Cram_malloc(INITIAL_DATA_CAPACITY * sizeof(Cram_Image*));
|
||||
context->imageCapacity = INITIAL_DATA_CAPACITY;
|
||||
context->imageCount = 0;
|
||||
|
||||
context->atlasData = Cram_malloc(sizeof(Cram_AtlasData));
|
||||
|
||||
context->pixels = NULL;
|
||||
context->imageDatas = NULL;
|
||||
context->imageDataCount = 0;
|
||||
|
||||
return (Cram_Context*) context;
|
||||
}
|
||||
|
||||
static char* Cram_Internal_GetImageName(const char *path)
|
||||
{
|
||||
char *lastSeparator = strrchr(path, SEPARATOR) + 1;
|
||||
size_t returnBytes = strlen(lastSeparator) + 1;
|
||||
char *name = Cram_malloc(returnBytes);
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i < returnBytes; i += 1)
|
||||
{
|
||||
name[i] = lastSeparator[i];
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
void Cram_AddFile(Cram_Context *context, const char *path)
|
||||
{
|
||||
Cram_Internal_Context *internalContext = (Cram_Internal_Context*) context;
|
||||
|
@ -509,12 +528,13 @@ void Cram_AddFile(Cram_Context *context, const char *path)
|
|||
if (internalContext->imageCapacity == internalContext->imageCount)
|
||||
{
|
||||
internalContext->imageCapacity *= 2;
|
||||
internalContext->images = Cram_realloc(internalContext->images, internalContext->imageCapacity * sizeof(Cram_Image));
|
||||
internalContext->images = Cram_realloc(internalContext->images, internalContext->imageCapacity * sizeof(Cram_Image*));
|
||||
}
|
||||
|
||||
image = &internalContext->images[internalContext->imageCount];
|
||||
image = Cram_malloc(sizeof(Cram_Image));
|
||||
internalContext->images[internalContext->imageCount] = image;
|
||||
|
||||
/* image->name = Cram_Internal_GetTrimmedPath(); */
|
||||
image->name = Cram_Internal_GetImageName(path);
|
||||
|
||||
pixels = stbi_load(
|
||||
path,
|
||||
|
@ -524,6 +544,11 @@ void Cram_AddFile(Cram_Context *context, const char *path)
|
|||
STBI_rgb_alpha
|
||||
);
|
||||
|
||||
image->originalRect.x = 0;
|
||||
image->originalRect.y = 0;
|
||||
image->originalRect.w = width;
|
||||
image->originalRect.h = height;
|
||||
|
||||
/* Check for trim */
|
||||
if (internalContext->trim)
|
||||
{
|
||||
|
@ -574,10 +599,7 @@ void Cram_AddFile(Cram_Context *context, const char *path)
|
|||
}
|
||||
else
|
||||
{
|
||||
image->rect.x = 0;
|
||||
image->rect.y = 0;
|
||||
image->rect.w = width;
|
||||
image->rect.h = height;
|
||||
image->rect = image->originalRect;
|
||||
}
|
||||
|
||||
/* copy and free source pixels */
|
||||
|
@ -595,15 +617,15 @@ void Cram_AddFile(Cram_Context *context, const char *path)
|
|||
image->hash = stbds_hash_bytes(image->pixels, image->rect.w * image->rect.h * 4, 0);
|
||||
|
||||
/* check if this is a duplicate */
|
||||
image->duplicate = 0;
|
||||
image->duplicateOf = NULL;
|
||||
for (i = 0; i < internalContext->imageCount; i += 1)
|
||||
{
|
||||
if (!internalContext->images[i].duplicate)
|
||||
if (!internalContext->images[i]->duplicateOf)
|
||||
{
|
||||
if (Cram_Internal_IsImageEqual(image, &internalContext->images[i]))
|
||||
if (Cram_Internal_IsImageEqual(image, internalContext->images[i]))
|
||||
{
|
||||
/* this is duplicate data! */
|
||||
image->duplicate = 1;
|
||||
image->duplicateOf = image;
|
||||
Cram_free(image->pixels);
|
||||
image->pixels = NULL;
|
||||
break;
|
||||
|
@ -623,15 +645,19 @@ int8_t Cram_Pack(Cram_Context *context)
|
|||
uint32_t numRects = 0;
|
||||
Rect *packerRect;
|
||||
Rect dstRect, srcRect;
|
||||
int32_t i;
|
||||
Cram_Image *image;
|
||||
uint32_t maxWidth = 0;
|
||||
uint32_t maxHeight = 0;
|
||||
int32_t i;
|
||||
|
||||
internalContext->imageDataCount = internalContext->imageCount;
|
||||
internalContext->imageDatas = Cram_realloc(internalContext->imageDatas, sizeof(Cram_ImageData) * internalContext->imageDataCount);
|
||||
|
||||
rectPackContext = Cram_Internal_InitRectPacker(internalContext->width, internalContext->height);
|
||||
|
||||
for (i = 0; i < internalContext->imageCount; i += 1)
|
||||
{
|
||||
if (!internalContext->images[i].duplicate)
|
||||
if (!internalContext->images[i]->duplicateOf)
|
||||
{
|
||||
numRects += 1;
|
||||
}
|
||||
|
@ -642,12 +668,12 @@ int8_t Cram_Pack(Cram_Context *context)
|
|||
numRects = 0;
|
||||
for (i = 0; i < internalContext->imageCount; i += 1)
|
||||
{
|
||||
if (!internalContext->images[i].duplicate)
|
||||
if (!internalContext->images[i]->duplicateOf)
|
||||
{
|
||||
packerRect = &packerRects[numRects];
|
||||
|
||||
packerRect->w = internalContext->images[i].rect.w + internalContext->padding;
|
||||
packerRect->h = internalContext->images[i].rect.h + internalContext->padding;
|
||||
packerRect->w = internalContext->images[i]->rect.w + internalContext->padding;
|
||||
packerRect->h = internalContext->images[i]->rect.h + internalContext->padding;
|
||||
|
||||
numRects += 1;
|
||||
}
|
||||
|
@ -661,12 +687,12 @@ int8_t Cram_Pack(Cram_Context *context)
|
|||
numRects = 0;
|
||||
for (i = 0; i < internalContext->imageCount; i += 1)
|
||||
{
|
||||
if (!internalContext->images[i].duplicate)
|
||||
if (!internalContext->images[i]->duplicateOf)
|
||||
{
|
||||
packerRect = &packerRects[numRects];
|
||||
|
||||
internalContext->images[i].rect.x = packerRect->x;
|
||||
internalContext->images[i].rect.y = packerRect->y;
|
||||
internalContext->images[i]->rect.x = packerRect->x;
|
||||
internalContext->images[i]->rect.y = packerRect->y;
|
||||
|
||||
maxWidth = Cram_max(maxWidth, packerRect->x + packerRect->w);
|
||||
maxHeight = Cram_max(maxHeight, packerRect->y + packerRect->h);
|
||||
|
@ -683,27 +709,48 @@ int8_t Cram_Pack(Cram_Context *context)
|
|||
|
||||
for (i = 0; i < internalContext->imageCount; i += 1)
|
||||
{
|
||||
if (!internalContext->images[i].duplicate)
|
||||
if (!internalContext->images[i]->duplicateOf)
|
||||
{
|
||||
dstRect.x = internalContext->images[i].rect.x;
|
||||
dstRect.y = internalContext->images[i].rect.y;
|
||||
dstRect.w = internalContext->images[i].rect.w;
|
||||
dstRect.h = internalContext->images[i].rect.h;
|
||||
dstRect.x = internalContext->images[i]->rect.x;
|
||||
dstRect.y = internalContext->images[i]->rect.y;
|
||||
dstRect.w = internalContext->images[i]->rect.w;
|
||||
dstRect.h = internalContext->images[i]->rect.h;
|
||||
|
||||
srcRect.x = 0;
|
||||
srcRect.y = 0;
|
||||
srcRect.w = internalContext->images[i].rect.w;
|
||||
srcRect.h = internalContext->images[i].rect.h;
|
||||
srcRect.w = internalContext->images[i]->rect.w;
|
||||
srcRect.h = internalContext->images[i]->rect.h;
|
||||
|
||||
Cram_Internal_CopyPixels(
|
||||
(uint32_t*) internalContext->pixels,
|
||||
internalContext->width,
|
||||
(uint32_t*) internalContext->images[i].pixels,
|
||||
internalContext->images[i].rect.w,
|
||||
(uint32_t*) internalContext->images[i]->pixels,
|
||||
internalContext->images[i]->rect.w,
|
||||
&dstRect,
|
||||
&srcRect
|
||||
);
|
||||
}
|
||||
|
||||
if (internalContext->images[i]->duplicateOf)
|
||||
{
|
||||
image = internalContext->images[i]->duplicateOf;
|
||||
}
|
||||
else
|
||||
{
|
||||
image = internalContext->images[i];
|
||||
}
|
||||
|
||||
internalContext->imageDatas[i].x = image->rect.x;
|
||||
internalContext->imageDatas[i].y = image->rect.y;
|
||||
internalContext->imageDatas[i].width = image->rect.w;
|
||||
internalContext->imageDatas[i].height = image->rect.h;
|
||||
|
||||
internalContext->imageDatas[i].offsetX = image->rect.x - image->originalRect.x;
|
||||
internalContext->imageDatas[i].offsetY = image->rect.y - image->originalRect.y;
|
||||
internalContext->imageDatas[i].untrimmedWidth = image->originalRect.w;
|
||||
internalContext->imageDatas[i].untrimmedHeight = image->originalRect.h;
|
||||
|
||||
internalContext->imageDatas[i].name = strdup(image->name);
|
||||
}
|
||||
|
||||
Cram_free(packerRects);
|
||||
|
@ -719,9 +766,12 @@ void Cram_GetPixelData(Cram_Context *context, uint8_t **pPixels, uint32_t *pWidt
|
|||
*pHeight = internalContext->height;
|
||||
}
|
||||
|
||||
void Cram_GetAtlasData(Cram_Context *context, Cram_AtlasData **pAtlasData)
|
||||
void Cram_GetMetadata(Cram_Context *context, Cram_ImageData **pImage, uint32_t *pImageCount)
|
||||
{
|
||||
*pAtlasData = ((Cram_Internal_Context*) context)->atlasData;
|
||||
Cram_Internal_Context *internalContext = (Cram_Internal_Context*) context;
|
||||
|
||||
*pImage = internalContext->imageDatas;
|
||||
*pImageCount = internalContext->imageDataCount;
|
||||
}
|
||||
|
||||
void Cram_Destroy(Cram_Context *context)
|
||||
|
@ -736,13 +786,17 @@ void Cram_Destroy(Cram_Context *context)
|
|||
|
||||
for (i = 0; i < internalContext->imageCount; i += 1)
|
||||
{
|
||||
if (!internalContext->images[i].duplicate)
|
||||
if (!internalContext->images[i]->duplicateOf)
|
||||
{
|
||||
Cram_free(internalContext->images[i].pixels);
|
||||
Cram_free(internalContext->images[i]->pixels);
|
||||
}
|
||||
|
||||
Cram_free(internalContext->images[i]->name);
|
||||
Cram_free(internalContext->images[i]);
|
||||
}
|
||||
|
||||
Cram_free(internalContext->name);
|
||||
Cram_free(internalContext->images);
|
||||
Cram_free(internalContext->atlasData);
|
||||
Cram_free(internalContext->imageDatas);
|
||||
Cram_free(internalContext);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
|
||||
#ifndef JSON_WRITER_H
|
||||
#define JSON_WRITER_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define INITIAL_JSON_OUTPUT_CAPACITY 2048
|
||||
|
||||
typedef struct JsonBuilder
|
||||
{
|
||||
char *string;
|
||||
size_t index;
|
||||
size_t capacity;
|
||||
size_t indentLevel;
|
||||
} JsonBuilder;
|
||||
|
||||
JsonBuilder* JsonBuilder_Init()
|
||||
{
|
||||
JsonBuilder *builder = malloc(sizeof(JsonBuilder));
|
||||
|
||||
builder->string = malloc(INITIAL_JSON_OUTPUT_CAPACITY);
|
||||
builder->capacity = INITIAL_JSON_OUTPUT_CAPACITY;
|
||||
|
||||
builder->string[0] = '\0';
|
||||
|
||||
strcat(builder->string, "{\n");
|
||||
builder->indentLevel = 1;
|
||||
builder->index = 2;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
void JsonBuilder_Internal_MaybeExpand(JsonBuilder *builder, size_t len)
|
||||
{
|
||||
if (builder->capacity < builder->index + len)
|
||||
{
|
||||
builder->capacity = max(builder->index + len, builder->capacity * 2);
|
||||
builder->string = realloc(builder->string, builder->capacity);
|
||||
}
|
||||
}
|
||||
|
||||
void JsonBuilder_Internal_Indent(JsonBuilder *builder)
|
||||
{
|
||||
int32_t i;
|
||||
JsonBuilder_Internal_MaybeExpand(builder, builder->indentLevel);
|
||||
|
||||
for (i = 0; i < builder->indentLevel; i += 1)
|
||||
{
|
||||
strcat(builder->string, "\t");
|
||||
}
|
||||
|
||||
builder->index += builder->indentLevel;
|
||||
}
|
||||
|
||||
void JsonBuilder_Internal_RemoveTrailingComma(JsonBuilder *builder)
|
||||
{
|
||||
if (builder->string[builder->index - 2] == ',')
|
||||
{
|
||||
builder->index -= 2;
|
||||
builder->index += sprintf(&builder->string[builder->index], "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void JsonBuilder_AppendProperty(JsonBuilder *builder, char *propertyName, char *propertyString, uint8_t isString)
|
||||
{
|
||||
size_t lineLength;
|
||||
|
||||
lineLength = strlen(propertyName) + strlen(propertyString) + 6;
|
||||
if (isString)
|
||||
{
|
||||
lineLength += 2;
|
||||
}
|
||||
|
||||
JsonBuilder_Internal_MaybeExpand(builder, lineLength);
|
||||
JsonBuilder_Internal_Indent(builder);
|
||||
|
||||
builder->index += sprintf(&builder->string[builder->index], "\"%s\": ", propertyName);
|
||||
|
||||
if (isString)
|
||||
{
|
||||
builder->index += sprintf(&builder->string[builder->index], "\"%s\",\n", propertyString);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder->index += sprintf(&builder->string[builder->index], "%s,\n", propertyString);
|
||||
}
|
||||
}
|
||||
|
||||
void JsonBuilder_AppendStringProperty(JsonBuilder *builder, char *propertyName, char *value)
|
||||
{
|
||||
JsonBuilder_AppendProperty(builder, propertyName, value, 1);
|
||||
}
|
||||
|
||||
void JsonBuilder_AppendIntProperty(JsonBuilder *builder, char *propertyName, int32_t value)
|
||||
{
|
||||
char buffer[65];
|
||||
itoa(value, buffer, 10);
|
||||
JsonBuilder_AppendProperty(builder, propertyName, buffer, 0);
|
||||
}
|
||||
|
||||
void JsonBuilder_StartObject(JsonBuilder *builder)
|
||||
{
|
||||
JsonBuilder_Internal_Indent(builder);
|
||||
JsonBuilder_Internal_MaybeExpand(builder, 1);
|
||||
builder->index += sprintf(&builder->string[builder->index], "{\n");
|
||||
builder->indentLevel += 1;
|
||||
}
|
||||
|
||||
void JsonBuilder_EndObject(JsonBuilder *builder)
|
||||
{
|
||||
JsonBuilder_Internal_RemoveTrailingComma(builder);
|
||||
|
||||
builder->indentLevel -= 1;
|
||||
|
||||
JsonBuilder_Internal_Indent(builder);
|
||||
JsonBuilder_Internal_MaybeExpand(builder, 3);
|
||||
builder->index += sprintf(&builder->string[builder->index], "},\n");
|
||||
}
|
||||
|
||||
void JsonBuilder_StartArrayProperty(JsonBuilder *builder, char *propertyName)
|
||||
{
|
||||
JsonBuilder_Internal_Indent(builder);
|
||||
JsonBuilder_Internal_MaybeExpand(builder, strlen(propertyName) + 6);
|
||||
builder->index += sprintf(&builder->string[builder->index], "\"%s\": [\n", propertyName);
|
||||
builder->indentLevel += 1;
|
||||
}
|
||||
|
||||
void JsonBuilder_FinishArrayProperty(JsonBuilder *builder)
|
||||
{
|
||||
JsonBuilder_Internal_RemoveTrailingComma(builder);
|
||||
|
||||
builder->indentLevel -= 1;
|
||||
|
||||
JsonBuilder_Internal_Indent(builder);
|
||||
JsonBuilder_Internal_MaybeExpand(builder, 3);
|
||||
builder->index += sprintf(&builder->string[builder->index], "],\n");
|
||||
}
|
||||
|
||||
void JsonBuilder_Finish(JsonBuilder *builder)
|
||||
{
|
||||
builder->indentLevel = 0;
|
||||
|
||||
JsonBuilder_Internal_RemoveTrailingComma(builder);
|
||||
JsonBuilder_Internal_MaybeExpand(builder, 3);
|
||||
|
||||
builder->index += sprintf(&builder->string[builder->index], "}\n");
|
||||
}
|
||||
|
||||
void JsonBuilder_Destroy(JsonBuilder *builder)
|
||||
{
|
||||
free(builder->string);
|
||||
free(builder);
|
||||
}
|
||||
|
||||
#endif /* JSON_WRITER_H */
|
|
@ -1,5 +1,6 @@
|
|||
#include "cram.h"
|
||||
#include "dirent.h"
|
||||
#include "json_writer.h"
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
|
@ -8,18 +9,6 @@
|
|||
|
||||
static Cram_Context *context;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define SEPARATOR "\\"
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __unix__
|
||||
|
||||
#define SEPARATOR "/"
|
||||
|
||||
#endif
|
||||
|
||||
static const char* GetFilenameExtension(const char *filename)
|
||||
{
|
||||
const char *dot = strrchr(filename, '.');
|
||||
|
@ -52,7 +41,7 @@ static void dirwalk(char *dir)
|
|||
continue;
|
||||
}
|
||||
|
||||
sprintf(subname, "%s%s%s", dir, SEPARATOR, dp->d_name);
|
||||
sprintf(subname, "%s%c%s", dir, SEPARATOR, dp->d_name);
|
||||
|
||||
if (dp->d_type == DT_DIR)
|
||||
{
|
||||
|
@ -102,6 +91,10 @@ int main(int argc, char *argv[])
|
|||
char *inputDirPath = NULL;
|
||||
char *outputDirPath = NULL;
|
||||
char *imageOutputFilename;
|
||||
char *metadataFilename;
|
||||
JsonBuilder *jsonBuilder;
|
||||
Cram_ImageData *imageDatas;
|
||||
uint32_t imageCount;
|
||||
int32_t i;
|
||||
|
||||
/* Set defaults */
|
||||
|
@ -195,8 +188,9 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
Cram_GetPixelData(context, &pixelData, &width, &height);
|
||||
/* output pixel data */
|
||||
|
||||
Cram_GetPixelData(context, &pixelData, &width, &height);
|
||||
imageOutputFilename = Cram_malloc(strlen(createInfo.name) + 5);
|
||||
strcpy(imageOutputFilename, createInfo.name);
|
||||
strcat(imageOutputFilename, ".png");
|
||||
|
@ -210,7 +204,50 @@ int main(int argc, char *argv[])
|
|||
width * 4
|
||||
);
|
||||
|
||||
/* output json */
|
||||
|
||||
Cram_GetMetadata(context, &imageDatas, &imageCount);
|
||||
|
||||
jsonBuilder = JsonBuilder_Init();
|
||||
JsonBuilder_AppendStringProperty(jsonBuilder, "Name", createInfo.name);
|
||||
JsonBuilder_AppendIntProperty(jsonBuilder, "Width", width);
|
||||
JsonBuilder_AppendIntProperty(jsonBuilder, "Height", height);
|
||||
JsonBuilder_StartArrayProperty(jsonBuilder, "Images");
|
||||
for (i = 0; i < imageCount; i += 1)
|
||||
{
|
||||
JsonBuilder_StartObject(jsonBuilder);
|
||||
JsonBuilder_AppendStringProperty(jsonBuilder, "Name", imageDatas[i].name);
|
||||
JsonBuilder_AppendIntProperty(jsonBuilder, "X", imageDatas[i].x);
|
||||
JsonBuilder_AppendIntProperty(jsonBuilder, "Y", imageDatas[i].y);
|
||||
JsonBuilder_AppendIntProperty(jsonBuilder, "W", imageDatas[i].width);
|
||||
JsonBuilder_AppendIntProperty(jsonBuilder, "H", imageDatas[i].height);
|
||||
JsonBuilder_AppendIntProperty(jsonBuilder, "OffsetX", imageDatas[i].offsetX);
|
||||
JsonBuilder_AppendIntProperty(jsonBuilder, "OffsetY", imageDatas[i].offsetY);
|
||||
JsonBuilder_AppendIntProperty(jsonBuilder, "UntrimmedWidth", imageDatas[i].untrimmedWidth);
|
||||
JsonBuilder_AppendIntProperty(jsonBuilder, "UntrimmedHeight", imageDatas[i].untrimmedHeight);
|
||||
JsonBuilder_EndObject(jsonBuilder);
|
||||
}
|
||||
JsonBuilder_FinishArrayProperty(jsonBuilder);
|
||||
JsonBuilder_Finish(jsonBuilder);
|
||||
|
||||
metadataFilename = Cram_malloc(strlen(createInfo.name) + 6);
|
||||
strcpy(metadataFilename, createInfo.name);
|
||||
strcat(metadataFilename, ".json");
|
||||
|
||||
FILE *jsonOutput = fopen(metadataFilename, "w");
|
||||
if (!jsonOutput)
|
||||
{
|
||||
fprintf(stderr, "Could not open JSON file for writing!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(jsonOutput, jsonBuilder->string);
|
||||
|
||||
JsonBuilder_Destroy(jsonBuilder);
|
||||
fclose(jsonOutput);
|
||||
|
||||
Cram_free(imageOutputFilename);
|
||||
Cram_free(metadataFilename);
|
||||
Cram_Destroy(context);
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue