*/ void Init_Mold(REBCNT size) /* ***********************************************************************/ { REBYTE *cp; REBYTE c; REBYTE *dc; Set_Root_Series(TASK_MOLD_LOOP, Make_Block(size/10), "mold loop"); Set_Root_Series(TASK_BUF_MOLD, Make_Unicode(size), "mold buffer"); // Create quoted char escape table: Char_Escapes = cp = Make_Mem(MAX_ESC_CHAR+1); // cleared for (c = '@'; c <= '_'; c++) *cp++ = c; Char_Escapes[TAB] = '-'; Char_Escapes[LF] = '/'; Char_Escapes['"'] = '"'; Char_Escapes['^'] = '^'; URL_Escapes = cp = Make_Mem(MAX_URL_CHAR+1); // cleared //for (c = 0; c <= MAX_URL_CHAR; c++) if (IS_LEX_DELIMIT(c)) cp[c] = ESC_URL; for (c = 0; c <= ' '; c++) cp[c] = ESC_URL | ESC_FILE; dc = ";%\"()[]{}<>"; for (c = LEN_BYTES(dc); c > 0; c--) URL_Escapes[*dc++] = ESC_URL | ESC_FILE; }
*/ void Decode_LZW(REBCNT *data, REBYTE **cpp, REBYTE *colortab, REBINT w, REBINT h, REBOOL interlaced) /* ** Perform LZW decompression. ** ***********************************************************************/ { REBYTE *cp = *cpp; REBYTE *rp; REBINT available, clear, code_mask, code_size, end_of_info, in_code; REBINT old_code, bits, code, count, x, y, data_size, row, i; REBCNT *dp, datum; short *prefix; REBYTE first, *pixel_stack, *suffix, *top_stack; suffix = Make_Mem(MAX_STACK_SIZE * (sizeof(REBYTE) + sizeof(REBYTE) + sizeof(short))); pixel_stack = suffix + MAX_STACK_SIZE; prefix = (short *)(pixel_stack + MAX_STACK_SIZE); data_size = *cp++; clear = 1 << data_size; end_of_info = clear + 1; available = clear + 2; old_code = NULL_CODE; code_size = data_size + 1; code_mask = (1 << code_size) - 1; for (code=0; code<clear; code++) { prefix[code] = 0; suffix[code] = code; } datum = 0; bits = 0; count = 0; first = 0; row = i = 0; top_stack = pixel_stack; dp = data; for (y=0; y<h; y++) { for (x=0; x<w;) { // if the stack is empty if (top_stack == pixel_stack) { // if we don't have enough bits if (bits < code_size) { // if we run out of bytes in the packet if (count == 0) { // get size of next packet count = *cp++; // if 0, end of image if (count == 0) break; } // add bits from next byte and adjust counters datum += *cp++ << bits; bits += 8; count--; continue; } // isolate the code bits and adjust the temps code = datum & code_mask; datum >>= code_size; bits -= code_size; // sanity check if (code > available || code == end_of_info) break; // time to reset the tables if (code == clear) { code_size = data_size + 1; code_mask = (1 << code_size) - 1; available = clear + 2; old_code = NULL_CODE; continue; } // if we are the first code, just stack it if (old_code == NULL_CODE) { *top_stack++ = suffix[code]; old_code = code; first = code; continue; } in_code = code; if (code == available) { *top_stack++ = first; code = old_code; } while (code > clear) { *top_stack++ = suffix[code]; code = prefix[code]; } first = suffix[code]; // add a new string to the table if (available >= MAX_STACK_SIZE) break; *top_stack++ = first; prefix[available] = old_code; suffix[available++] = first; if ((available & code_mask) == 0 && available < MAX_STACK_SIZE) { code_size++; code_mask += available; } old_code = in_code; } top_stack--; rp = colortab + 3 * *top_stack; *dp++ = rp[2] | (rp[1] << 8) | (rp[0] << 16); x++; } if (interlaced) { row += interlace_rate[i]; if (row >= h) { row = interlace_start[++i]; } dp = data + row * w; } } *cpp = cp + count + 1; Free_Mem(suffix, MAX_STACK_SIZE * (sizeof(REBYTE) + sizeof(REBYTE) + sizeof(short))); }
*/ static void Decode_BMP_Image(REBCDI *codi) /* ** Input: BMP encoded image (codi->data, len) ** Output: Image bits (codi->bits, w, h) ** Error: Code in codi->error ** Return: Success as TRUE or FALSE ** ***********************************************************************/ { REBINT i, j, x, y, c; REBINT colors, compression, bitcount; REBINT w, h; BITMAPFILEHEADER bmfh; BITMAPINFOHEADER bmih; BITMAPCOREHEADER bmch; REBYTE *cp, *tp; REBCNT *dp; RGBQUADPTR color; RGBQUADPTR ctab = 0; cp = codi->data; Map_Bytes(&bmfh, &cp, mapBITMAPFILEHEADER); if (bmfh.bfType[0] != 'B' || bmfh.bfType[1] != 'M') { codi->error = CODI_ERR_SIGNATURE; return; } if (codi->action == CODI_IDENTIFY) return; // no error means success tp = cp; Map_Bytes(&bmih, &cp, mapBITMAPINFOHEADER); if (bmih.biSize < sizeof(BITMAPINFOHEADER)) { cp = tp; Map_Bytes(&bmch, &cp, mapBITMAPCOREHEADER); w = bmch.bcWidth; h = bmch.bcHeight; compression = 0; bitcount = bmch.bcBitCount; if (bmch.bcBitCount < 24) colors = 1 << bmch.bcBitCount; else colors = 0; if (colors) { ctab = (RGBQUADPTR)Make_Mem(colors * sizeof(RGBQUAD)); for (i = 0; i<colors; i++) { ctab[i].rgbBlue = *cp++; ctab[i].rgbGreen = *cp++; ctab[i].rgbRed = *cp++; ctab[i].rgbReserved = 0; } } } else { w = bmih.biWidth; h = bmih.biHeight; compression = bmih.biCompression; bitcount = bmih.biBitCount; if (bmih.biClrUsed == 0 && bmih.biBitCount < 24) colors = 1 << bmih.biBitCount; else colors = bmih.biClrUsed; if (colors) { ctab = (RGBQUADPTR)Make_Mem(colors * sizeof(RGBQUAD)); memcpy(ctab, cp, colors * sizeof(RGBQUAD)); cp += colors * sizeof(RGBQUAD); } } if (bmfh.bfOffBits != (DWORD)(cp - codi->data)) cp = codi->data + bmfh.bfOffBits; codi->w = w; codi->h = h; codi->bits = Make_Mem(w * h * 4); dp = (REBCNT *) codi->bits; dp += w * h - w; for (y = 0; y<h; y++) { switch(compression) { case BI_RGB: switch(bitcount) { case 1: x = 0; for (i = 0; i<w; i++) { if (x == 0) { x = 0x80; c = *cp++ & 0xff; } color = &ctab[(c&x) != 0]; *dp++ = ((int)color->rgbRed << 16) | ((int)color->rgbGreen << 8) | color->rgbBlue; x >>= 1; } i = (w+7) / 8; break; case 4: for (i = 0; i<w; i++) { if ((i&1) == 0) { c = *cp++ & 0xff; x = c >> 4; } else x = c & 0xf; if (x > colors) { codi->error = CODI_ERR_BAD_TABLE; goto error; } color = &ctab[x]; *dp++ = ((int)color->rgbRed << 16) | ((int)color->rgbGreen << 8) | color->rgbBlue; } i = (w+1) / 2; break; case 8: for (i = 0; i<w; i++) { c = *cp++ & 0xff; if (c > colors) { codi->error = CODI_ERR_BAD_TABLE; goto error; } color = &ctab[c]; *dp++ = ((int)color->rgbRed << 16) | ((int)color->rgbGreen << 8) | color->rgbBlue; } break; case 24: for (i = 0; i<w; i++) { #ifdef ENDIAN_BIG *dp++=cp[0]|(cp[1]<<8)|(cp[2]<<16); #else *dp++ = (*(int *)cp) & 0xffffffL; #endif cp += 3; } i = w * 3; break; default: codi->error = CODI_ERR_BIT_LEN; goto error; } while (i++ % 4) cp++; break; case BI_RLE4: i = 0; for (;;) { c = *cp++ & 0xff; if (c == 0) { c = *cp++ & 0xff; if (c == 0 || c == 1) break; if (c == 2) { codi->error = CODI_ERR_BAD_TABLE; goto error; } for (j = 0; j<c; j++) { if (i == w) goto error; if ((j&1) == 0) { x = *cp++ & 0xff; color = &ctab[x>>4]; } else color = &ctab[x&0x0f]; *dp++ = ((int)color->rgbRed << 16) | ((int)color->rgbGreen << 8) | color->rgbBlue; }
*/ void Decode_GIF_Image(REBCDI *codi) /* ** Input: GIF encoded image (codi->data, len) ** Output: Image bits (codi->bits, w, h) ** Error: Code in codi->error ** Return: Success as TRUE or FALSE ** ***********************************************************************/ { REBINT w, h; REBINT transparency_index; REBYTE c, *global_colormap, *colormap; REBCNT global_colors, image_count, local_colormap; REBCNT colors; REBYTE *cp; REBCNT *dp; REBOOL interlaced; REBYTE *end; cp = codi->data; end = codi->data + codi->len; if (strncmp((char *)cp, "GIF87", 5) != 0 && strncmp((char *)cp, "GIF89", 5) != 0) { codi->error = CODI_ERR_SIGNATURE; return; } if (codi->action == CODI_IDENTIFY) return; // no error means success global_colors = 0; global_colormap = (unsigned char *) NULL; if (cp[10] & 0x80) { // Read global colormap. global_colors = 1 << ((cp[10] & 0x07) + 1); global_colormap = cp + 13; cp += global_colors * 3; } cp += 13; transparency_index = -1; image_count = 0; for (;;) { if (cp >= end) break; c = *cp++; if (c == ';') break; // terminator if (c == '!') { // GIF Extension block. c = *cp++; switch (c) { case 0xf9: // Transparency extension block. while (cp[0] != 0 && cp[5] != 0) cp += 5; if ((cp[1] & 0x01) == 1) transparency_index = cp[4]; cp += cp[0] + 1 + 1; break; default: while (cp[0] != 0) cp += cp[0] + 1; cp++; break; } } if (c != ',') continue; image_count++; interlaced = (cp[8] & 0x40) != 0; local_colormap = cp[8] & 0x80; w = LSBFirstOrder(cp[4],cp[5]); h = LSBFirstOrder(cp[6],cp[7]); // if(w * h * 4 > VAL_STR_LEN(img)) // h = 4 * VAL_STR_LEN(img) / w; // Inititialize colormap. colors = !local_colormap ? global_colors : 1 << ((cp[8] & 0x07)+1); if (!local_colormap) { colormap = global_colormap; } else { colormap = cp + 9; cp += 3 * colors; } cp += 9; /* if (image_count == 2) { VAL_SERIES(Temp2_Value) = Make_Block(0, 0); VAL_INIT(Temp2_Value, REB_BLOCK); VAL_INDEX(Temp2_Value) = 0; Append_Series(VAL_SERIES(Temp2_Value), (REBMEM *)Temp_Value, 1); } */ dp = codi->bits = Make_Mem(w * h * 4); codi->w = w; codi->h = h; Decode_LZW(dp, &cp, colormap, w, h, interlaced); if(transparency_index >= 0) { int ADD_alpha_key_detection; REBYTE *p=colormap+3*transparency_index; ///Chroma_Key_Alpha(Temp_Value, (REBCNT)(p[2]|(p[1]<<8)|(p[0]<<16)), BLIT_MODE_COLOR); } // if (image_count == 1) // *Temp2_Value = *Temp_Value; // else // Append_Series(VAL_SERIES(Temp2_Value), (REBMEM *)Temp_Value, 1); } }