RImage *wTextureRenderImage(WTexture * texture, int width, int height, int relief) { RImage *image = NULL; RColor color1; int d; int subtype; switch (texture->any.type) { case WTEX_SOLID: image = RCreateImage(width, height, False); color1.red = texture->solid.normal.red >> 8; color1.green = texture->solid.normal.green >> 8; color1.blue = texture->solid.normal.blue >> 8; color1.alpha = 255; RClearImage(image, &color1); break; case WTEX_PIXMAP: if (texture->pixmap.subtype == WTP_TILE) { image = RMakeTiledImage(texture->pixmap.pixmap, width, height); } else if (texture->pixmap.subtype == WTP_CENTER) { color1.red = texture->pixmap.normal.red >> 8; color1.green = texture->pixmap.normal.green >> 8; color1.blue = texture->pixmap.normal.blue >> 8; color1.alpha = 255; image = RMakeCenteredImage(texture->pixmap.pixmap, width, height, &color1); } else {
/* *---------------------------------------------------------------------- * renderVGradient-- * Renders a vertical linear gradient of the specified size in the * RImage format with a border of the specified type. * * Returns: * A 24bit RImage with the gradient (no alpha channel). * * Side effects: * None *---------------------------------------------------------------------- */ static RImage *renderVGradient(unsigned width, unsigned height, int r0, int g0, int b0, int rf, int gf, int bf) { int i; long r, g, b, dr, dg, db; RImage *image; unsigned char *ptr; image = RCreateImage(width, height, False); if (!image) { return NULL; } ptr = image->data; r = r0 << 16; g = g0 << 16; b = b0 << 16; dr = ((rf - r0) << 16) / (int)height; dg = ((gf - g0) << 16) / (int)height; db = ((bf - b0) << 16) / (int)height; for (i = 0; i < height; i++) { ptr = renderGradientWidth(ptr, width, r >> 16, g >> 16, b >> 16); r += dr; g += dg; b += db; } return image; }
static RImage *renderMVGradient(unsigned width, unsigned height, RColor ** colors, int count) { int i, j, k; long r, g, b, dr, dg, db; unsigned lineSize = width * 3; RImage *image; unsigned char *ptr, *tmp; unsigned height2; assert(count > 2); image = RCreateImage(width, height, False); if (!image) { return NULL; } ptr = image->data; if (count > height) count = height; if (count > 1) height2 = height / (count - 1); else height2 = height; k = 0; r = colors[0]->red << 16; g = colors[0]->green << 16; b = colors[0]->blue << 16; for (i = 1; i < count; i++) { dr = ((int)(colors[i]->red - colors[i - 1]->red) << 16) / (int)height2; dg = ((int)(colors[i]->green - colors[i - 1]->green) << 16) / (int)height2; db = ((int)(colors[i]->blue - colors[i - 1]->blue) << 16) / (int)height2; for (j = 0; j < height2; j++) { ptr = renderGradientWidth(ptr, width, r >> 16, g >> 16, b >> 16); r += dr; g += dg; b += db; k++; } r = colors[i]->red << 16; g = colors[i]->green << 16; b = colors[i]->blue << 16; } if (k < height) { tmp = ptr; ptr = renderGradientWidth(ptr, width, r >> 16, g >> 16, b >> 16); for (j = k + 1; j < height; j++) { memcpy(ptr, tmp, lineSize); ptr += lineSize; } }
RImage *wraster_rotate_image_180(RImage *source) { RImage *target; int nwidth, nheight; int x, y; nwidth = source->width; nheight = source->height; target = RCreateImage(nwidth, nheight, (source->format != RRGBFormat)); if (!target) return NULL; if (source->format == RRGBFormat) { unsigned char *optr, *nptr; optr = source->data; nptr = target->data + nwidth * nheight * 3 - 3; for (y = 0; y < nheight; y++) { for (x = 0; x < nwidth; x++) { nptr[0] = optr[0]; nptr[1] = optr[1]; nptr[2] = optr[2]; optr += 3; nptr -= 3; } } } else { unsigned char *optr, *nptr; optr = source->data; nptr = target->data + nwidth * nheight * 4 - 4; for (y = nheight * nwidth - 1; y >= 0; y--) { nptr[0] = optr[0]; nptr[1] = optr[1]; nptr[2] = optr[2]; nptr[3] = optr[3]; optr += 4; nptr -= 4; } } return target; }
static RImage *renderMDGradient(unsigned width, unsigned height, RColor ** colors, int count) { RImage *image, *tmp; float a, offset; int j; unsigned char *ptr; assert(count > 2); if (width == 1) return renderMVGradient(width, height, colors, count); else if (height == 1) return renderMHGradient(width, height, colors, count); image = RCreateImage(width, height, False); if (!image) { return NULL; } if (count > width) count = width; if (count > height) count = height; if (count > 2) tmp = renderMHGradient(2 * width - 1, 1, colors, count); else tmp = renderHGradient(2 * width - 1, 1, colors[0]->red << 8, colors[0]->green << 8, colors[0]->blue << 8, colors[1]->red << 8, colors[1]->green << 8, colors[1]->blue << 8); if (!tmp) { RReleaseImage(image); return NULL; } ptr = tmp->data; a = ((float)(width - 1)) / ((float)(height - 1)); width = width * 3; /* copy the first line to the other lines with corresponding offset */ for (j = 0, offset = 0; j < width * height; j += width) { memcpy(&(image->data[j]), &ptr[3 * (int)offset], width); offset += a; } RReleaseImage(tmp); return image; }
static RImage *rotate_image_90(RImage *source) { RImage *target; int nwidth, nheight; int x, y; nwidth = source->height; nheight = source->width; target = RCreateImage(nwidth, nheight, (source->format != RRGBFormat)); if (!target) return NULL; if (source->format == RRGBFormat) { unsigned char *optr, *nptr; optr = source->data; for (x = nwidth; x; x--) { nptr = target->data + 3 * (x - 1); for (y = nheight; y; y--) { nptr[0] = *optr++; nptr[1] = *optr++; nptr[2] = *optr++; nptr += 3 * nwidth; } } } else { unsigned char *optr, *nptr; optr = source->data; for (x = nwidth; x; x--) { nptr = target->data + 4 * (x - 1); for (y = nheight; y; y--) { nptr[0] = *optr++; nptr[1] = *optr++; nptr[2] = *optr++; nptr[3] = *optr++; nptr += 4 * nwidth; } } } return target; }
RImage *RRenderInterwovenGradient(unsigned width, unsigned height, RColor colors1[2], int thickness1, RColor colors2[2], int thickness2) { int i, j, k, l, ll; long r1, g1, b1, dr1, dg1, db1; long r2, g2, b2, dr2, dg2, db2; RImage *image; unsigned char *ptr; unsigned char rr, gg, bb; image = RCreateImage(width, height, False); if (!image) { return NULL; } ptr = image->data; r1 = colors1[0].red << 16; g1 = colors1[0].green << 16; b1 = colors1[0].blue << 16; r2 = colors2[0].red << 16; g2 = colors2[0].green << 16; b2 = colors2[0].blue << 16; dr1 = ((colors1[1].red - colors1[0].red) << 16) / (int)height; dg1 = ((colors1[1].green - colors1[0].green) << 16) / (int)height; db1 = ((colors1[1].blue - colors1[0].blue) << 16) / (int)height; dr2 = ((colors2[1].red - colors2[0].red) << 16) / (int)height; dg2 = ((colors2[1].green - colors2[0].green) << 16) / (int)height; db2 = ((colors2[1].blue - colors2[0].blue) << 16) / (int)height; for (i = 0, k = 0, l = 0, ll = thickness1; i < height; i++) { if (k == 0) { rr = r1 >> 16; gg = g1 >> 16; bb = b1 >> 16; } else {
/* *---------------------------------------------------------------------- * renderHGradient-- * Renders a horizontal linear gradient of the specified size in the * RImage format with a border of the specified type. * * Returns: * A 24bit RImage with the gradient (no alpha channel). * * Side effects: * None *---------------------------------------------------------------------- */ static RImage *renderHGradient(unsigned width, unsigned height, int r0, int g0, int b0, int rf, int gf, int bf) { int i; long r, g, b, dr, dg, db; unsigned lineSize = width * 3; RImage *image; unsigned char *ptr; image = RCreateImage(width, height, False); if (!image) { return NULL; } ptr = image->data; r = r0 << 16; g = g0 << 16; b = b0 << 16; dr = ((rf - r0) << 16) / (int)width; dg = ((gf - g0) << 16) / (int)width; db = ((bf - b0) << 16) / (int)width; /* render the first line */ for (i = 0; i < width; i++) { *(ptr++) = (unsigned char)(r >> 16); *(ptr++) = (unsigned char)(g >> 16); *(ptr++) = (unsigned char)(b >> 16); r += dr; g += dg; b += db; } /* copy the first line to the other lines */ for (i = 1; i < height; i++) { memcpy(&(image->data[i * lineSize]), image->data, lineSize); } return image; }
static RImage *renderDGradient(unsigned width, unsigned height, int r0, int g0, int b0, int rf, int gf, int bf) { RImage *image, *tmp; int j; float a, offset; unsigned char *ptr; if (width == 1) return renderVGradient(width, height, r0, g0, b0, rf, gf, bf); else if (height == 1) return renderHGradient(width, height, r0, g0, b0, rf, gf, bf); image = RCreateImage(width, height, False); if (!image) { return NULL; } tmp = renderHGradient(2 * width - 1, 1, r0, g0, b0, rf, gf, bf); if (!tmp) { RReleaseImage(image); return NULL; } ptr = tmp->data; a = ((float)(width - 1)) / ((float)(height - 1)); width = width * 3; /* copy the first line to the other lines with corresponding offset */ for (j = 0, offset = 0.0; j < width * height; j += width) { memcpy(&(image->data[j]), &ptr[3 * (int)offset], width); offset += a; } RReleaseImage(tmp); return image; }
RImage *RLoadPNG(RContext *context, const char *file) { char *tmp; RImage *image = NULL; FILE *f; png_structp png; png_infop pinfo, einfo; png_color_16p bkcolor; int alpha; int x, y, i; double gamma, sgamma; png_uint_32 width, height; int depth, junk, color_type; png_bytep *png_rows; unsigned char *ptr; f = fopen(file, "rb"); if (!f) { RErrorCode = RERR_OPEN; return NULL; } png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr) NULL, (png_error_ptr) NULL); if (!png) { RErrorCode = RERR_NOMEMORY; fclose(f); return NULL; } pinfo = png_create_info_struct(png); if (!pinfo) { RErrorCode = RERR_NOMEMORY; fclose(f); png_destroy_read_struct(&png, NULL, NULL); return NULL; } einfo = png_create_info_struct(png); if (!einfo) { RErrorCode = RERR_NOMEMORY; fclose(f); png_destroy_read_struct(&png, &pinfo, NULL); return NULL; } RErrorCode = RERR_INTERNAL; #if PNG_LIBPNG_VER - 0 < 10400 if (setjmp(png->jmpbuf)) { #else if (setjmp(png_jmpbuf(png))) { #endif fclose(f); png_destroy_read_struct(&png, &pinfo, &einfo); if (image) RReleaseImage(image); return NULL; } png_init_io(png, f); png_read_info(png, pinfo); png_get_IHDR(png, pinfo, &width, &height, &depth, &color_type, &junk, &junk, &junk); /* sanity check */ if (width < 1 || height < 1) { fclose(f); png_destroy_read_struct(&png, &pinfo, &einfo); RErrorCode = RERR_BADIMAGEFILE; return NULL; } /* check for an alpha channel */ if (png_get_valid(png, pinfo, PNG_INFO_tRNS)) alpha = True; else alpha = (color_type & PNG_COLOR_MASK_ALPHA); /* allocate RImage */ image = RCreateImage(width, height, alpha); if (!image) { fclose(f); png_destroy_read_struct(&png, &pinfo, &einfo); return NULL; } /* normalize to 8bpp with alpha channel */ if (color_type == PNG_COLOR_TYPE_PALETTE && depth <= 8) png_set_expand(png); if (color_type == PNG_COLOR_TYPE_GRAY && depth <= 8) png_set_expand(png); if (png_get_valid(png, pinfo, PNG_INFO_tRNS)) png_set_expand(png); if (depth == 16) png_set_strip_16(png); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); /* set gamma correction */ if ((context->attribs->flags & RC_GammaCorrection) && context->depth != 8) { sgamma = (context->attribs->rgamma + context->attribs->ggamma + context->attribs->bgamma) / 3; } else if ((tmp = getenv("DISPLAY_GAMMA")) != NULL) { sgamma = atof(tmp); if (sgamma < 1.0E-3) sgamma = 1; } else { /* blah */ sgamma = 2.2; } if (png_get_gAMA(png, pinfo, &gamma)) png_set_gamma(png, sgamma, gamma); else png_set_gamma(png, sgamma, 0.45); /* do the transforms */ png_read_update_info(png, pinfo); /* set background color */ if (png_get_bKGD(png, pinfo, &bkcolor)) { image->background.red = bkcolor->red >> 8; image->background.green = bkcolor->green >> 8; image->background.blue = bkcolor->blue >> 8; } png_rows = calloc(height, sizeof(char *)); if (!png_rows) { RErrorCode = RERR_NOMEMORY; fclose(f); RReleaseImage(image); png_destroy_read_struct(&png, &pinfo, &einfo); return NULL; } for (y = 0; y < height; y++) { png_rows[y] = malloc(png_get_rowbytes(png, pinfo)); if (!png_rows[y]) { RErrorCode = RERR_NOMEMORY; fclose(f); RReleaseImage(image); png_destroy_read_struct(&png, &pinfo, &einfo); while (y-- > 0) if (png_rows[y]) free(png_rows[y]); free(png_rows); return NULL; } } /* read data */ png_read_image(png, png_rows); png_read_end(png, einfo); png_destroy_read_struct(&png, &pinfo, &einfo); fclose(f); ptr = image->data; /* convert to RImage */ if (alpha) { for (y = 0; y < height; y++) { for (x = 0, i = width * 4; x < i; x++, ptr++) { *ptr = *(png_rows[y] + x); } } } else { for (y = 0; y < height; y++) { for (x = 0, i = width * 3; x < i; x++, ptr++) { *ptr = *(png_rows[y] + x); } } } for (y = 0; y < height; y++) if (png_rows[y]) free(png_rows[y]); free(png_rows); return image; }
/* *---------------------------------------------------------------------- * renderVGradient-- * Renders a vertical linear gradient of the specified size in the * RImage format with a border of the specified type. * * Returns: * A 24bit RImage with the gradient (no alpha channel). * * Side effects: * None *---------------------------------------------------------------------- */ static RImage *renderVGradient(unsigned width, unsigned height, int r0, int g0, int b0, int rf, int gf, int bf) { int i, j; long r, g, b, dr, dg, db; RImage *image; unsigned char *ptr; unsigned char rr, gg, bb; image = RCreateImage(width, height, False); if (!image) { return NULL; } ptr = image->data; r = r0 << 16; g = g0 << 16; b = b0 << 16; dr = ((rf - r0) << 16) / (int)height; dg = ((gf - g0) << 16) / (int)height; db = ((bf - b0) << 16) / (int)height; for (i = 0; i < height; i++) { rr = r >> 16; gg = g >> 16; bb = b >> 16; for (j = 0; j < width / 8; j++) { *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; } switch (width % 8) { case 7: *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; case 6: *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; case 5: *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; case 4: *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; case 3: *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; case 2: *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; case 1: *(ptr++) = rr; *(ptr++) = gg; *(ptr++) = bb; } r += dr; g += dg; b += db; } return image; }
RImage* RRotateImage(RImage *image, float angle) { RImage *img; int nwidth, nheight; int x, y; int bpp = image->format == RRGBAFormat ? 4 : 3; angle = ((int)angle % 360) + (angle - (int)angle); if (angle == 0.0) { return RCloneImage(image); } else if (angle == 90.0) { nwidth = image->height; nheight = image->width; img = RCreateImage(nwidth, nheight, True); if (!img) { return NULL; } if (bpp == 3) { unsigned char *optr, *nptr; unsigned offs; offs = nwidth * 4; optr = image->data; nptr = img->data; for (x = 0; x < nwidth; x++) { nptr = img->data + x*4; for (y = nheight; y; y--) { nptr[0] = *optr++; nptr[1] = *optr++; nptr[2] = *optr++; nptr[3] = 255; nptr += offs; } } } else { unsigned *optr, *nptr; unsigned *p; optr = (unsigned*)image->data; p = (unsigned*)img->data; for (x = 0; x < nwidth; x++) { nptr = p++; for (y = nheight; y; y--) { *nptr = *optr++; nptr += nwidth; } } } } else if (angle == 180.0) { nwidth = image->width; nheight = image->height; img = RCreateImage(nwidth, nheight, True); if (!img) { return NULL; } if (bpp == 3) { unsigned char *optr, *nptr; optr = image->data; nptr = img->data + nwidth * nheight * 4 - 4; for (y = 0; y < nheight; y++) { for (x = 0; x < nwidth; x++) { nptr[0] = optr[0]; nptr[1] = optr[1]; nptr[2] = optr[2]; nptr[3] = 255; optr += 3; nptr -= 4; } } } else { unsigned *optr, *nptr; optr = (unsigned*)image->data; nptr = (unsigned*)img->data + nwidth * nheight - 1; for (y = nheight*nwidth-1; y >= 0; y--) { *nptr = *optr; optr++; nptr--; } } } else if (angle == 270.0) { nwidth = image->height; nheight = image->width; img = RCreateImage(nwidth, nheight, True); if (!img) { return NULL; } if (bpp == 3) { unsigned char *optr, *nptr; unsigned offs; offs = nwidth * 4; optr = image->data; nptr = img->data; for (x = 0; x < nwidth; x++) { nptr = img->data + x*4; for (y = nheight; y; y--) { nptr[0] = *optr++; nptr[1] = *optr++; nptr[2] = *optr++; nptr[3] = 255; nptr += offs; } } } else { unsigned *optr, *nptr; unsigned *p; optr = (unsigned*)image->data; p = (unsigned*)img->data + nwidth*nheight; for (x = 0; x < nwidth; x++) { nptr = p--; for (y = nheight; y; y--) { *nptr = *optr++; nptr -= nwidth; } } } } else { img = rotateImage(image, angle); } return img; }
RImage* RGetImageFromXPMData(RContext *context, char **xpmData) { Display *dpy = context->dpy; Colormap cmap = context->cmap; RImage *image; XpmImage xpm; unsigned char *color_table[4]; unsigned char *data; int *p; int i; i = XpmCreateXpmImageFromData(xpmData, &xpm, (XpmInfo *)NULL); if (i!=XpmSuccess) { switch (i) { case XpmOpenFailed: RErrorCode = RERR_OPEN; break; case XpmFileInvalid: RErrorCode = RERR_BADIMAGEFILE; break; case XpmNoMemory: RErrorCode = RERR_NOMEMORY; break; default: RErrorCode = RERR_BADIMAGEFILE; break; } return NULL; } if (xpm.height<1 || xpm.width < 1) { RErrorCode = RERR_BADIMAGEFILE; XpmFreeXpmImage(&xpm); return NULL; } if (xpm.colorTable==NULL) { RErrorCode = RERR_BADIMAGEFILE; XpmFreeXpmImage(&xpm); return NULL; } image = RCreateImage(xpm.width, xpm.height, True); if (!image) { XpmFreeXpmImage(&xpm); return NULL; } /* make color table */ for (i=0; i<4; i++) { color_table[i] = malloc(xpm.ncolors*sizeof(char)); if (!color_table[i]) { for (i=i-1;i>=0; i--) { if (color_table[i]) free(color_table[i]); } RReleaseImage(image); RErrorCode = RERR_NOMEMORY; XpmFreeXpmImage(&xpm); return NULL; } } for (i=0; i<xpm.ncolors; i++) { XColor xcolor; char * color = NULL; if (xpm.colorTable[i].c_color) color = xpm.colorTable[i].c_color; else if (xpm.colorTable[i].g_color) color = xpm.colorTable[i].g_color; else if (xpm.colorTable[i].g4_color) color = xpm.colorTable[i].g4_color; else if (xpm.colorTable[i].m_color) color = xpm.colorTable[i].m_color; else if (xpm.colorTable[i].symbolic) color = xpm.colorTable[i].symbolic; if (!color) { color_table[0][i] = 0xbe; color_table[1][i] = 0xbe; color_table[2][i] = 0xbe; color_table[3][i] = 0xff; continue; } if (strncmp(color,"None",4)==0) { color_table[0][i]=0; color_table[1][i]=0; color_table[2][i]=0; color_table[3][i]=0; continue; } if (XParseColor(dpy, cmap, color, &xcolor)) { color_table[0][i] = xcolor.red>>8; color_table[1][i] = xcolor.green>>8; color_table[2][i] = xcolor.blue>>8; color_table[3][i] = 0xff; } else {
RImage *RCreateImageFromXImage(RContext * context, XImage * image, XImage * mask) { RImage *img; int x, y; unsigned long pixel; unsigned char *data; int rshift, gshift, bshift; int rmask, gmask, bmask; assert(image != NULL); assert(image->format == ZPixmap); assert(!mask || mask->format == ZPixmap); img = RCreateImage(image->width, image->height, mask != NULL); if (!img) { return NULL; } /* I don't know why, but XGetImage() for pixmaps don't set the * {red,green,blue}_mask values correctly. */ if (context->depth == image->depth) { rmask = context->visual->red_mask; gmask = context->visual->green_mask; bmask = context->visual->blue_mask; } else { rmask = image->red_mask; gmask = image->green_mask; bmask = image->blue_mask; } /* how many bits to shift to normalize the color into 8bpp */ rshift = get_shifts(rmask) - 8; gshift = get_shifts(gmask) - 8; bshift = get_shifts(bmask) - 8; data = img->data; if (image->depth == 1) { for (y = 0; y < image->height; y++) { for (x = 0; x < image->width; x++) { pixel = XGetPixel(image, x, y); if (pixel) { *data++ = 0; *data++ = 0; *data++ = 0; } else { *data++ = 0xff; *data++ = 0xff; *data++ = 0xff; } if (mask) data++; } } } else { for (y = 0; y < image->height; y++) { for (x = 0; x < image->width; x++) { pixel = XGetPixel(image, x, y); *(data++) = NORMALIZE_RED(pixel); *(data++) = NORMALIZE_GREEN(pixel); *(data++) = NORMALIZE_BLUE(pixel); if (mask) data++; } } } #define MIN(a,b) ((a)<(b)?(a):(b)) if (mask) { data = img->data + 3; /* Skip R, G & B */ for (y = 0; y < MIN(mask->height, image->height); y++) { for (x = 0; x < MIN(mask->width, image->width); x++) { if (mask->width <= image->width && XGetPixel(mask, x, y)) { *data = 0xff; } else { *data = 0; } data += 4; } for (; x < image->width; x++) { *data = 0; data += 4; } } for (; y < image->height; y++) { for (x = 0; x < image->width; x++) { *data = 0; data += 4; } } } return img; }
static RImage *renderMVGradient(unsigned width, unsigned height, RColor ** colors, int count) { int i, j, k; long r, g, b, dr, dg, db; unsigned lineSize = width * 3; RImage *image; unsigned char *ptr, *tmp; unsigned height2; int x; unsigned char rr, gg, bb; assert(count > 2); image = RCreateImage(width, height, False); if (!image) { return NULL; } ptr = image->data; if (count > height) count = height; if (count > 1) height2 = height / (count - 1); else height2 = height; k = 0; r = colors[0]->red << 16; g = colors[0]->green << 16; b = colors[0]->blue << 16; for (i = 1; i < count; i++) { dr = ((int)(colors[i]->red - colors[i - 1]->red) << 16) / (int)height2; dg = ((int)(colors[i]->green - colors[i - 1]->green) << 16) / (int)height2; db = ((int)(colors[i]->blue - colors[i - 1]->blue) << 16) / (int)height2; for (j = 0; j < height2; j++) { rr = r >> 16; gg = g >> 16; bb = b >> 16; for (x = 0; x < width / 4; x++) { *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; } switch (width % 4) { case 3: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; case 2: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; case 1: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; } r += dr; g += dg; b += db; k++; } r = colors[i]->red << 16; g = colors[i]->green << 16; b = colors[i]->blue << 16; } rr = r >> 16; gg = g >> 16; bb = b >> 16; if (k < height) { tmp = ptr; for (x = 0; x < width / 4; x++) { *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; } switch (width % 4) { case 3: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; case 2: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; case 1: *ptr++ = rr; *ptr++ = gg; *ptr++ = bb; default: break; } for (j = k + 1; j < height; j++) { memcpy(ptr, tmp, lineSize); ptr += lineSize; } } return image; }
/* * Partially based on code in gif2rgb from giflib, by Gershon Elber. */ RImage *RLoadGIF(const char *file, int index) { RImage *image = NULL; unsigned char *cptr; GifFileType *gif = NULL; GifPixelType *buffer = NULL; int i, j, k; int width, height; GifRecordType recType; ColorMapObject *colormap; unsigned char rmap[256]; unsigned char gmap[256]; unsigned char bmap[256]; if (index < 0) index = 0; /* default error message */ RErrorCode = RERR_BADINDEX; gif = DGifOpenFileName(file); if (!gif) { switch (GifLastError()) { case D_GIF_ERR_OPEN_FAILED: RErrorCode = RERR_OPEN; break; case D_GIF_ERR_READ_FAILED: RErrorCode = RERR_READ; break; default: RErrorCode = RERR_BADIMAGEFILE; break; } return NULL; } if (gif->SWidth < 1 || gif->SHeight < 1) { DGifCloseFile(gif); RErrorCode = RERR_BADIMAGEFILE; return NULL; } colormap = gif->SColorMap; i = 0; do { int extCode; GifByteType *extension; if (DGifGetRecordType(gif, &recType) == GIF_ERROR) { goto giferr; } switch (recType) { case IMAGE_DESC_RECORD_TYPE: if (i++ != index) break; if (DGifGetImageDesc(gif) == GIF_ERROR) { goto giferr; } width = gif->Image.Width; height = gif->Image.Height; if (gif->Image.ColorMap) colormap = gif->Image.ColorMap; /* the gif specs talk about a default colormap, but it * doesnt say what the heck is this default colormap */ if (!colormap) { /* * Well, since the spec says the colormap can be anything, * lets just render it with whatever garbage the stack * has :) * goto bye; */ } else { for (j = 0; j < colormap->ColorCount; j++) { rmap[j] = colormap->Colors[j].Red; gmap[j] = colormap->Colors[j].Green; bmap[j] = colormap->Colors[j].Blue; } } buffer = malloc(width * sizeof(GifColorType)); if (!buffer) { RErrorCode = RERR_NOMEMORY; goto bye; } image = RCreateImage(width, height, False); if (!image) { goto bye; } if (gif->Image.Interlace) { int l; int pelsPerLine; if (RRGBAFormat == image->format) pelsPerLine = width * 4; else pelsPerLine = width * 3; for (j = 0; j < 4; j++) { for (k = InterlacedOffset[j]; k < height; k += InterlacedJumps[j]) { if (DGifGetLine(gif, buffer, width) == GIF_ERROR) { goto giferr; } cptr = image->data + (k * pelsPerLine); for (l = 0; l < width; l++) { int pixel = buffer[l]; *cptr++ = rmap[pixel]; *cptr++ = gmap[pixel]; *cptr++ = bmap[pixel]; } } } } else { cptr = image->data; for (j = 0; j < height; j++) { if (DGifGetLine(gif, buffer, width) == GIF_ERROR) { goto giferr; } for (k = 0; k < width; k++) { int pixel = buffer[k]; *cptr++ = rmap[pixel]; *cptr++ = gmap[pixel]; *cptr++ = bmap[pixel]; if (RRGBAFormat == image->format) cptr++; } } } break; case EXTENSION_RECORD_TYPE: /* skip all extension blocks */ if (DGifGetExtension(gif, &extCode, &extension) == GIF_ERROR) { goto giferr; } while (extension) { if (DGifGetExtensionNext(gif, &extension) == GIF_ERROR) { goto giferr; } } break; default: break; } } while (recType != TERMINATE_RECORD_TYPE && i <= index); /* yuck! */ goto did_not_get_any_errors; giferr: switch (GifLastError()) { case D_GIF_ERR_OPEN_FAILED: RErrorCode = RERR_OPEN; break; case D_GIF_ERR_READ_FAILED: RErrorCode = RERR_READ; break; default: RErrorCode = RERR_BADIMAGEFILE; break; } bye: if (image) RReleaseImage(image); image = NULL; did_not_get_any_errors: if (buffer) free(buffer); if (gif) DGifCloseFile(gif); return image; }
static RImage* rotateImage(RImage *image, float angle) { RImage *img; int nwidth, nheight; int x1, y1; int x2, y2; int dx, dy; int xi, yi; int xx, yy; unsigned char *src, *dst; int dpr, dpru, p; /* only 180o for now */ if (angle > 180.0) angle -= 180.0; angle = (angle * PI) / 180.0; nwidth = ceil(abs(cos(angle) * image->width)) + ceil(abs(cos(PI/2 - angle) * image->width)); nheight = ceil(abs(sin(angle) * image->height)) + ceil(abs(cos(PI/2 - angle) * image->height)); img = RCreateImage(nwidth, nheight, True); if (!img) return NULL; src = image->data; dst = img->data; x1 = floor(abs(cos(PI/2 - angle)*image->width)); y1 = 0; x2 = 0; y2 = floor(abs(sin(PI/2 - angle)*image->width)); xx = floor(abs(cos(angle)*image->height)) - 1; yy = nheight - 1; printf("%ix%i, %i %i %i %i %i\n", nwidth, nheight, x1, y1, x2, y2, (int)((angle*180.0)/PI)); dx = abs(x2 - x1); dy = abs(y2 - y1); if (x1 > x2) xi = -1; else xi = 1; if (y1 > y2) yi = -1; else yi = 1; if (dx >= dy) { dpr = dy << 1; dpru = dpr - (dx << 1); p = dpr - dx; while (dx-- >= 0) { copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src); /* calc next step */ if (p > 0) { x1 += xi; y1 += yi; xx += xi; yy += yi; p += dpru; } else { x1 += xi; xx += xi; p += dpr; } } } else { puts("NOT IMPLEMTENED"); return img; dpr = dx << 1; dpru = dpr - (dy << 1); p = dpr - dy; while (dy-- >= 0) { xx = abs(x1*sin(angle*PI/180.0)); yy = abs(y1*cos(angle*PI/180.0)); copyLine(x1, y1, xx, yy, nwidth, image->format, dst, &src); /* calc next step*/ if (p > 0) { x1 += xi; y1 += yi; p += dpru; } else { y1 += yi; p += dpr; } } } return img; }
static RImage *renderMHGradient(unsigned width, unsigned height, RColor ** colors, int count) { int i, j, k; long r, g, b, dr, dg, db; unsigned lineSize = width * 3; RImage *image; unsigned char *ptr; unsigned width2; assert(count > 2); image = RCreateImage(width, height, False); if (!image) { return NULL; } ptr = image->data; if (count > width) count = width; if (count > 1) width2 = width / (count - 1); else width2 = width; k = 0; r = colors[0]->red << 16; g = colors[0]->green << 16; b = colors[0]->blue << 16; /* render the first line */ for (i = 1; i < count; i++) { dr = ((int)(colors[i]->red - colors[i - 1]->red) << 16) / (int)width2; dg = ((int)(colors[i]->green - colors[i - 1]->green) << 16) / (int)width2; db = ((int)(colors[i]->blue - colors[i - 1]->blue) << 16) / (int)width2; for (j = 0; j < width2; j++) { *ptr++ = (unsigned char)(r >> 16); *ptr++ = (unsigned char)(g >> 16); *ptr++ = (unsigned char)(b >> 16); r += dr; g += dg; b += db; k++; } r = colors[i]->red << 16; g = colors[i]->green << 16; b = colors[i]->blue << 16; } for (j = k; j < width; j++) { *ptr++ = (unsigned char)(r >> 16); *ptr++ = (unsigned char)(g >> 16); *ptr++ = (unsigned char)(b >> 16); } /* copy the first line to the other lines */ for (i = 1; i < height; i++) { memcpy(&(image->data[i * lineSize]), image->data, lineSize); } return image; }
int main (int argc, char **argv){ int i,j; WMColor *color; WMWindow * win; RImage *image; struct _pict pict; Drawable de; RColor one, two={0xaf, 0x0f,0xff,0x33}; one.red=247; one.green=251; one.blue=107; one.alpha=0xff; WMInitializeApplication("DrawWin", &argc, argv); display = XOpenDisplay(""); screen = WMCreateScreen(display, DefaultScreen(display)); win = WMCreateWindow(screen, ""); WMResizeWidget(win, WINWIDTH, WINHEIGHT); WMSetWindowCloseAction(win, closeAction, NULL); WMSetWindowTitle(win,"Graphics"); color = WMCreateRGBColor(screen,124<<9,206<<8,162<<8, False); WMSetWidgetBackgroundColor((WMWidget *)win, color); /* end setup main window */ image=RCreateImage( 100,100,0.5); RFillImage(image, &two); RDrawLine(image, 50,10,90,90,&one); RDrawLine(image, 10,90,50,10,&one); RDrawLine(image, 10,90,90,90,&one); g3=WMColorGC(screen->gray); XSetLineAttributes(display,g3,3,LineSolid,CapButt,JoinMiter); pict.segments[1].x1= pict.segments[0].x1=HOFF; pict.segments[0].x2=HOFF; pict.segments[0].y1=VOFF; pict.segments[1].y2= pict.segments[0].y2=VOFF; pict.segments[1].x2= HOFF+10; pict.segments[1].y1=VOFF+10; pict.seglen=2; for (i=9;i>0;i--){ j=2*(10-i); pict.segments[j+1].x1= pict.segments[j].x1=HOFF; pict.segments[j+1].y2= pict.segments[j].y2=VOFF; pict.segments[j].x2= i+pict.segments[j-1].x2; pict.segments[j].y1=i+pict.segments[j-1].y1; pict.segments[j+1].x2= i+pict.segments[j].x2; pict.segments[j+1].y1=i+pict.segments[j].y1; pict.seglen+=2; }; WMRealizeWidget(win); pict.dwin=W_VIEW_DRAWABLE(WMWidgetView(win)); pixmap=WMCreatePixmapFromRImage(screen, image,1); WMCreateEventHandler(WMWidgetView(win), ExposureMask,drawProcedure,&pict); WMMapWidget(win); WMScreenMainLoop(screen); }
RImage *RLoadJPEG(RContext * context, const char *file_name) { RImage *image = NULL; struct jpeg_decompress_struct cinfo; int i; unsigned char *ptr; JSAMPROW buffer[1], bptr; FILE *file; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct my_error_mgr jerr; file = fopen(file_name, "rb"); if (!file) { RErrorCode = RERR_OPEN; return NULL; } cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_decompress(&cinfo); fclose(file); return NULL; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, file); jpeg_read_header(&cinfo, TRUE); if (cinfo.image_width < 1 || cinfo.image_height < 1) { RErrorCode = RERR_BADIMAGEFILE; goto bye; } bptr = buffer[0] = (JSAMPROW) malloc(cinfo.image_width * cinfo.num_components); if (!buffer[0]) { RErrorCode = RERR_NOMEMORY; goto bye; } if (cinfo.jpeg_color_space == JCS_GRAYSCALE) { cinfo.out_color_space = JCS_GRAYSCALE; } else cinfo.out_color_space = JCS_RGB; cinfo.quantize_colors = FALSE; cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; jpeg_calc_output_dimensions(&cinfo); if (context->flags.optimize_for_speed) image = RCreateImage(cinfo.image_width, cinfo.image_height, True); else image = RCreateImage(cinfo.image_width, cinfo.image_height, False); if (!image) { RErrorCode = RERR_NOMEMORY; goto bye; } jpeg_start_decompress(&cinfo); ptr = image->data; if (cinfo.out_color_space == JCS_RGB) { if (context->flags.optimize_for_speed) { while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, (JDIMENSION) 1); bptr = buffer[0]; for (i = 0; i < cinfo.image_width; i++) { *ptr++ = *bptr++; *ptr++ = *bptr++; *ptr++ = *bptr++; ptr++; /* skip alpha channel */ } } } else { while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, (JDIMENSION) 1); bptr = buffer[0]; memcpy(ptr, bptr, cinfo.image_width * 3); ptr += cinfo.image_width * 3; } } } else { while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, (JDIMENSION) 1); bptr = buffer[0]; for (i = 0; i < cinfo.image_width; i++) { *ptr++ = *bptr; *ptr++ = *bptr; *ptr++ = *bptr++; } } } jpeg_finish_decompress(&cinfo); bye: jpeg_destroy_decompress(&cinfo); fclose(file); if (buffer[0]) free(buffer[0]); return image; }