123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 |
- /*
- * File : image_xpm.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2009-10-16 Bernard first version
- */
- #include <stdio.h>
- #include <string.h>
- #include <rtgui/filerw.h>
- #include <rtgui/image_xpm.h>
- #include <rtgui/rtgui_system.h>
- #define XPM_MAGIC_LEN 9
- static rt_bool_t rtgui_image_xpm_check(struct rtgui_filerw * file);
- static rt_bool_t rtgui_image_xpm_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
- static void rtgui_image_xpm_unload(struct rtgui_image* image);
- static void rtgui_image_xpm_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
- struct rtgui_image_engine rtgui_image_xpm_engine =
- {
- "xpm",
- {RT_NULL},
- rtgui_image_xpm_check,
- rtgui_image_xpm_load,
- rtgui_image_xpm_unload,
- rtgui_image_xpm_blit
- };
- struct rgb_item
- {
- char *name;
- int r;
- int g;
- int b;
- };
- const struct rgb_item rgbRecord[234] = {
- {"AliceBlue", 240, 248, 255},
- {"AntiqueWhite", 250, 235, 215},
- {"Aquamarine", 50, 191, 193},
- {"Azure", 240, 255, 255},
- {"Beige", 245, 245, 220},
- {"Bisque", 255, 228, 196},
- {"Black", 0, 0, 0},
- {"BlanchedAlmond", 255, 235, 205},
- {"Blue", 0, 0, 255},
- {"BlueViolet", 138, 43, 226},
- {"Brown", 165, 42, 42},
- {"burlywood", 222, 184, 135},
- {"CadetBlue", 95, 146, 158},
- {"chartreuse", 127, 255, 0},
- {"chocolate", 210, 105, 30},
- {"Coral", 255, 114, 86},
- {"CornflowerBlue", 34, 34, 152},
- {"cornsilk", 255, 248, 220},
- {"Cyan", 0, 255, 255},
- {"DarkGoldenrod", 184, 134, 11},
- {"DarkGreen", 0, 86, 45},
- {"DarkKhaki", 189, 183, 107},
- {"DarkOliveGreen", 85, 86, 47},
- {"DarkOrange", 255, 140, 0},
- {"DarkOrchid", 139, 32, 139},
- {"DarkSalmon", 233, 150, 122},
- {"DarkSeaGreen", 143, 188, 143},
- {"DarkSlateBlue", 56, 75, 102},
- {"DarkSlateGray", 47, 79, 79},
- {"DarkTurquoise", 0, 166, 166},
- {"DarkViolet", 148, 0, 211},
- {"DeepPink", 255, 20, 147},
- {"DeepSkyBlue", 0, 191, 255},
- {"DimGray", 84, 84, 84},
- {"DodgerBlue", 30, 144, 255},
- {"Firebrick", 142, 35, 35},
- {"FloralWhite", 255, 250, 240},
- {"ForestGreen", 80, 159, 105},
- {"gainsboro", 220, 220, 220},
- {"GhostWhite", 248, 248, 255},
- {"Gold", 218, 170, 0},
- {"Goldenrod", 239, 223, 132},
- {"Gray", 126, 126, 126},
- {"Gray0", 0, 0, 0},
- {"Gray1", 3, 3, 3},
- {"Gray10", 26, 26, 26},
- {"Gray100", 255, 255, 255},
- {"Gray11", 28, 28, 28},
- {"Gray12", 31, 31, 31},
- {"Gray13", 33, 33, 33},
- {"Gray14", 36, 36, 36},
- {"Gray15", 38, 38, 38},
- {"Gray16", 41, 41, 41},
- {"Gray17", 43, 43, 43},
- {"Gray18", 46, 46, 46},
- {"Gray19", 48, 48, 48},
- {"Gray2", 5, 5, 5},
- {"Gray20", 51, 51, 51},
- {"Gray21", 54, 54, 54},
- {"Gray22", 56, 56, 56},
- {"Gray23", 59, 59, 59},
- {"Gray24", 61, 61, 61},
- {"Gray25", 64, 64, 64},
- {"Gray26", 66, 66, 66},
- {"Gray27", 69, 69, 69},
- {"Gray28", 71, 71, 71},
- {"Gray29", 74, 74, 74},
- {"Gray3", 8, 8, 8},
- {"Gray30", 77, 77, 77},
- {"Gray31", 79, 79, 79},
- {"Gray32", 82, 82, 82},
- {"Gray33", 84, 84, 84},
- {"Gray34", 87, 87, 87},
- {"Gray35", 89, 89, 89},
- {"Gray36", 92, 92, 92},
- {"Gray37", 94, 94, 94},
- {"Gray38", 97, 97, 97},
- {"Gray39", 99, 99, 99},
- {"Gray4", 10, 10, 10},
- {"Gray40", 102, 102, 102},
- {"Gray41", 105, 105, 105},
- {"Gray42", 107, 107, 107},
- {"Gray43", 110, 110, 110},
- {"Gray44", 112, 112, 112},
- {"Gray45", 115, 115, 115},
- {"Gray46", 117, 117, 117},
- {"Gray47", 120, 120, 120},
- {"Gray48", 122, 122, 122},
- {"Gray49", 125, 125, 125},
- {"Gray5", 13, 13, 13},
- {"Gray50", 127, 127, 127},
- {"Gray51", 130, 130, 130},
- {"Gray52", 133, 133, 133},
- {"Gray53", 135, 135, 135},
- {"Gray54", 138, 138, 138},
- {"Gray55", 140, 140, 140},
- {"Gray56", 143, 143, 143},
- {"Gray57", 145, 145, 145},
- {"Gray58", 148, 148, 148},
- {"Gray59", 150, 150, 150},
- {"Gray6", 15, 15, 15},
- {"Gray60", 153, 153, 153},
- {"Gray61", 156, 156, 156},
- {"Gray62", 158, 158, 158},
- {"Gray63", 161, 161, 161},
- {"Gray64", 163, 163, 163},
- {"Gray65", 166, 166, 166},
- {"Gray66", 168, 168, 168},
- {"Gray67", 171, 171, 171},
- {"Gray68", 173, 173, 173},
- {"Gray69", 176, 176, 176},
- {"Gray7", 18, 18, 18},
- {"Gray70", 179, 179, 179},
- {"Gray71", 181, 181, 181},
- {"Gray72", 184, 184, 184},
- {"Gray73", 186, 186, 186},
- {"Gray74", 189, 189, 189},
- {"Gray75", 191, 191, 191},
- {"Gray76", 194, 194, 194},
- {"Gray77", 196, 196, 196},
- {"Gray78", 199, 199, 199},
- {"Gray79", 201, 201, 201},
- {"Gray8", 20, 20, 20},
- {"Gray80", 204, 204, 204},
- {"Gray81", 207, 207, 207},
- {"Gray82", 209, 209, 209},
- {"Gray83", 212, 212, 212},
- {"Gray84", 214, 214, 214},
- {"Gray85", 217, 217, 217},
- {"Gray86", 219, 219, 219},
- {"Gray87", 222, 222, 222},
- {"Gray88", 224, 224, 224},
- {"Gray89", 227, 227, 227},
- {"Gray9", 23, 23, 23},
- {"Gray90", 229, 229, 229},
- {"Gray91", 232, 232, 232},
- {"Gray92", 235, 235, 235},
- {"Gray93", 237, 237, 237},
- {"Gray94", 240, 240, 240},
- {"Gray95", 242, 242, 242},
- {"Gray96", 245, 245, 245},
- {"Gray97", 247, 247, 247},
- {"Gray98", 250, 250, 250},
- {"Gray99", 252, 252, 252},
- {"Green", 0, 255, 0},
- {"GreenYellow", 173, 255, 47},
- {"honeydew", 240, 255, 240},
- {"HotPink", 255, 105, 180},
- {"IndianRed", 107, 57, 57},
- {"ivory", 255, 255, 240},
- {"Khaki", 179, 179, 126},
- {"lavender", 230, 230, 250},
- {"LavenderBlush", 255, 240, 245},
- {"LawnGreen", 124, 252, 0},
- {"LemonChiffon", 255, 250, 205},
- {"LightBlue", 176, 226, 255},
- {"LightCoral", 240, 128, 128},
- {"LightCyan", 224, 255, 255},
- {"LightGoldenrod", 238, 221, 130},
- {"LightGoldenrodYellow", 250, 250, 210},
- {"LightGray", 168, 168, 168},
- {"LightPink", 255, 182, 193},
- {"LightSalmon", 255, 160, 122},
- {"LightSeaGreen", 32, 178, 170},
- {"LightSkyBlue", 135, 206, 250},
- {"LightSlateBlue", 132, 112, 255},
- {"LightSlateGray", 119, 136, 153},
- {"LightSteelBlue", 124, 152, 211},
- {"LightYellow", 255, 255, 224},
- {"LimeGreen", 0, 175, 20},
- {"linen", 250, 240, 230},
- {"Magenta", 255, 0, 255},
- {"Maroon", 143, 0, 82},
- {"MediumAquamarine", 0, 147, 143},
- {"MediumBlue", 50, 50, 204},
- {"MediumForestGreen", 50, 129, 75},
- {"MediumGoldenrod", 209, 193, 102},
- {"MediumOrchid", 189, 82, 189},
- {"MediumPurple", 147, 112, 219},
- {"MediumSeaGreen", 52, 119, 102},
- {"MediumSlateBlue", 106, 106, 141},
- {"MediumSpringGreen", 35, 142, 35},
- {"MediumTurquoise", 0, 210, 210},
- {"MediumVioletRed", 213, 32, 121},
- {"MidnightBlue", 47, 47, 100},
- {"MintCream", 245, 255, 250},
- {"MistyRose", 255, 228, 225},
- {"moccasin", 255, 228, 181},
- {"NavajoWhite", 255, 222, 173},
- {"Navy", 35, 35, 117},
- {"NavyBlue", 35, 35, 117},
- {"OldLace", 253, 245, 230},
- {"OliveDrab", 107, 142, 35},
- {"Orange", 255, 135, 0},
- {"OrangeRed", 255, 69, 0},
- {"Orchid", 239, 132, 239},
- {"PaleGoldenrod", 238, 232, 170},
- {"PaleGreen", 115, 222, 120},
- {"PaleTurquoise", 175, 238, 238},
- {"PaleVioletRed", 219, 112, 147},
- {"PapayaWhip", 255, 239, 213},
- {"PeachPuff", 255, 218, 185},
- {"peru", 205, 133, 63},
- {"Pink", 255, 181, 197},
- {"Plum", 197, 72, 155},
- {"PowderBlue", 176, 224, 230},
- {"purple", 160, 32, 240},
- {"Red", 255, 0, 0},
- {"RosyBrown", 188, 143, 143},
- {"RoyalBlue", 65, 105, 225},
- {"SaddleBrown", 139, 69, 19},
- {"Salmon", 233, 150, 122},
- {"SandyBrown", 244, 164, 96},
- {"SeaGreen", 82, 149, 132},
- {"seashell", 255, 245, 238},
- {"Sienna", 150, 82, 45},
- {"SkyBlue", 114, 159, 255},
- {"SlateBlue", 126, 136, 171},
- {"SlateGray", 112, 128, 144},
- {"snow", 255, 250, 250},
- {"SpringGreen", 65, 172, 65},
- {"SteelBlue", 84, 112, 170},
- {"Tan", 222, 184, 135},
- {"Thistle", 216, 191, 216},
- {"tomato", 255, 99, 71},
- {"Transparent", 0, 0, 1},
- {"Turquoise", 25, 204, 223},
- {"Violet", 156, 62, 206},
- {"VioletRed", 243, 62, 150},
- {"Wheat", 245, 222, 179},
- {"White", 255, 255, 255},
- {"WhiteSmoke", 245, 245, 245},
- {"Yellow", 255, 255, 0},
- {"YellowGreen", 50, 216, 56}
- };
- /* Hash table to look up colors from pixel strings */
- #define STARTING_HASH_SIZE 256
- struct hash_entry
- {
- char key[10];
- rtgui_color_t color;
- struct hash_entry *next;
- };
- struct color_hash
- {
- struct hash_entry **table;
- struct hash_entry *entries; /* array of all entries */
- struct hash_entry *next_free;
- int size;
- int maxnum;
- };
- static int hash_key(const char *key, int cpp, int size)
- {
- int hash;
- hash = 0;
- while ( cpp-- > 0 )
- {
- hash = hash * 33 + *key++;
- }
- return hash & (size - 1);
- }
- static struct color_hash *create_colorhash(int maxnum)
- {
- int bytes, s;
- struct color_hash *hash;
- /* we know how many entries we need, so we can allocate
- everything here */
- hash = rtgui_malloc(sizeof *hash);
- if(!hash) return RT_NULL;
- /* use power-of-2 sized hash table for decoding speed */
- for(s = STARTING_HASH_SIZE; s < maxnum; s <<= 1) ;
- hash->size = s;
- hash->maxnum = maxnum;
- bytes = hash->size * sizeof(struct hash_entry **);
- hash->entries = RT_NULL; /* in case rt_malloc fails */
- hash->table = rtgui_malloc(bytes);
- if(!hash->table) return RT_NULL;
- rt_memset(hash->table, 0, bytes);
- hash->entries = rtgui_malloc(maxnum * sizeof(struct hash_entry));
- if(!hash->entries) return RT_NULL;
- hash->next_free = hash->entries;
- return hash;
- }
- static int add_colorhash(struct color_hash *hash,
- char *key, int cpp, rtgui_color_t *color)
- {
- int index = hash_key(key, cpp, hash->size);
- struct hash_entry *e = hash->next_free++;
- e->color = *color;
- rt_memset(e->key, 0, sizeof(e->key));
- rt_strncpy(e->key, key, cpp);
- e->next = hash->table[index];
- hash->table[index] = e;
- return 1;
- }
- static void get_colorhash(struct color_hash *hash, const char *key, int cpp, rtgui_color_t* c)
- {
- struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
- while(entry)
- {
- if(rt_memcmp(key, entry->key, cpp) == 0)
- {
- *c = entry->color;
- return;
- }
- entry = entry->next;
- }
- return ; /* garbage in - garbage out */
- }
- static void free_colorhash(struct color_hash *hash)
- {
- if(hash && hash->table)
- {
- rtgui_free(hash->table);
- rtgui_free(hash->entries);
- rtgui_free(hash);
- }
- }
- #if defined(_MSC_VER) || defined(__CC_ARM)
- int strcasecmp( const char* s1, const char* s2 )
- {
- register unsigned int x2;
- register unsigned int x1;
- while (1) {
- x2 = *s2 - 'A'; if (x2 < 26u) x2 += 32;
- x1 = *s1 - 'A'; if (x1 < 26u) x1 += 32;
- s1++; s2++;
- if (x2 != x1)
- break;
- if (x1 == (unsigned int)-'A')
- break;
- }
- return x1 - x2;
- }
- #endif
- static int hex2int (char *str)
- {
- int i = 0;
- int r = 0;
- for (i = 0; i < 2; i++)
- {
- if (str[i] >= '0' && str[i] <= '9') r += str[i] - '0';
- else if (str[i] >= 'a' && str[i] <= 'f') r += str[i] - 'a' + 10;
- else if (str[i] >= 'A' && str[i] <= 'F') r += str[i] - 'A' + 10;
- if (!i) r *= 16;
- }
- return r;
- }
- void rtgui_image_xpm_init()
- {
- /* register xpm engine */
- rtgui_image_register_engine(&rtgui_image_xpm_engine);
- }
- static rt_bool_t rtgui_image_xpm_check(struct rtgui_filerw* file)
- {
- #if 0
- rt_uint8_t buffer[XPM_MAGIC_LEN];
- rt_size_t start;
- rt_bool_t result;
- result = RT_FALSE;
- start = rtgui_filerw_tell(file);
- /* seek to the begining of file */
- if (start != 0) rtgui_filerw_seek(file, 0, SEEK_SET);
- rtgui_filerw_read(file, &buffer[0], XPM_MAGIC_LEN, 1);
- if (rt_memcmp(buffer, "/* XPM */", (rt_ubase_t)XPM_MAGIC_LEN) == 0)
- result = RT_TRUE;
- rtgui_filerw_seek(file, start, SEEK_SET);
- return result;
- #else
- /* we can not check image type for memory file */
- return RT_TRUE;
- #endif
- }
- static rt_bool_t rtgui_image_xpm_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
- {
- const char **xpm;
- const char *buf;
- const char *buf_tmp;
- int w, h;
- int colors = 0;
- int colors_pp = 0;
- int i, j;
- /* color hash table */
- struct color_hash *colors_table = RT_NULL;
- if (image == RT_NULL) return RT_FALSE;
- xpm = (const char **)rtgui_filerw_mem_getdata(file);
- if (xpm == RT_NULL) return RT_FALSE;
- /* set image engine */
- image->engine = &rtgui_image_xpm_engine;
- /* parse xpm image */
- sscanf(xpm[0], "%d %d %d %d", &w, &h, &colors, &colors_pp);
- image->w = w;
- image->h = h;
- /* build color table */
- colors_table = create_colorhash(colors);
- if (!colors_table)
- {
- return RT_FALSE;
- }
- for (i = 0; i < colors; i++)
- {
- char color_name[10];
- rtgui_color_t c = 0;
- buf = xpm[i + 1];
- for (j = 0; j < colors_pp; j++)
- {
- color_name[j] = buf[j];
- }
- color_name[j] = '\0';
- /* build rtgui_color */
- if ((buf_tmp = strstr(buf, "c #")) != RT_NULL)
- {
- char color_hex[10];
- /* hexadecimal color value */
- sscanf(buf_tmp, "c #%s", color_hex);
- c = RTGUI_ARGB(0, hex2int(color_hex),
- hex2int(color_hex + 2),
- hex2int(color_hex + 4));
- }
- else if ((buf_tmp = strstr(buf, "c ")) != RT_NULL)
- {
- int k;
- /* color name */
- char rgbname[30];
- sscanf(buf_tmp, "c %s", rgbname);
- if (strcasecmp(rgbname, "None") == 0)
- {
- goto color_none;
- }
- for (k = 0; k < 234; k++)
- {
- if (strcasecmp(rgbname, rgbRecord[k].name) == 0)
- {
- c = RTGUI_ARGB(0, rgbRecord[k].r,
- rgbRecord[k].g,
- rgbRecord[k].b);
- break;
- }
- }
- }
- else
- {
- color_none:
- c = RTGUI_RGB(0, 0, 0);
- }
- /* add to color hash table */
- add_colorhash(colors_table, color_name, colors_pp, &c);
- }
- /* build rgb pixel data */
- image->data = (rt_uint8_t*) rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t));
- memset(image->data, 0, image->w * image->h * sizeof(rtgui_color_t));
- {
- rtgui_color_t *ptr = (rtgui_color_t*) image->data;
- for (h = 0; h < image->h; h++)
- {
- buf = xpm[colors + 1 + h];
- for (w = 0; w < image->w; w++, buf += colors_pp)
- {
- get_colorhash(colors_table, buf, colors_pp, ptr);
- ptr ++;
- }
- }
- }
- free_colorhash(colors_table);
- rtgui_filerw_close(file);
- return RT_TRUE;
- }
- static void rtgui_image_xpm_unload(struct rtgui_image* image)
- {
- if (image != RT_NULL)
- {
- /* release data */
- rtgui_free(image->data);
- image->data = RT_NULL;
- }
- }
- static void rtgui_image_xpm_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect)
- {
- rt_uint16_t x, y;
- rtgui_color_t* ptr;
- RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
- RT_ASSERT(image->data != RT_NULL);
- ptr = (rtgui_color_t*) image->data;
- /* draw each point within dc */
- for (y = 0; y < image->h; y ++)
- {
- for (x = 0; x < image->w; x++)
- {
- /* not alpha */
- if ((*ptr >> 24) != 255)
- {
- rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, *ptr);
- }
- /* move to next color buffer */
- ptr ++;
- }
- }
- }
|