本文主要是介绍W801学习笔记十三:掌机系统——系统基础组件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
我们以一个唐诗学习程序为引子,把掌机的系统架子搭起来。
唐诗学习程序目标:
1、随机选择一首唐诗,随即选择其中的一句进行隐藏。
2、玩家从四个备选句子中选择一个答案。
系统目标:
1、静态数据尽量放在SD中,便于后续的扩展。动态数据尽量放在PSRAM中。
2、尽量的可配置化。
3、不使用LVGL等开源图形框架,按需自己手锤一个图形框架。比如在PSRAM中建立显示缓存。
开始吧。
首先我们要为系统添加一些常用的基础组件。
1、JSON组件
用JSON来保存菜单项。这里,我们用开源的cJSON。
cJSON.h
/*Copyright (c) 2009 Dave GamblePermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE.
*/#ifndef cJSON__h
#define cJSON__h#ifdef __cplusplus
extern "C"
{
#endif/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6#define cJSON_IsReference 256/* The cJSON structure: */
typedef struct cJSON {struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */int type; /* The type of the item, as above. */char *valuestring; /* The item's string, if type==cJSON_String */int valueint; /* The item's number, if type==cJSON_Number */double valuedouble; /* The item's number, if type==cJSON_Number */char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;
#if 0
typedef struct cJSON_Hooks {void *(*malloc_fn)(size_t sz);void (*free_fn)(void *ptr);
} cJSON_Hooks;/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
#endif/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item);
/* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c);/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
extern const char *cJSON_GetErrorPtr(void);/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);/* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);/* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);/* Update array items. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);/* Duplicate a cJSON item */
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. *//* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);extern void cJSON_Minify(char *json);/* Macros for creating things quickly. */
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))#ifdef __cplusplus
}
#endif#endif
cJSON.c
/*Copyright (c) 2009 Dave GamblePermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHERLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INTHE SOFTWARE.
*//* cJSON */
/* JSON parser in C. */
#include "wm_mem.h"
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "cJSON.h"
#include "utils.h"static const char *ep;const char *cJSON_GetErrorPtr(void) {return ep;}static int cJSON_strcasecmp(const char *s1,const char *s2)
{if (!s1) {return (s1==s2)?0:1;}if (!s2) {return 1;}for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}//static void *(*cJSON_malloc)(size_t sz) = malloc;
//static void (*cJSON_free)(void *ptr) = free;
#define cJSON_malloc tls_mem_alloc
#define cJSON_free tls_mem_free
#define cJSON_strdup strdup
#if 0
static char* cJSON_strdup(const char* str)
{size_t len;char* copy;len = strlen(str) + 1;if (!(copy = (char*)cJSON_malloc(len))) return 0;memcpy(copy,str,len);return copy;
}
void cJSON_InitHooks(cJSON_Hooks* hooks)
{if (!hooks) { /* Reset hooks */cJSON_malloc = malloc;cJSON_free = free;return;}cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
}
#endif
/* Internal constructor. */
static cJSON *cJSON_New_Item(void)
{cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));if (node) memset(node,0,sizeof(cJSON));return node;
}/* Delete a cJSON structure. */
void cJSON_Delete(cJSON *c)
{cJSON *next;while (c){next=c->next;if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);if (c->string) cJSON_free(c->string);cJSON_free(c);c=next;}
}/* Parse the input text to generate a number, and populate the result into item. */
static const char *parse_number(cJSON *item,const char *num)
{double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;if (*num=='-') sign=-1,num++; /* Has sign? */if (*num=='0') num++; /* is zero */if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */if (*num=='e' || *num=='E') /* Exponent? */{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */}n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */item->valuedouble=n;item->valueint=(int)n;item->type=cJSON_Number;return num;
}/* Render the number nicely from the given item into a string. */
static char *print_number(cJSON *item)
{char *str;double d=item->valuedouble;if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN){str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */if (str) sprintf(str,"%d",item->valueint);}else{str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */if (str){if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);else sprintf(str,"%f",d);}}return str;
}static unsigned parse_hex4(const char *str)
{unsigned h=0;if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;h=h<<4;str++;if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;h=h<<4;str++;if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;h=h<<4;str++;if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;return h;
}/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(cJSON *item,const char *str)
{const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;if (*str!='\"') {ep=str;return 0;} /* not a string! */while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */if (!out) return 0;ptr=str+1;ptr2=out;while (*ptr!='\"' && *ptr){if (*ptr!='\\') *ptr2++=*ptr++;else{ptr++;switch (*ptr){case 'b': *ptr2++='\b'; break;case 'f': *ptr2++='\f'; break;case 'n': *ptr2++='\n'; break;case 'r': *ptr2++='\r'; break;case 't': *ptr2++='\t'; break;case 'u': /* transcode utf16 to utf8. */uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */{if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */uc2=parse_hex4(ptr+3);ptr+=6;if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));}len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;switch (len) {case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;case 1: *--ptr2 =(uc | firstByteMark[len]);}ptr2+=len;break;default: *ptr2++=*ptr; break;}ptr++;}}*ptr2=0;if (*ptr=='\"') ptr++;item->valuestring=out;item->type=cJSON_String;return ptr;
}/* Render the cstring provided to an escaped version that can be printed. */
static char *print_string_ptr(const char *str)
{const char *ptr;char *ptr2,*out;int len=0;unsigned char token;if (!str) return cJSON_strdup("");ptr=str;while ((0 != (token=*ptr)) && (0 != (++len))) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}out=(char*)cJSON_malloc(len+3);if (!out) return 0;ptr2=out;ptr=str;*ptr2++='\"';while (*ptr){if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;else{*ptr2++='\\';switch (token=*ptr++){case '\\': *ptr2++='\\'; break;case '\"': *ptr2++='\"'; break;case '\b': *ptr2++='b'; break;case '\f': *ptr2++='f'; break;case '\n': *ptr2++='n'; break;case '\r': *ptr2++='r'; break;case '\t': *ptr2++='t'; break;default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */}}}*ptr2++='\"';*ptr2++=0;return out;
}
/* Invote print_string_ptr (which is useful) on an item. */
static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}/* Predeclare these prototypes. */
static const char *parse_value(cJSON *item,const char *value);
static char *print_value(cJSON *item,int depth,int fmt);
static const char *parse_array(cJSON *item,const char *value);
static char *print_array(cJSON *item,int depth,int fmt);
static const char *parse_object(cJSON *item,const char *value);
static char *print_object(cJSON *item,int depth,int fmt);/* Utility to jump whitespace and cr/lf */
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}/* Parse an object - create a new root, and populate. */
cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
{const char *end=0;cJSON *c=cJSON_New_Item();ep=0;if (!c) return 0; /* memory fail */end=parse_value(c,skip(value));if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. *//* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}if (return_parse_end) *return_parse_end=end;return c;
}
/* Default options for cJSON_Parse */
cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}/* Render a cJSON item/entity/structure to text. */
char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}/* Parser core - when encountering text, process appropriately. */
static const char *parse_value(cJSON *item,const char *value)
{if (!value) return 0; /* Fail on null. */if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }if (*value=='\"') { return parse_string(item,value); }if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }if (*value=='[') { return parse_array(item,value); }if (*value=='{') { return parse_object(item,value); }ep=value;return 0; /* failure. */
}/* Render a value to text. */
static char *print_value(cJSON *item,int depth,int fmt)
{char *out=0;if (!item) return 0;switch ((item->type)&255){case cJSON_NULL: out=cJSON_strdup("null"); break;case cJSON_False: out=cJSON_strdup("false");break;case cJSON_True: out=cJSON_strdup("true"); break;case cJSON_Number: out=print_number(item);break;case cJSON_String: out=print_string(item);break;case cJSON_Array: out=print_array(item,depth,fmt);break;case cJSON_Object: out=print_object(item,depth,fmt);break;}return out;
}/* Build an array from input text. */
static const char *parse_array(cJSON *item,const char *value)
{cJSON *child;if (*value!='[') {ep=value;return 0;} /* not an array! */item->type=cJSON_Array;value=skip(value+1);if (*value==']') return value+1; /* empty array. */item->child=child=cJSON_New_Item();if (!item->child) return 0; /* memory fail */value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */if (!value) return 0;while (*value==','){cJSON *new_item;if (NULL == (new_item=cJSON_New_Item())) return 0; /* memory fail */child->next=new_item;new_item->prev=child;child=new_item;value=skip(parse_value(child,skip(value+1)));if (!value) return 0; /* memory fail */}if (*value==']') return value+1; /* end of array */ep=value;return 0; /* malformed. */
}/* Render an array to text */
static char *print_array(cJSON *item,int depth,int fmt)
{char **entries;char *out=0,*ptr,*ret;int len=5;cJSON *child=item->child;int numentries=0,i=0,fail=0;/* How many entries in the array? */while (child) numentries++,child=child->next;/* Explicitly handle numentries==0 */if (!numentries){out=(char*)cJSON_malloc(3);if (out) strcpy(out,"[]");return out;}/* Allocate an array to hold the values for each */entries=(char**)cJSON_malloc(numentries*sizeof(char*));if (!entries) return 0;memset(entries,0,numentries*sizeof(char*));/* Retrieve all the results: */child=item->child;while (child && !fail){ret=print_value(child,depth+1,fmt);entries[i++]=ret;if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;child=child->next;}/* If we didn't fail, try to malloc the output string */if (!fail) out=(char*)cJSON_malloc(len);/* If that fails, we fail. */if (!out) fail=1;/* Handle failure. */if (fail){for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);cJSON_free(entries);return 0;}/* Compose the output array. */*out='[';ptr=out+1;*ptr=0;for (i=0;i<numentries;i++){strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}cJSON_free(entries[i]);}cJSON_free(entries);*ptr++=']';*ptr++=0;return out;
}/* Build an object from the text. */
static const char *parse_object(cJSON *item,const char *value)
{cJSON *child;if (*value!='{') {ep=value;return 0;} /* not an object! */item->type=cJSON_Object;value=skip(value+1);if (*value=='}') return value+1; /* empty array. */item->child=child=cJSON_New_Item();if (!item->child) return 0;value=skip(parse_string(child,skip(value)));if (!value) return 0;child->string=child->valuestring;child->valuestring=0;if (*value!=':') {ep=value;return 0;} /* fail! */value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */if (!value) return 0;while (*value==','){cJSON *new_item;if (NULL == (new_item=cJSON_New_Item())) return 0; /* memory fail */child->next=new_item;new_item->prev=child;child=new_item;value=skip(parse_string(child,skip(value+1)));if (!value) return 0;child->string=child->valuestring;child->valuestring=0;if (*value!=':') {ep=value;return 0;} /* fail! */value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */if (!value) return 0;}if (*value=='}') return value+1; /* end of array */ep=value;return 0; /* malformed. */
}/* Render an object to text. */
static char *print_object(cJSON *item,int depth,int fmt)
{char **entries=0,**names=0;char *out=0,*ptr,*ret,*str;int len=7,i=0,j;cJSON *child=item->child;int numentries=0,fail=0;/* Count the number of entries. */while (child) numentries++,child=child->next;/* Explicitly handle empty object case */if (!numentries){out=(char*)cJSON_malloc(fmt?depth+4:3);if (!out) return 0;ptr=out;*ptr++='{';if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}*ptr++='}';*ptr++=0;return out;}/* Allocate space for the names and the objects */entries=(char**)cJSON_malloc(numentries*sizeof(char*));if (!entries) return 0;names=(char**)cJSON_malloc(numentries*sizeof(char*));if (!names) {cJSON_free(entries);return 0;}memset(entries,0,sizeof(char*)*numentries);memset(names,0,sizeof(char*)*numentries);/* Collect all the results into our arrays: */child=item->child;depth++;if (fmt) len+=depth;while (child){names[i]=str=print_string_ptr(child->string);entries[i++]=ret=print_value(child,depth,fmt);if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;child=child->next;}/* Try to allocate the output string */if (!fail) out=(char*)cJSON_malloc(len);if (!out) fail=1;/* Handle failure */if (fail){for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}cJSON_free(names);cJSON_free(entries);return 0;}/* Compose the output: */*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;for (i=0;i<numentries;i++){if (fmt) for (j=0;j<depth;j++) *ptr++='\t';strcpy(ptr,names[i]);ptr+=strlen(names[i]);*ptr++=':';if (fmt) *ptr++='\t';strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);if (i!=numentries-1) *ptr++=',';if (fmt) {*ptr++='\n';}*ptr=0;cJSON_free(names[i]);cJSON_free(entries[i]);}cJSON_free(names);cJSON_free(entries);if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';*ptr++='}';*ptr++=0;return out;
}/* Get Array size/item / object item. */
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}/* Utility for array list handling. */
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
/* Utility for handling references. */
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}/* Add item to array/object. */
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;if (c->prev) {c->prev->next=c->next;}if (c->next) {c->next->prev=c->prev;}if (c==array->child) {array->child=c->next;}c->prev=c->next=0;return c;}
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}/* Replace array/object items with new ones. */
void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}/* Create basic types: */
cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}/* Create Arrays: */
cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}/* Duplication */
cJSON *cJSON_Duplicate(cJSON *item,int recurse)
{cJSON *newitem,*cptr,*nptr=0,*newchild;/* Bail on bad ptr */if (!item) return 0;/* Create new item */newitem=cJSON_New_Item();if (!newitem) return 0;/* Copy over all vars */newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}/* If non-recursive, then we're done! */if (!recurse) return newitem;/* Walk the ->next chain for the child. */cptr=item->child;while (cptr){newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */if (!newchild) {cJSON_Delete(newitem);return 0;}if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */cptr=cptr->next;}return newitem;
}void cJSON_Minify(char *json)
{char *into=json;while (*json){if (*json==' ') json++;else if (*json=='\t') json++; // Whitespace characters.else if (*json=='\r') json++;else if (*json=='\n') json++;else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line.else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments.else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.else *into++=*json++; // All other characters.}*into=0; // and null-terminate.
}
2、DList 双向链表
后续的动态数组、栈等都可以基于链表实现。网上有开源的。
DList.h
#ifndef __SLIST_H__
#define __SLIST_H__#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "wm_type_def.h"
#include "stdint.h"#ifdef __cplusplus
extern "C" {
#endiftypedef void* LTDataType;
typedef struct ListNode
{LTDataType data;struct ListNode* next;struct ListNode* prev;
}ListNode;//创造节点
ListNode* BuyLTNode(LTDataType x);
// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead, void (*callback)(LTDataType x));
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);// 双向链表查找
ListNode* ListFindItem(ListNode* pHead, LTDataType y, u8 (*callback)(LTDataType x, LTDataType y));// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);u16 ListCount(ListNode* pHead);ListNode* ListGetNodeAt(ListNode* pHead, u32 idx);#ifdef __cplusplus
}
#endif#endif
DList.c
#include "DList.h"
// 创建返回链表的头结点.
ListNode* ListCreate()
{ListNode* head = BuyLTNode(0);head->next = head;//循环列表创建头时头的首尾都指向自己head->prev = head;return head;
}
//创造节点
ListNode* BuyLTNode(LTDataType x)
{ListNode* cur = (ListNode*)malloc(sizeof(ListNode));if (cur == NULL){perror("malloc");exit(-1);}cur->data = x;return cur;}
// 双向链表打印
void ListPrint(ListNode* pHead,void (*callback)(LTDataType x))
{assert(pHead);ListNode* cur = pHead->next;if(callback){while (cur!=pHead){(*callback)(cur->data);cur = cur->next;}}else{while (cur!=pHead){printf("%d->", cur->data);cur = cur->next;}printf("head\n");}
}
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newnode = BuyLTNode(x);newnode->prev = pHead->prev;//要尾插的节点的prev指向原来的尾节点newnode->next = pHead;//要尾插的节点的next指向头pHead->prev->next = newnode;//原来的尾节点的next指向新尾pHead->prev = newnode;//头的prev指向新尾}
// 双向链表尾删
void ListPopBack(ListNode* pHead)
{assert(pHead);assert(pHead->next!=pHead);ListNode* tail = pHead->prev;//用一个指针保存尾巴tail->prev->next = pHead;//将倒数第二个节点的next指向头pHead->prev = tail->prev;//头节点的prev指向倒数第二节点free(tail);}
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newnode = BuyLTNode(x);newnode->next = pHead->next;//新空间的next指向原来的第一个数据newnode->prev = pHead;//新空间的prev指向头pHead->next->prev = newnode;//原来的的一个数据的prev指向newnodepHead->next = newnode;//头的next指向newnode
}
// 双向链表头删
void ListPopFront(ListNode* pHead)
{assert(pHead);assert(pHead->next != pHead);//先判断链表中除了头有无其他数据ListNode* oldnode = pHead->next;//将要删除的数据的位置保存起来,以防后面丢失pHead->next = oldnode->next;//头的next指向第二个数据oldnode->next->prev = pHead;//第二个数据的prev指向头free(oldnode);//释放数据空间即可
}
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{if(pHead == NULL) return NULL;ListNode* cur = pHead->next;while (cur != pHead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}ListNode* ListFindItem(ListNode* pHead, LTDataType y, u8 (*callback)(LTDataType x, LTDataType y)){if(pHead == NULL) return NULL;ListNode* cur = pHead->next;while (cur != pHead){if ((*callback)(cur->data, y)){return cur;}cur = cur->next;}return NULL;
}// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);//调整pos newnode pos前面的数据这三个空间的prev和next即可ListNode* newnode = BuyLTNode(x);ListNode* prev = pos->prev;prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{assert(pos);ListNode* prev = pos->prev;ListNode* next = pos->next;free(pos);prev->next = next;next->prev = prev;}
// 双向链表销毁
void ListDestory(ListNode* pHead)
{if(pHead == NULL) return;ListNode* cur = pHead->next;if(cur == NULL) return;ListNode* next = cur->next;while (cur != pHead)//先释放除头以外的所有节点,再释放头{free(cur);cur = next;next = next->next;}free(cur);
}u16 ListCount(ListNode* pHead){if(pHead == NULL) return 0;u16 c=0;ListNode* cur = pHead->next;while (cur != pHead){c++;cur = cur->next;}return c;
}ListNode* ListGetNodeAt(ListNode* pHead, u32 idx){ListNode* cur = pHead->next;for(u16 i=0;i<idx;i++) cur=cur->next;return cur;
}
3、map组件
便于快速检索资源。开源的。
hashmap.h
/** Generic hashmap manipulation functions** Originally by Elliot C Back - http://elliottback.com/wp/hashmap-implementation-in-c/** Modified by Pete Warden to fix a serious performance problem, support strings as keys* and removed thread synchronization - http://petewarden.typepad.com*/
#ifndef _HASHMAP_H_
#define _HASHMAP_H_#define MAP_MISSING -3 /* No such element */
#define MAP_FULL -2 /* Hashmap is full */
#define MAP_OMEM -1 /* Out of Memory */
#define MAP_OK 0 /* OK */#ifdef __cplusplus
extern "C" {
#endif/** any_t is a pointer. This allows you to put arbitrary structures in* the hashmap.*/
typedef void *any_t;/** PFany is a pointer to a function that can take two any_t arguments* and return an integer. Returns status code..*/
typedef int (*PFany)(any_t, any_t);/** map_t is a pointer to an internally maintained data structure.* Clients of this package do not need to know how hashmaps are* represented. They see and manipulate only map_t's.*/
typedef any_t map_t;/** Return an empty hashmap. Returns NULL if empty.
*/
extern map_t hashmap_new();/** Iteratively call f with argument (item, data) for* each element data in the hashmap. The function must* return a map status code. If it returns anything other* than MAP_OK the traversal is terminated. f must* not reenter any hashmap functions, or deadlock may arise.*/
extern int hashmap_iterate(map_t in, PFany f, any_t item);/** Add an element to the hashmap. Return MAP_OK or MAP_OMEM.*/
extern int hashmap_put(map_t in, char* key, any_t value);/** Get an element from the hashmap. Return MAP_OK or MAP_MISSING.*/
extern int hashmap_get(map_t in, char* key, any_t *arg);/** Remove an element from the hashmap. Return MAP_OK or MAP_MISSING.*/
extern int hashmap_remove(map_t in, char* key);/** Get any element. Return MAP_OK or MAP_MISSING.* remove - should the element be removed from the hashmap*/
extern int hashmap_get_one(map_t in, any_t *arg, int remove);/** Free the hashmap*/
extern void hashmap_free(map_t in);/** Get the current size of a hashmap*/
extern int hashmap_length(map_t in);#ifdef __cplusplus
}
#endif#endif
hashmap.c
/** Generic map implementation.*/
#include "hashmap.h"#include <stdlib.h>
#include <stdio.h>
#include <string.h>#define INITIAL_SIZE (256)
#define MAX_CHAIN_LENGTH (8)/* We need to keep keys and values */
typedef struct _hashmap_element{char* key;int in_use;any_t data;
} hashmap_element;/* A hashmap has some maximum size and current size,* as well as the data to hold. */
typedef struct _hashmap_map{int table_size;int size;hashmap_element *data;
} hashmap_map;/** Return an empty hashmap, or NULL on failure.*/
map_t hashmap_new() {hashmap_map* m = (hashmap_map*) malloc(sizeof(hashmap_map));if(!m) goto err;m->data = (hashmap_element*) calloc(INITIAL_SIZE, sizeof(hashmap_element));if(!m->data) goto err;m->table_size = INITIAL_SIZE;m->size = 0;return m;err:if (m)hashmap_free(m);return NULL;
}/* The implementation here was originally done by Gary S. Brown. I haveborrowed the tables directly, and made some minor changes to thecrc32-function (including changing the interface). //ylo *//* ============================================================= *//* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or *//* code or tables extracted from it, as desired without restriction. *//* *//* First, the polynomial itself and its table of feedback terms. The *//* polynomial is *//* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 *//* *//* Note that we take it "backwards" and put the highest-order term in *//* the lowest-order bit. The X^32 term is "implied"; the LSB is the *//* X^31 term, etc. The X^0 term (usually shown as "+1") results in *//* the MSB being 1. *//* *//* Note that the usual hardware shift register implementation, which *//* is what we're using (we're merely optimizing it by doing eight-bit *//* chunks at a time) shifts bits into the lowest-order term. In our *//* implementation, that means shifting towards the right. Why do we *//* do it this way? Because the calculated CRC must be transmitted in *//* order from highest-order term to lowest-order term. UARTs transmit *//* characters in order from LSB to MSB. By storing the CRC this way, *//* we hand it to the UART in the order low-byte to high-byte; the UART *//* sends each low-bit to hight-bit; and the result is transmission bit *//* by bit from highest- to lowest-order term without requiring any bit *//* shuffling on our part. Reception works similarly. *//* *//* The feedback terms table consists of 256, 32-bit entries. Notes: *//* *//* The table can be generated at runtime if desired; code to do so *//* is shown later. It might not be obvious, but the feedback *//* terms simply represent the results of eight shift/xor opera- *//* tions for all combinations of data and CRC register values. *//* *//* The values must be right-shifted by eight bits by the "updcrc" *//* logic; the shift must be unsigned (bring in zeroes). On some *//* hardware you could probably optimize the shift in assembler by *//* using byte-swap instructions. *//* polynomial $edb88320 *//* *//* -------------------------------------------------------------------- */static unsigned long crc32_tab[] = {0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,0x2d02ef8dL};/* Return a 32-bit CRC of the contents of the buffer. */unsigned long crc32(const unsigned char *s, unsigned int len)
{unsigned int i;unsigned long crc32val;crc32val = 0;for (i = 0; i < len; i ++){crc32val =crc32_tab[(crc32val ^ s[i]) & 0xff] ^(crc32val >> 8);}return crc32val;
}/** Hashing function for a string*/
unsigned int hashmap_hash_int(hashmap_map * m, char* keystring){unsigned long key = crc32((unsigned char*)(keystring), strlen(keystring));/* Robert Jenkins' 32 bit Mix Function */key += (key << 12);key ^= (key >> 22);key += (key << 4);key ^= (key >> 9);key += (key << 10);key ^= (key >> 2);key += (key << 7);key ^= (key >> 12);/* Knuth's Multiplicative Method */key = (key >> 3) * 2654435761;return key % m->table_size;
}/** Return the integer of the location in data* to store the point to the item, or MAP_FULL.*/
int hashmap_hash(map_t in, char* key){int curr;int i;/* Cast the hashmap */hashmap_map* m = (hashmap_map *) in;/* If full, return immediately */if(m->size >= (m->table_size/2)) return MAP_FULL;/* Find the best index */curr = hashmap_hash_int(m, key);/* Linear probing */for(i = 0; i< MAX_CHAIN_LENGTH; i++){if(m->data[curr].in_use == 0)return curr;if(m->data[curr].in_use == 1 && (strcmp(m->data[curr].key,key)==0))return curr;curr = (curr + 1) % m->table_size;}return MAP_FULL;
}/** Doubles the size of the hashmap, and rehashes all the elements*/
int hashmap_rehash(map_t in){int i;int old_size;hashmap_element* curr;/* Setup the new elements */hashmap_map *m = (hashmap_map *) in;hashmap_element* temp = (hashmap_element *)calloc(2 * m->table_size, sizeof(hashmap_element));if(!temp) return MAP_OMEM;/* Update the array */curr = m->data;m->data = temp;/* Update the size */old_size = m->table_size;m->table_size = 2 * m->table_size;m->size = 0;/* Rehash the elements */for(i = 0; i < old_size; i++){int status;if (curr[i].in_use == 0)continue;status = hashmap_put(m, curr[i].key, curr[i].data);if (status != MAP_OK)return status;}free(curr);return MAP_OK;
}/** Add a pointer to the hashmap with some key*/
int hashmap_put(map_t in, char* key, any_t value){int index;hashmap_map* m;/* Cast the hashmap */m = (hashmap_map *) in;/* Find a place to put our value */index = hashmap_hash(in, key);while(index == MAP_FULL){if (hashmap_rehash(in) == MAP_OMEM) {return MAP_OMEM;}index = hashmap_hash(in, key);}/* Set the data */m->data[index].data = value;m->data[index].key = key;m->data[index].in_use = 1;m->size++; return MAP_OK;
}/** Get your pointer out of the hashmap with a key*/
int hashmap_get(map_t in, char* key, any_t *arg){int curr;int i;hashmap_map* m;/* Cast the hashmap */m = (hashmap_map *) in;/* Find data location */curr = hashmap_hash_int(m, key);/* Linear probing, if necessary */for(i = 0; i<MAX_CHAIN_LENGTH; i++){int in_use = m->data[curr].in_use;if (in_use == 1){if (strcmp(m->data[curr].key,key)==0){*arg = (m->data[curr].data);return MAP_OK;}}curr = (curr + 1) % m->table_size;}*arg = NULL;/* Not found */return MAP_MISSING;
}/** Iterate the function parameter over each element in the hashmap. The* additional any_t argument is passed to the function as its first* argument and the hashmap element is the second.*/
int hashmap_iterate(map_t in, PFany f, any_t item) {int i;/* Cast the hashmap */hashmap_map* m = (hashmap_map*) in;/* On empty hashmap, return immediately */if (hashmap_length(m) <= 0)return MAP_MISSING; /* Linear probing */for(i = 0; i< m->table_size; i++)if(m->data[i].in_use != 0) {any_t data = (any_t) (m->data[i].data);int status = f(item, data);if (status != MAP_OK) {return status;}}return MAP_OK;
}/** Remove an element with that key from the map*/
int hashmap_remove(map_t in, char* key){int i;int curr;hashmap_map* m;/* Cast the hashmap */m = (hashmap_map *) in;/* Find key */curr = hashmap_hash_int(m, key);/* Linear probing, if necessary */for(i = 0; i<MAX_CHAIN_LENGTH; i++){int in_use = m->data[curr].in_use;if (in_use == 1){if (strcmp(m->data[curr].key,key)==0){/* Blank out the fields */m->data[curr].in_use = 0;m->data[curr].data = NULL;m->data[curr].key = NULL;/* Reduce the size */m->size--;return MAP_OK;}}curr = (curr + 1) % m->table_size;}/* Data not found */return MAP_MISSING;
}/* Deallocate the hashmap */
void hashmap_free(map_t in){hashmap_map* m = (hashmap_map*) in;free(m->data);free(m);
}/* Return the length of the hashmap */
int hashmap_length(map_t in){hashmap_map* m = (hashmap_map *) in;if(m != NULL) return m->size;else return 0;
}
4、lodePNG图片读取组件
图片统一用PNG格式,没必要耍那么多花样。也是开源的。
lodepng.h
/*
LodePNG version 20230410Copyright (c) 2005-2023 Lode VandevenneThis software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:1. The origin of this software must not be misrepresented; you must notclaim that you wrote the original software. If you use this softwarein a product, an acknowledgment in the product documentation would beappreciated but is not required.2. Altered source versions must be plainly marked as such, and must not bemisrepresented as being the original software.3. This notice may not be removed or altered from any sourcedistribution.
*/#ifndef LODEPNG_H
#define LODEPNG_H#include <string.h> /*for size_t*/extern const char* LODEPNG_VERSION_STRING;/*
The following #defines are used to create code sections. They can be disabled
to disable code sections, which can give faster compile time and smaller binary.
The "NO_COMPILE" defines are designed to be used to pass as defines to the
compiler command to disable them without modifying this header, e.g.
-DLODEPNG_NO_COMPILE_ZLIB for gcc or clang.
*/
/*deflate & zlib. If disabled, you must specify alternative zlib functions in
the custom_zlib field of the compress and decompress settings*/
#ifndef LODEPNG_NO_COMPILE_ZLIB
/*pass -DLODEPNG_NO_COMPILE_ZLIB to the compiler to disable this, or comment out LODEPNG_COMPILE_ZLIB below*/
#define LODEPNG_COMPILE_ZLIB
#endif/*png encoder and png decoder*/
#ifndef LODEPNG_NO_COMPILE_PNG
/*pass -DLODEPNG_NO_COMPILE_PNG to the compiler to disable this, or comment out LODEPNG_COMPILE_PNG below*/
#define LODEPNG_COMPILE_PNG
#endif/*deflate&zlib decoder and png decoder*/
#ifndef LODEPNG_NO_COMPILE_DECODER
/*pass -DLODEPNG_NO_COMPILE_DECODER to the compiler to disable this, or comment out LODEPNG_COMPILE_DECODER below*/
#define LODEPNG_COMPILE_DECODER
#endif/*deflate&zlib encoder and png encoder*/
#ifndef LODEPNG_NO_COMPILE_ENCODER
/*pass -DLODEPNG_NO_COMPILE_ENCODER to the compiler to disable this, or comment out LODEPNG_COMPILE_ENCODER below*/
#define LODEPNG_COMPILE_ENCODER
#endif/*the optional built in harddisk file loading and saving functions*/
#ifndef LODEPNG_NO_COMPILE_DISK
/*pass -DLODEPNG_NO_COMPILE_DISK to the compiler to disable this, or comment out LODEPNG_COMPILE_DISK below*/
#define LODEPNG_COMPILE_DISK
#endif/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/
#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
/*pass -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS to the compiler to disable this,
or comment out LODEPNG_COMPILE_ANCILLARY_CHUNKS below*/
#define LODEPNG_COMPILE_ANCILLARY_CHUNKS
#endif/*ability to convert error numerical codes to English text string*/
#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT
/*pass -DLODEPNG_NO_COMPILE_ERROR_TEXT to the compiler to disable this,
or comment out LODEPNG_COMPILE_ERROR_TEXT below*/
#define LODEPNG_COMPILE_ERROR_TEXT
#endif/*Compile the default allocators (C's free, malloc and realloc). If you disable this,
you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your
source files with custom allocators.*/
#ifndef LODEPNG_NO_COMPILE_ALLOCATORS
/*pass -DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler to disable the built-in ones,
or comment out LODEPNG_COMPILE_ALLOCATORS below*/
#define LODEPNG_COMPILE_ALLOCATORS
#endif/*Disable built-in CRC function, in that case a custom implementation of
lodepng_crc32 must be defined externally so that it can be linked in.
The default built-in CRC code comes with 8KB of lookup tables, so for memory constrained environment you may want it
disabled and provide a much smaller implementation externally as said above. You can find such an example implementation
in a comment in the lodepng.c(pp) file in the 'else' case of the searchable LODEPNG_COMPILE_CRC section.*/
#ifndef LODEPNG_NO_COMPILE_CRC
/*pass -DLODEPNG_NO_COMPILE_CRC to the compiler to disable the built-in one,
or comment out LODEPNG_COMPILE_CRC below*/
#define LODEPNG_COMPILE_CRC
#endif/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/
#ifdef __cplusplus
#ifndef LODEPNG_NO_COMPILE_CPP
/*pass -DLODEPNG_NO_COMPILE_CPP to the compiler to disable C++ (not needed if a C-only compiler),
or comment out LODEPNG_COMPILE_CPP below*/
#define LODEPNG_COMPILE_CPP
#endif
#endif#ifdef LODEPNG_COMPILE_CPP
#include <vector>
#include <string>
#endif /*LODEPNG_COMPILE_CPP*/#ifdef LODEPNG_COMPILE_PNG
/*The PNG color types (also used for raw image).*/
typedef enum LodePNGColorType {LCT_GREY = 0, /*grayscale: 1,2,4,8,16 bit*/LCT_RGB = 2, /*RGB: 8,16 bit*/LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/LCT_GREY_ALPHA = 4, /*grayscale with alpha: 8,16 bit*/LCT_RGBA = 6, /*RGB with alpha: 8,16 bit*//*LCT_MAX_OCTET_VALUE lets the compiler allow this enum to represent any invalidbyte value from 0 to 255 that could be present in an invalid PNG file header. Donot use, compare with or set the name LCT_MAX_OCTET_VALUE, instead either usethe valid color type names above, or numeric values like 1 or 7 when checking forparticular disallowed color type byte values, or cast to integer to print it.*/LCT_MAX_OCTET_VALUE = 255
} LodePNGColorType;#ifdef LODEPNG_COMPILE_DECODERvoid lodepng_free(void* ptr) ;
/*
Converts PNG data in memory to raw pixel data.
out: Output parameter. Pointer to buffer that will contain the raw pixel data.After decoding, its size is w * h * (bytes per pixel) bytes larger thaninitially. Bytes per pixel depends on colortype and bitdepth.Must be freed after usage with free(*out).Note: for 16-bit per channel colors, uses big endian format like PNG does.
w: Output parameter. Pointer to width of pixel data.
h: Output parameter. Pointer to height of pixel data.
in: Memory buffer with the PNG file.
insize: size of the in buffer.
colortype: the desired color type for the raw output image. See explanation on PNG color types.
bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types.
Return value: LodePNG error code (0 means no error).
*/
unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h,const unsigned char* in, size_t insize,LodePNGColorType colortype, unsigned bitdepth);/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/
unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h,const unsigned char* in, size_t insize);/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/
unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h,const unsigned char* in, size_t insize);#ifdef LODEPNG_COMPILE_DISK
/*
Load PNG from disk, from file with given name.
Same as the other decode functions, but instead takes a filename as input.NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and decode in-memory.*/
unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,const char* filename,LodePNGColorType colortype, unsigned bitdepth);/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and decode in-memory.*/
unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,const char* filename);/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and decode in-memory.*/
unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,const char* filename);
#endif /*LODEPNG_COMPILE_DISK*/
#endif /*LODEPNG_COMPILE_DECODER*/#ifdef LODEPNG_COMPILE_ENCODER
/*
Converts raw pixel data into a PNG image in memory. The colortype and bitdepthof the output PNG image cannot be chosen, they are automatically determinedby the colortype, bitdepth and content of the input pixel data.Note: for 16-bit per channel colors, needs big endian format like PNG does.
out: Output parameter. Pointer to buffer that will contain the PNG image data.Must be freed after usage with free(*out).
outsize: Output parameter. Pointer to the size in bytes of the out buffer.
image: The raw pixel data to encode. The size of this buffer should bew * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth.
w: width of the raw pixel data in pixels.
h: height of the raw pixel data in pixels.
colortype: the color type of the raw input image. See explanation on PNG color types.
bitdepth: the bit depth of the raw input image. See explanation on PNG color types.
Return value: LodePNG error code (0 means no error).
*/
unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize,const unsigned char* image, unsigned w, unsigned h,LodePNGColorType colortype, unsigned bitdepth);/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/
unsigned lodepng_encode32(unsigned char** out, size_t* outsize,const unsigned char* image, unsigned w, unsigned h);/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/
unsigned lodepng_encode24(unsigned char** out, size_t* outsize,const unsigned char* image, unsigned w, unsigned h);#ifdef LODEPNG_COMPILE_DISK
/*
Converts raw pixel data into a PNG file on disk.
Same as the other encode functions, but instead takes a filename as output.NOTE: This overwrites existing files without warning!NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and encode in-memory.*/
unsigned lodepng_encode_file(const char* filename,const unsigned char* image, unsigned w, unsigned h,LodePNGColorType colortype, unsigned bitdepth);/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and encode in-memory.*/
unsigned lodepng_encode32_file(const char* filename,const unsigned char* image, unsigned w, unsigned h);/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and encode in-memory.*/
unsigned lodepng_encode24_file(const char* filename,const unsigned char* image, unsigned w, unsigned h);
#endif /*LODEPNG_COMPILE_DISK*/
#endif /*LODEPNG_COMPILE_ENCODER*/#ifdef LODEPNG_COMPILE_CPP
namespace lodepng {
#ifdef LODEPNG_COMPILE_DECODER
/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype
is the format to output the pixels to. Default is RGBA 8-bit per channel.*/
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,const unsigned char* in, size_t insize,LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,const std::vector<unsigned char>& in,LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
#ifdef LODEPNG_COMPILE_DISK
/*
Converts PNG file from disk to raw pixel data in memory.
Same as the other decode functions, but instead takes a filename as input.NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and decode in-memory.
*/
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,const std::string& filename,LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
#endif /* LODEPNG_COMPILE_DISK */
#endif /* LODEPNG_COMPILE_DECODER */#ifdef LODEPNG_COMPILE_ENCODER
/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype
is that of the raw input data. The output PNG color type will be auto chosen.*/
unsigned encode(std::vector<unsigned char>& out,const unsigned char* in, unsigned w, unsigned h,LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
unsigned encode(std::vector<unsigned char>& out,const std::vector<unsigned char>& in, unsigned w, unsigned h,LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
#ifdef LODEPNG_COMPILE_DISK
/*
Converts 32-bit RGBA raw pixel data into a PNG file on disk.
Same as the other encode functions, but instead takes a filename as output.NOTE: This overwrites existing files without warning!NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and decode in-memory.
*/
unsigned encode(const std::string& filename,const unsigned char* in, unsigned w, unsigned h,LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
unsigned encode(const std::string& filename,const std::vector<unsigned char>& in, unsigned w, unsigned h,LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
#endif /* LODEPNG_COMPILE_DISK */
#endif /* LODEPNG_COMPILE_ENCODER */
} /* namespace lodepng */
#endif /*LODEPNG_COMPILE_CPP*/
#endif /*LODEPNG_COMPILE_PNG*/#ifdef LODEPNG_COMPILE_ERROR_TEXT
/*Returns an English description of the numerical error code.*/
const char* lodepng_error_text(unsigned code);
#endif /*LODEPNG_COMPILE_ERROR_TEXT*/#ifdef LODEPNG_COMPILE_DECODER
/*Settings for zlib decompression*/
typedef struct LodePNGDecompressSettings LodePNGDecompressSettings;
struct LodePNGDecompressSettings {/* Check LodePNGDecoderSettings for more ignorable errors such as ignore_crc */unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*//*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding,return an error, output a data size > max_output_size and all the data up to that point. This isnot hard limit nor a guarantee, but can prevent excessive memory usage. This setting isignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones.Set to 0 to impose no limit (the default).*/size_t max_output_size;/*use custom zlib decoder instead of built in one (default: null).Should return 0 if success, any non-0 if error (numeric value not exposed).*/unsigned (*custom_zlib)(unsigned char**, size_t*,const unsigned char*, size_t,const LodePNGDecompressSettings*);/*use custom deflate decoder instead of built in one (default: null)if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate).Should return 0 if success, any non-0 if error (numeric value not exposed).*/unsigned (*custom_inflate)(unsigned char**, size_t*,const unsigned char*, size_t,const LodePNGDecompressSettings*);const void* custom_context; /*optional custom settings for custom functions*/
};extern const LodePNGDecompressSettings lodepng_default_decompress_settings;
void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings);
#endif /*LODEPNG_COMPILE_DECODER*/#ifdef LODEPNG_COMPILE_ENCODER
/*
Settings for zlib compression. Tweaking these settings tweaks the balance
between speed and compression ratio.
*/
typedef struct LodePNGCompressSettings LodePNGCompressSettings;
struct LodePNGCompressSettings /*deflate = compress*/ {/*LZ77 related settings*/unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/unsigned minmatch; /*minimum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*//*use custom zlib encoder instead of built in one (default: null)*/unsigned (*custom_zlib)(unsigned char**, size_t*,const unsigned char*, size_t,const LodePNGCompressSettings*);/*use custom deflate encoder instead of built in one (default: null)if custom_zlib is used, custom_deflate is ignored since only the built inzlib function will call custom_deflate*/unsigned (*custom_deflate)(unsigned char**, size_t*,const unsigned char*, size_t,const LodePNGCompressSettings*);const void* custom_context; /*optional custom settings for custom functions*/
};extern const LodePNGCompressSettings lodepng_default_compress_settings;
void lodepng_compress_settings_init(LodePNGCompressSettings* settings);
#endif /*LODEPNG_COMPILE_ENCODER*/#ifdef LODEPNG_COMPILE_PNG
/*
Color mode of an image. Contains all information required to decode the pixel
bits to RGBA colors. This information is the same as used in the PNG file
format, and is used both for PNG and raw image data in LodePNG.
*/
typedef struct LodePNGColorMode {/*header (IHDR)*/LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*//*palette (PLTE and tRNS)Dynamically allocated with the colors of the palette, including alpha.This field may not be allocated directly, use lodepng_color_mode_init first,then lodepng_palette_add per color to correctly initialize it (to ensure sizeof exactly 1024 bytes).The alpha channels must be set as well, set them to 255 for opaque images.When decoding, with the default settings you can ignore this palette, sinceLodePNG already fills the palette colors in the pixels of the raw RGBA output,but when decoding to the original PNG color mode it is needed to reconstructthe colors.The palette is only supported for color type 3.*/unsigned char* palette; /*palette in RGBARGBA... order. Must be either 0, or when allocated must have 1024 bytes*/size_t palettesize; /*palette size in number of colors (amount of used bytes is 4 * palettesize)*//*transparent color key (tRNS)This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit.For grayscale PNGs, r, g and b will all 3 be set to the same.When decoding, by default you can ignore this information, since LodePNG setspixels with this key to transparent already in the raw RGBA output.The color key is only supported for color types 0 and 2.*/unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/unsigned key_r; /*red/grayscale component of color key*/unsigned key_g; /*green component of color key*/unsigned key_b; /*blue component of color key*/
} LodePNGColorMode;/*init, cleanup and copy functions to use with this struct*/
void lodepng_color_mode_init(LodePNGColorMode* info);
void lodepng_color_mode_cleanup(LodePNGColorMode* info);
/*return value is error code (0 means no error)*/
unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source);
/* Makes a temporary LodePNGColorMode that does not need cleanup (no palette) */
LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth);void lodepng_palette_clear(LodePNGColorMode* info);
/*add 1 color to the palette*/
unsigned lodepng_palette_add(LodePNGColorMode* info,unsigned char r, unsigned char g, unsigned char b, unsigned char a);/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/
unsigned lodepng_get_bpp(const LodePNGColorMode* info);
/*get the amount of color channels used, based on colortype in the struct.
If a palette is used, it counts as 1 channel.*/
unsigned lodepng_get_channels(const LodePNGColorMode* info);
/*is it a grayscale type? (only colortype 0 or 4)*/
unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info);
/*has it got an alpha channel? (only colortype 2 or 6)*/
unsigned lodepng_is_alpha_type(const LodePNGColorMode* info);
/*has it got a palette? (only colortype 3)*/
unsigned lodepng_is_palette_type(const LodePNGColorMode* info);
/*only returns true if there is a palette and there is a value in the palette with alpha < 255.
Loops through the palette to check this.*/
unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info);
/*
Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image.
Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels).
Returns false if the image can only have opaque pixels.
In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values,
or if "key_defined" is true.
*/
unsigned lodepng_can_have_alpha(const LodePNGColorMode* info);
/*Returns the byte size of a raw image buffer with given width, height and color mode*/
size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color);#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
/*The information of a Time chunk in PNG.*/
typedef struct LodePNGTime {unsigned year; /*2 bytes used (0-65535)*/unsigned month; /*1-12*/unsigned day; /*1-31*/unsigned hour; /*0-23*/unsigned minute; /*0-59*/unsigned second; /*0-60 (to allow for leap seconds)*/
} LodePNGTime;
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*//*Information about the PNG image, except pixels, width and height.*/
typedef struct LodePNGInfo {/*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/unsigned compression_method;/*compression method of the original file. Always 0.*/unsigned filter_method; /*filter method of the original file*/unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS/*Suggested background color chunk (bKGD)This uses the same color mode and bit depth as the PNG (except no alpha channel),with values truncated to the bit depth in the unsigned integer.For grayscale and palette PNGs, the value is stored in background_r. The valuesin background_g and background_b are then unused. The decoder will set themequal to background_r, the encoder ignores them in this case.When decoding, you may get these in a different color mode than the one you requestedfor the raw pixels: the colortype and bitdepth defined by info_png.color, that is theones defined in the header of the PNG image, are used.When encoding with auto_convert, you must use the color model defined in info_png.color forthese values. The encoder normally ignores info_png.color when auto_convert is on, but willuse it to interpret these values (and convert copies of them to its chosen color model).When encoding, avoid setting this to an expensive color, such as a non-gray valuewhen the image is gray, or the compression will be worse since it will be forced towrite the PNG with a more expensive color mode (when auto_convert is on).The decoder does not use this background color to edit the color of pixels. This is acompletely optional metadata feature.*/unsigned background_defined; /*is a suggested background color given?*/unsigned background_r; /*red/gray/palette component of suggested background color*/unsigned background_g; /*green component of suggested background color*/unsigned background_b; /*blue component of suggested background color*//*Non-international text chunks (tEXt and zTXt)The char** arrays each contain num strings. The actual messages are intext_strings, while text_keys are keywords that give a short description whatthe actual text represents, e.g. Title, Author, Description, or anything else.All the string fields below including strings, keys, names and language tags are null terminated.The PNG specification uses null characters for the keys, names and tags, and forbids nullcharacters to appear in the main text which is why we can use null termination everywhere here.A keyword is minimum 1 character and maximum 79 characters long (plus theadditional null terminator). It's discouraged to use a single line lengthlonger than 79 characters for texts.Don't allocate these text buffers yourself. Use the init/cleanup functionscorrectly and use lodepng_add_text and lodepng_clear_text.Standard text chunk keywords and strings are encoded using Latin-1.*/size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/char** text_strings; /*the actual text*//*International text chunks (iTXt)Similar to the non-international text chunks, but with additional strings"langtags" and "transkeys", and the following text encodings are used:keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8.keys must be 1-79 characters (plus the additional null terminator), the otherstrings are any length.*/size_t itext_num; /*the amount of international texts in this PNG*/char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/char** itext_strings; /*the actual international text - UTF-8 string*//*time chunk (tIME)*/unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/LodePNGTime time;/*phys chunk (pHYs)*/unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/unsigned phys_x; /*pixels per unit in x direction*/unsigned phys_y; /*pixels per unit in y direction*/unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*//*Color profile related chunks: gAMA, cHRM, sRGB, iCPP, sBITLodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these colorprofile values. It merely passes on the information. If you wish to use color profiles and convert colors, pleaseuse these values with a color management library.See the PNG, ICC and sRGB specifications for more information about the meaning of these values.*//* gAMA chunk: optional, overridden by sRGB or iCCP if those are present. */unsigned gama_defined; /* Whether a gAMA chunk is present (0 = not present, 1 = present). */unsigned gama_gamma; /* Gamma exponent times 100000 *//* cHRM chunk: optional, overridden by sRGB or iCCP if those are present. */unsigned chrm_defined; /* Whether a cHRM chunk is present (0 = not present, 1 = present). */unsigned chrm_white_x; /* White Point x times 100000 */unsigned chrm_white_y; /* White Point y times 100000 */unsigned chrm_red_x; /* Red x times 100000 */unsigned chrm_red_y; /* Red y times 100000 */unsigned chrm_green_x; /* Green x times 100000 */unsigned chrm_green_y; /* Green y times 100000 */unsigned chrm_blue_x; /* Blue x times 100000 */unsigned chrm_blue_y; /* Blue y times 100000 *//*sRGB chunk: optional. May not appear at the same time as iCCP.If gAMA is also present gAMA must contain value 45455.If cHRM is also present cHRM must contain respectively 31270,32900,64000,33000,30000,60000,15000,6000.*/unsigned srgb_defined; /* Whether an sRGB chunk is present (0 = not present, 1 = present). */unsigned srgb_intent; /* Rendering intent: 0=perceptual, 1=rel. colorimetric, 2=saturation, 3=abs. colorimetric *//*iCCP chunk: optional. May not appear at the same time as sRGB.LodePNG does not parse or use the ICC profile (except its color space header field for an edge case), aseparate library to handle the ICC data (not included in LodePNG) format is needed to use it for colormanagement and conversions.For encoding, if iCCP is present, gAMA and cHRM are recommended to be added as well with values that match the ICCprofile as closely as possible, if you wish to do this you should provide the correct values for gAMA and cHRM andenable their '_defined' flags since LodePNG will not automatically compute them from the ICC profile.For encoding, the ICC profile is required by the PNG specification to be an "RGB" profile for non-grayPNG color types and a "GRAY" profile for gray PNG color types. If you disable auto_convert, you must ensurethe ICC profile type matches your requested color type, else the encoder gives an error. If auto_convert isenabled (the default), and the ICC profile is not a good match for the pixel data, this will result in an encodererror if the pixel data has non-gray pixels for a GRAY profile, or a silent less-optimal compression of the pixeldata if the pixels could be encoded as grayscale but the ICC profile is RGB.To avoid this do not set an ICC profile in the image unless there is a good reason for it, and when doing somake sure you compute it carefully to avoid the above problems.*/unsigned iccp_defined; /* Whether an iCCP chunk is present (0 = not present, 1 = present). */char* iccp_name; /* Null terminated string with profile name, 1-79 bytes *//*The ICC profile in iccp_profile_size bytes.Don't allocate this buffer yourself. Use the init/cleanup functionscorrectly and use lodepng_set_icc and lodepng_clear_icc.*/unsigned char* iccp_profile;unsigned iccp_profile_size; /* The size of iccp_profile in bytes *//*sBIT chunk: significant bits. Optional metadata, only set this if needed.If defined, these values give the bit depth of the original data. Since PNG only stores 1, 2, 4, 8 or 16-bitper channel data, the significant bits value can be used to indicate the original encoded data has anothersample depth, such as 10 or 12.Encoders using this value, when storing the pixel data, should use the most significant bitsof the data to store the original bits, and use a good sample depth scaling method such as"left bit replication" to fill in the least significant bits, rather than fill zeroes.Decoders using this value, if able to work with data that's e.g. 10-bit or 12-bit, should rightshift the data to go back to the original bit depth, but decoders are also allowed to ignoresbit and work e.g. with the 8-bit or 16-bit data from the PNG directly, since thanksto the encoder contract, the values encoded in PNG are in valid range for the PNG bit depth.For grayscale images, sbit_g and sbit_b are not used, and for images that don't use colortype RGBA or grayscale+alpha, sbit_a is not used (it's not used even for palette images withtranslucent palette values, or images with color key). The values that are used must begreater than zero and smaller than or equal to the PNG bit depth.The color type from the header in the PNG image defines these used and unused fields: ifdecoding with a color mode conversion, such as always decoding to RGBA, this metadata stillonly uses the color type of the original PNG, and may e.g. lack the alpha channel infoif the PNG was RGB. When encoding with auto_convert (as well as without), also always thecolor model defined in info_png.color determines this.NOTE: enabling sbit can hurt compression, because the encoder can then not always useauto_convert to choose a more optimal color mode for the data, because the PNG format hasstrict requirements for the allowed sbit values in combination with color modes.For example, setting these fields to 10-bit will force the encoder to keep using a 16-bit per channelcolor mode, even if the pixel data would in fact fit in a more efficient 8-bit mode.*/unsigned sbit_defined; /*is significant bits given? if not, the values below are unused*/unsigned sbit_r; /*red or gray component of significant bits*/unsigned sbit_g; /*green component of significant bits*/unsigned sbit_b; /*blue component of significant bits*/unsigned sbit_a; /*alpha component of significant bits*//* End of color profile related chunks *//*unknown chunks: chunks not known by LodePNG, passed on byte for byte.There are 3 buffers, one for each position in the PNG where unknown chunks can appear.Each buffer contains all unknown chunks for that position consecutively.The 3 positions are:0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND.For encoding, do not store critical chunks or known chunks that are enabled with a "_defined" flagabove in here, since the encoder will blindly follow this and could then encode an invalid PNG file(such as one with two IHDR chunks or the disallowed combination of sRGB with iCCP). But do usethis if you wish to store an ancillary chunk that is not supported by LodePNG (such as sPLT or hIST),or any non-standard PNG chunk.Do not allocate or traverse this data yourself. Use the chunk traversing functions declaredlater, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct.*/unsigned char* unknown_chunks_data[3];size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
} LodePNGInfo;/*init, cleanup and copy functions to use with this struct*/
void lodepng_info_init(LodePNGInfo* info);
void lodepng_info_cleanup(LodePNGInfo* info);
/*return value is error code (0 means no error)*/
unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source);#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/
void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/
void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*//*replaces if exists*/
unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size);
void lodepng_clear_icc(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*//*
Converts raw buffer from one color type to another color type, based on
LodePNGColorMode structs to describe the input and output color type.
See the reference manual at the end of this header file to see which color conversions are supported.
return value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported)
The out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel
of the output color type (lodepng_get_bpp).
For < 8 bpp images, there should not be padding bits at the end of scanlines.
For 16-bit per channel colors, uses big endian format like PNG does.
Return value is LodePNG error code
*/
unsigned lodepng_convert(unsigned char* out, const unsigned char* in,const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,unsigned w, unsigned h);#ifdef LODEPNG_COMPILE_DECODER
/*
Settings for the decoder. This contains settings for the PNG and the Zlib
decoder, but not the Info settings from the Info structs.
*/
typedef struct LodePNGDecoderSettings {LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*//* Check LodePNGDecompressSettings for more ignorable errors such as ignore_adler32 */unsigned ignore_crc; /*ignore CRC checksums*/unsigned ignore_critical; /*ignore unknown critical chunks*/unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*//* TODO: make a system involving warnings with levels and a strict mode instead. Other potentially recoverableerrors: srgb rendering intent value, size of content of ancillary chunks, more than 79 characters for somestrings, placement/combination rules for ancillary chunks, crc of unknown chunks, allowed charactersin string keys, etc... */unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKSunsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*//*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/unsigned remember_unknown_chunks;/* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned,unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size.By default it is a value that prevents unreasonably large strings from hogging memory. */size_t max_text_size;/* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than anylegitimate profile could be to hog memory. */size_t max_icc_size;
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
} LodePNGDecoderSettings;void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings);
#endif /*LODEPNG_COMPILE_DECODER*/#ifdef LODEPNG_COMPILE_ENCODER
/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/
typedef enum LodePNGFilterStrategy {/*every filter at zero*/LFS_ZERO = 0,/*every filter at 1, 2, 3 or 4 (paeth), unlike LFS_ZERO not a good choice, but for testing*/LFS_ONE = 1,LFS_TWO = 2,LFS_THREE = 3,LFS_FOUR = 4,/*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/LFS_MINSUM,/*Use the filter type that gives smallest Shannon entropy for this scanline. Dependingon the image, this is better or worse than minsum.*/LFS_ENTROPY,/*Brute-force-search PNG filters by compressing each filter for each scanline.Experimental, very slow, and only rarely gives better compression than MINSUM.*/LFS_BRUTE_FORCE,/*use predefined_filters buffer: you specify the filter type for each scanline*/LFS_PREDEFINED
} LodePNGFilterStrategy;/*Gives characteristics about the integer RGBA colors of the image (count, alpha channel usage, bit depth, ...),
which helps decide which color model to use for encoding.
Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms.*/
typedef struct LodePNGColorStats {unsigned colored; /*not grayscale*/unsigned key; /*image is not opaque and color key is possible instead of full alpha*/unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/unsigned short key_g;unsigned short key_b;unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16 or allow_palette is disabled.*/unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order, only valid when numcolors is valid*/unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for grayscale only. 16 if 16-bit per channel required.*/size_t numpixels;/*user settings for computing/using the stats*/unsigned allow_palette; /*default 1. if 0, disallow choosing palette colortype in auto_choose_color, and don't count numcolors*/unsigned allow_greyscale; /*default 1. if 0, choose RGB or RGBA even if the image only has gray colors*/
} LodePNGColorStats;void lodepng_color_stats_init(LodePNGColorStats* stats);/*Get a LodePNGColorStats of the image. The stats must already have been inited.
Returns error code (e.g. alloc fail) or 0 if ok.*/
unsigned lodepng_compute_color_stats(LodePNGColorStats* stats,const unsigned char* image, unsigned w, unsigned h,const LodePNGColorMode* mode_in);/*Settings for the encoder.*/
typedef struct LodePNGEncoderSettings {LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/unsigned auto_convert; /*automatically choose output PNG color type. Default: true*//*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that tocompletely follow the official PNG heuristic, filter_palette_zero must be true andfilter_strategy must be LFS_MINSUM*/unsigned filter_palette_zero;/*Which filter strategy to use when not using zeroes due to filter_palette_zero.Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/LodePNGFilterStrategy filter_strategy;/*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer withthe same length as the amount of scanlines in the image, and each value must <= 5. Youhave to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zeromust be set to 0 to ensure this is also used on palette or low bitdepth images.*/const unsigned char* predefined_filters;/*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette).If colortype is 3, PLTE is always created. If color type is explicitely setto a grayscale type (1 or 4), this is not done and is ignored. If enabling this,a palette must be present in the info_png.NOTE: enabling this may worsen compression if auto_convert is used to chooseoptimal color mode, because it cannot use grayscale color modes in this case*/unsigned force_palette;
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS/*add LodePNG identifier and version as a text chunk, for debugging*/unsigned add_id;/*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/unsigned text_compression;
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
} LodePNGEncoderSettings;void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings);
#endif /*LODEPNG_COMPILE_ENCODER*/#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)
/*The settings, state and information for extended encoding and decoding.*/
typedef struct LodePNGState {
#ifdef LODEPNG_COMPILE_DECODERLodePNGDecoderSettings decoder; /*the decoding settings*/
#endif /*LODEPNG_COMPILE_DECODER*/
#ifdef LODEPNG_COMPILE_ENCODERLodePNGEncoderSettings encoder; /*the encoding settings*/
#endif /*LODEPNG_COMPILE_ENCODER*/LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/unsigned error;
} LodePNGState;/*init, cleanup and copy functions to use with this struct*/
void lodepng_state_init(LodePNGState* state);
void lodepng_state_cleanup(LodePNGState* state);
void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source);
#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */#ifdef LODEPNG_COMPILE_DECODER
/*
Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and
getting much more information about the PNG image and color mode.
*/
unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,LodePNGState* state,const unsigned char* in, size_t insize);/*
Read the PNG header, but not the actual data. This returns only the information
that is in the IHDR chunk of the PNG, such as width, height and color type. The
information is placed in the info_png field of the LodePNGState.
*/
unsigned lodepng_inspect(unsigned* w, unsigned* h,LodePNGState* state,const unsigned char* in, size_t insize);
#endif /*LODEPNG_COMPILE_DECODER*//*
Reads one metadata chunk (other than IHDR, which is handled by lodepng_inspect)
of the PNG file and outputs what it read in the state. Returns error code on failure.
Use lodepng_inspect first with a new state, then e.g. lodepng_chunk_find_const
to find the desired chunk type, and if non null use lodepng_inspect_chunk (with
chunk_pointer - start_of_file as pos).
Supports most metadata chunks from the PNG standard (gAMA, bKGD, tEXt, ...).
Ignores unsupported, unknown, non-metadata or IHDR chunks (without error).
Requirements: &in[pos] must point to start of a chunk, must use regular
lodepng_inspect first since format of most other chunks depends on IHDR, and if
there is a PLTE chunk, that one must be inspected before tRNS or bKGD.
*/
unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,const unsigned char* in, size_t insize);#ifdef LODEPNG_COMPILE_ENCODER
/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/
unsigned lodepng_encode(unsigned char** out, size_t* outsize,const unsigned char* image, unsigned w, unsigned h,LodePNGState* state);
#endif /*LODEPNG_COMPILE_ENCODER*//*
The lodepng_chunk functions are normally not needed, except to traverse the
unknown chunks stored in the LodePNGInfo struct, or add new ones to it.
It also allows traversing the chunks of an encoded PNG file yourself.The chunk pointer always points to the beginning of the chunk itself, that is
the first byte of the 4 length bytes.In the PNG file format, chunks have the following format:
-4 bytes length: length of the data of the chunk in bytes (chunk itself is 12 bytes longer)
-4 bytes chunk type (ASCII a-z,A-Z only, see below)
-length bytes of data (may be 0 bytes if length was 0)
-4 bytes of CRC, computed on chunk name + dataThe first chunk starts at the 8th byte of the PNG file, the entire rest of the file
exists out of concatenated chunks with the above format.PNG standard chunk ASCII naming conventions:
-First byte: uppercase = critical, lowercase = ancillary
-Second byte: uppercase = public, lowercase = private
-Third byte: must be uppercase
-Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy
*//*
Gets the length of the data of the chunk. Total chunk length has 12 bytes more.
There must be at least 4 bytes to read from. If the result value is too large,
it may be corrupt data.
*/
unsigned lodepng_chunk_length(const unsigned char* chunk);/*puts the 4-byte type in null terminated string*/
void lodepng_chunk_type(char type[5], const unsigned char* chunk);/*check if the type is the given type*/
unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type);/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/
unsigned char lodepng_chunk_ancillary(const unsigned char* chunk);/*0: public, 1: private (see PNG standard)*/
unsigned char lodepng_chunk_private(const unsigned char* chunk);/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/
unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk);/*get pointer to the data of the chunk, where the input points to the header of the chunk*/
unsigned char* lodepng_chunk_data(unsigned char* chunk);
const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk);/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/
unsigned lodepng_chunk_check_crc(const unsigned char* chunk);/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/
void lodepng_chunk_generate_crc(unsigned char* chunk);/*
Iterate to next chunks, allows iterating through all chunks of the PNG file.
Input must be at the beginning of a chunk (result of a previous lodepng_chunk_next call,
or the 8th byte of a PNG file which always has the first chunk), or alternatively may
point to the first byte of the PNG file (which is not a chunk but the magic header, the
function will then skip over it and return the first real chunk).
Will output pointer to the start of the next chunk, or at or beyond end of the file if there
is no more chunk after this or possibly if the chunk is corrupt.
Start this process at the 8th byte of the PNG file.
In a non-corrupt PNG file, the last chunk should have name "IEND".
*/
unsigned char* lodepng_chunk_next(unsigned char* chunk, unsigned char* end);
const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk, const unsigned char* end);/*Finds the first chunk with the given type in the range [chunk, end), or returns NULL if not found.*/
unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, const char type[5]);
const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]);/*
Appends chunk to the data in out. The given chunk should already have its chunk header.
The out variable and outsize are updated to reflect the new reallocated buffer.
Returns error code (0 if it went ok)
*/
unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk);/*
Appends new chunk to out. The chunk to append is given by giving its length, type
and data separately. The type is a 4-letter string.
The out variable and outsize are updated to reflect the new reallocated buffer.
Returne error code (0 if it went ok)
*/
unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, size_t length,const char* type, const unsigned char* data);/*Calculate CRC32 of buffer*/
unsigned lodepng_crc32(const unsigned char* buf, size_t len);
#endif /*LODEPNG_COMPILE_PNG*/#ifdef LODEPNG_COMPILE_ZLIB
/*
This zlib part can be used independently to zlib compress and decompress a
buffer. It cannot be used to create gzip files however, and it only supports the
part of zlib that is required for PNG, it does not support dictionaries.
*/#ifdef LODEPNG_COMPILE_DECODER
/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/
unsigned lodepng_inflate(unsigned char** out, size_t* outsize,const unsigned char* in, size_t insize,const LodePNGDecompressSettings* settings);/*
Decompresses Zlib data. Reallocates the out buffer and appends the data. The
data must be according to the zlib specification.
Either, *out must be NULL and *outsize must be 0, or, *out must be a valid
buffer and *outsize its size in bytes. out must be freed by user after usage.
*/
unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize,const unsigned char* in, size_t insize,const LodePNGDecompressSettings* settings);
#endif /*LODEPNG_COMPILE_DECODER*/#ifdef LODEPNG_COMPILE_ENCODER
/*
Compresses data with Zlib. Reallocates the out buffer and appends the data.
Zlib adds a small header and trailer around the deflate data.
The data is output in the format of the zlib specification.
Either, *out must be NULL and *outsize must be 0, or, *out must be a valid
buffer and *outsize its size in bytes. out must be freed by user after usage.
*/
unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize,const unsigned char* in, size_t insize,const LodePNGCompressSettings* settings);/*
Find length-limited Huffman code for given frequencies. This function is in the
public interface only for tests, it's used internally by lodepng_deflate.
*/
unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,size_t numcodes, unsigned maxbitlen);/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/
unsigned lodepng_deflate(unsigned char** out, size_t* outsize,const unsigned char* in, size_t insize,const LodePNGCompressSettings* settings);#endif /*LODEPNG_COMPILE_ENCODER*/
#endif /*LODEPNG_COMPILE_ZLIB*/#ifdef LODEPNG_COMPILE_DISK
/*
Load a file from disk into buffer. The function allocates the out buffer, and
after usage you should free it.
out: output parameter, contains pointer to loaded buffer.
outsize: output parameter, size of the allocated out buffer
filename: the path to the file to load
return value: error code (0 means ok)NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and decode in-memory.
*/
unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);/*
Save a file from buffer to disk. Warning, if it exists, this function overwrites
the file without warning!
buffer: the buffer to write
buffersize: size of the buffer to write
filename: the path to the file to save to
return value: error code (0 means ok)NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and encode in-memory
*/
unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);
#endif /*LODEPNG_COMPILE_DISK*/#ifdef LODEPNG_COMPILE_CPP
/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */
namespace lodepng {
#ifdef LODEPNG_COMPILE_PNG
class State : public LodePNGState {public:State();State(const State& other);~State();State& operator=(const State& other);
};#ifdef LODEPNG_COMPILE_DECODER
/* Same as other lodepng::decode, but using a State for more settings and information. */
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,State& state,const unsigned char* in, size_t insize);
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,State& state,const std::vector<unsigned char>& in);
#endif /*LODEPNG_COMPILE_DECODER*/#ifdef LODEPNG_COMPILE_ENCODER
/* Same as other lodepng::encode, but using a State for more settings and information. */
unsigned encode(std::vector<unsigned char>& out,const unsigned char* in, unsigned w, unsigned h,State& state);
unsigned encode(std::vector<unsigned char>& out,const std::vector<unsigned char>& in, unsigned w, unsigned h,State& state);
#endif /*LODEPNG_COMPILE_ENCODER*/#ifdef LODEPNG_COMPILE_DISK
/*
Load a file from disk into an std::vector.
return value: error code (0 means ok)NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and decode in-memory
*/
unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);/*
Save the binary data in an std::vector to a file on disk. The file is overwritten
without warning.NOTE: Wide-character filenames are not supported, you can use an external method
to handle such files and encode in-memory
*/
unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
#endif /* LODEPNG_COMPILE_DISK */
#endif /* LODEPNG_COMPILE_PNG */#ifdef LODEPNG_COMPILE_ZLIB
#ifdef LODEPNG_COMPILE_DECODER
/* Zlib-decompress an unsigned char buffer */
unsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);/* Zlib-decompress an std::vector */
unsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);
#endif /* LODEPNG_COMPILE_DECODER */#ifdef LODEPNG_COMPILE_ENCODER
/* Zlib-compress an unsigned char buffer */
unsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,const LodePNGCompressSettings& settings = lodepng_default_compress_settings);/* Zlib-compress an std::vector */
unsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,const LodePNGCompressSettings& settings = lodepng_default_compress_settings);
#endif /* LODEPNG_COMPILE_ENCODER */
#endif /* LODEPNG_COMPILE_ZLIB */
} /* namespace lodepng */
#endif /*LODEPNG_COMPILE_CPP*/
lodepng.cpp
附资源
这篇关于W801学习笔记十三:掌机系统——系统基础组件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!