int32_t my_replacer(gdImagePtr im, int32_t src) { if (src == gdImageGetTransparent(im)) return gdTrueColor(255, 255, 255); return gdAlphaBlend(gdTrueColor(255, 255, 255), src); }
static void gdImageBrushApply(gdImagePtr im, int x, int y) { int lx, ly; int hy; int hx; int x1, y1, x2, y2; int srcx, srcy; if (!im->brush) { return; } hy = gdImageSY(im->brush)/2; y1 = y - hy; y2 = y1 + gdImageSY(im->brush); hx = gdImageSX(im->brush)/2; x1 = x - hx; x2 = x1 + gdImageSX(im->brush); srcy = 0; for (ly = y1; (ly < y2); ly++) { srcx = 0; for (lx = x1; (lx < x2); lx++) { int p; p = gdImageGetPixel(im->brush, srcx, srcy); /* Allow for non-square brushes! */ if (p != gdImageGetTransparent(im->brush)) { gdImageSetPixel(im, lx, ly, im->brushColorMap[p]); } srcx++; } srcy++; } }
result_t Image::get_transparent(int32_t &retVal) { if (!m_image) return CHECK_ERROR(CALL_E_INVALID_CALL); retVal = gdImageGetTransparent(m_image); return 0; }
gdImagePtr rotatePixmapGD(gdImagePtr img, double angle_rad) { gdImagePtr rimg = NULL; double cos_a, sin_a; double x1 = 0.0, y1 = 0.0; /* destination rectangle */ double x2 = 0.0, y2 = 0.0; double x3 = 0.0, y3 = 0.0; double x4 = 0.0, y4 = 0.0; long minx, miny, maxx, maxy; int width=0, height=0; /* int color; */ sin_a = sin(angle_rad); cos_a = cos(angle_rad); /* compute distination rectangle (x1,y1 is known) */ x1 = 0 ; y1 = 0 ; x2 = img->sy * sin_a; y2 = -img->sy * cos_a; x3 = (img->sx * cos_a) + (img->sy * sin_a); y3 = (img->sx * sin_a) - (img->sy * cos_a); x4 = (img->sx * cos_a); y4 = (img->sx * sin_a); minx = (long) MS_MIN(x1,MS_MIN(x2,MS_MIN(x3,x4))); miny = (long) MS_MIN(y1,MS_MIN(y2,MS_MIN(y3,y4))); maxx = (long) MS_MAX(x1,MS_MAX(x2,MS_MAX(x3,x4))); maxy = (long) MS_MAX(y1,MS_MAX(y2,MS_MAX(y3,y4))); width = (int)ceil(maxx-minx); height = (int)ceil(maxy-miny); /* create the new image based on the computed width/height */ if (gdImageTrueColor(img)) { rimg = gdImageCreateTrueColor(width, height); gdImageAlphaBlending(rimg, 0); gdImageFilledRectangle(rimg, 0, 0, width, height, gdImageColorAllocateAlpha(rimg, 0, 0, 0, gdAlphaTransparent)); } else { int tc = gdImageGetTransparent(img); rimg = gdImageCreate(width, height); if(tc != -1) gdImageColorTransparent(rimg, gdImageColorAllocate(rimg, gdImageRed(img, tc), gdImageGreen(img, tc), gdImageBlue(img, tc))); } if(!rimg) { msSetError(MS_GDERR,"failed to create rotated pixmap","rotatePixmapGD()"); return NULL; } gdImageCopyRotated (rimg, img, width*0.5, height*0.5, 0, 0, gdImageSX(img), gdImageSY(img), angle_rad*MS_RAD_TO_DEG); return rimg; }
void PrintGIFInfo ( gdImagePtr image ) { cout << endl; cout << "Index\tRed\tGreen\tBlue" << endl; const JSize colorCount = gdImageColorsTotal(image); for (JIndex i=0; i<colorCount; i++) { cout << i; cout << '\t' << gdImageRed (image, i); cout << '\t' << gdImageGreen(image, i); cout << '\t' << gdImageBlue (image, i); cout << endl; } cout << endl; cout << "Number of colors: " << colorCount << endl; const int transparentColor = gdImageGetTransparent(image); cout << "Transparent color index: "; if (transparentColor == kNoTransparentColor) { cout << "none"; } else { cout << transparentColor; } cout << endl; cout << endl; cout << "Width: " << gdImageSX(image) << endl; cout << "Height: " << gdImageSY(image) << endl; cout << "Interlaced: "; if (gdImageGetInterlaced(image)) { cout << "yes"; } else { cout << "no"; } cout << endl; cout << endl; }
static int gd_resolve_color(char* name) { color_t color; if (!(strcmp(name,"transparent"))) { /* special case for "transparent" color */ return gdImageGetTransparent(im); } else { colorxlate(name,&color,RGBA_BYTE); return gdImageColorResolve(im,color.u.rgba[0],color.u.rgba[1],color.u.rgba[2]); } }
static int color_index(gdImagePtr im, gvcolor_t color) { int alpha; /* convert alpha (normally an "opacity" value) to gd's "transparency" */ alpha = (255 - color.u.rgba[3]) * gdAlphaMax / 255; if(alpha == gdAlphaMax) return (gdImageGetTransparent(im)); else return (gdImageColorResolveAlpha(im, color.u.rgba[0], color.u.rgba[1], color.u.rgba[2], alpha)); }
static void gdImageTileApply(gdImagePtr im, int x, int y) { int srcx, srcy; int p; if (!im->tile) { return; } srcx = x % gdImageSX(im->tile); srcy = y % gdImageSY(im->tile); p = gdImageGetPixel(im->tile, srcx, srcy); /* Allow for transparency */ if (p != gdImageGetTransparent(im->tile)) { gdImageSetPixel(im, x, y, im->tileColorMap[p]); } }
result_t Image::rotate(int32_t dir) { if (dir != gd_base::_LEFT && dir != gd_base::_RIGHT) return CHECK_ERROR(CALL_E_INVALIDARG); int32_t sx = gdImageSX(m_image); int32_t sy = gdImageSY(m_image); int32_t i, j; gdImagePtr newImage; if (gdImageTrueColor(m_image)) newImage = gdImageCreateTrueColor(sy, sx); else { newImage = gdImageCreate(sy, sx); gdImagePaletteCopy(newImage, m_image); } gdImageColorTransparent(newImage, gdImageGetTransparent(m_image)); if (dir == gd_base::_LEFT) { for (i = 0; i < sx; i++) for (j = 0; j < sy; j++) gdImageSetPixel(newImage, j, sx - i - 1, gdImageGetPixel(m_image, i, j)); } else { for (i = 0; i < sx; i++) for (j = 0; j < sy; j++) gdImageSetPixel(newImage, sy - j - 1, i, gdImageGetPixel(m_image, i, j)); } setExtMemory(-1); gdImageDestroy(m_image); m_image = newImage; setExtMemory(); return 0; }
result_t Image::New(int32_t width, int32_t height, obj_ptr<Image> &retVal) { if (width <= 0 || height <= 0) return CHECK_ERROR(CALL_E_INVALIDARG); obj_ptr<Image> img = new Image(); if (gdImageTrueColor(m_image)) img->m_image = gdImageCreateTrueColor(width, height); else img->m_image = gdImageCreate(width, height); gdImagePaletteCopy(img->m_image, m_image); gdImageColorTransparent(img->m_image, gdImageGetTransparent(m_image)); img->setExtMemory(); retVal = img; return 0; }
static void make_thumb(void *conf) { int colors = 0; int transparent = -1; ngx_image_conf_t *info = conf; info->dst_im = gdImageCreateTrueColor(info->width,info->height); colors = gdImageColorsTotal(info->src_im); transparent = gdImageGetTransparent(info->src_im); if (transparent == -1) { gdImageSaveAlpha(info->src_im,1); gdImageColorTransparent(info->src_im, -1); if(colors == 0) { gdImageAlphaBlending(info->dst_im,0); gdImageSaveAlpha(info->dst_im,1); } if(colors) { gdImageTrueColorToPalette(info->dst_im,1,256); } } if(info->w_margin == 1) { info->w_im = gdImageCreateTrueColor(info->width,info->height); gdImageFilledRectangle(info->w_im, 0, 0, info->width,info->height, gdImageColorAllocate(info->w_im, 255, 255, 255)); info->dst_im = gdImageCreateTrueColor(info->max_width,info->max_height); gdImageFilledRectangle(info->dst_im, 0, 0, info->max_width,info->max_height, gdImageColorAllocate(info->dst_im, 255, 255, 255)); gdImageCopyResampled(info->w_im, info->src_im, 0, 0, info->src_x, info->src_y,info->width, info->height, info->src_w,info->src_h); gdImageCopyResampled(info->dst_im, info->w_im, info->dst_x,info->dst_y, 0, 0,info->width, info->height, info->width, info->height); gdImageDestroy(info->w_im); } else { gdImageCopyResampled(info->dst_im,info->src_im,info->dst_x,info->dst_y,info->src_x,info->src_y,info->width,info->height,info->src_w,info->src_h); } gdImageDestroy(info->src_im); }
static int set_penstyle(GVJ_t * job, gdImagePtr im, gdImagePtr brush) { obj_state_t *obj = job->obj; int i, pen, pencolor, transparent, width, dashstyle[40]; pen = pencolor = color_index(im, obj->pencolor); transparent = gdImageGetTransparent(im); if (obj->pen == PEN_DASHED) { for (i = 0; i < 20; i++) dashstyle[i] = pencolor; for (; i < 40; i++) dashstyle[i] = transparent; gdImageSetStyle(im, dashstyle, 20); pen = gdStyled; } else if (obj->pen == PEN_DOTTED) { for (i = 0; i < 2; i++) dashstyle[i] = pencolor; for (; i < 24; i++) dashstyle[i] = transparent; gdImageSetStyle(im, dashstyle, 24); pen = gdStyled; } width = obj->penwidth * job->scale.x; if (width < PENWIDTH_NORMAL) width = PENWIDTH_NORMAL; /* gd can't do thin lines */ gdImageSetThickness(im, width); /* use brush instead of Thickness to improve end butts */ if (width != PENWIDTH_NORMAL) { brush = gdImageCreate(width, width); gdImagePaletteCopy(brush, im); gdImageFilledRectangle(brush, 0, 0, width - 1, width - 1, pencolor); gdImageSetBrush(im, brush); if (pen == gdStyled) pen = gdStyledBrushed; else pen = gdBrushed; } return pen; }
/** * Function: gdImageCropAuto * * Crop an image automatically * * This function detects the cropping area according to the given _mode_. * * Parameters: * im - The image. * mode - The cropping mode, see <gdCropMode>. * * Returns: * The newly created cropped image, or NULL on failure. * * See also: * - <gdImageCrop> * - <gdImageCropThreshold> */ BGD_DECLARE(gdImagePtr) gdImageCropAuto(gdImagePtr im, const unsigned int mode) { const int width = gdImageSX(im); const int height = gdImageSY(im); int x,y; int color, match; gdRect crop; crop.x = 0; crop.y = 0; crop.width = 0; crop.height = 0; switch (mode) { case GD_CROP_TRANSPARENT: color = gdImageGetTransparent(im); break; case GD_CROP_BLACK: color = gdImageColorClosestAlpha(im, 0, 0, 0, 0); break; case GD_CROP_WHITE: color = gdImageColorClosestAlpha(im, 255, 255, 255, 0); break; case GD_CROP_SIDES: gdGuessBackgroundColorFromCorners(im, &color); break; case GD_CROP_DEFAULT: default: color = gdImageGetTransparent(im); break; } /* TODO: Add gdImageGetRowPtr and works with ptr at the row level * for the true color and palette images * new formats will simply work with ptr */ match = 1; for (y = 0; match && y < height; y++) { for (x = 0; match && x < width; x++) { match = (color == gdImageGetPixel(im, x,y)); } } /* Whole image would be cropped > bye */ if (match) { return NULL; } crop.y = y - 1; match = 1; for (y = height - 1; match && y >= 0; y--) { for (x = 0; match && x < width; x++) { match = (color == gdImageGetPixel(im, x,y)); } } crop.height = y - crop.y + 2; match = 1; for (x = 0; match && x < width; x++) { for (y = 0; match && y < crop.y + crop.height; y++) { match = (color == gdImageGetPixel(im, x,y)); } } crop.x = x - 1; match = 1; for (x = width - 1; match && x >= 0; x--) { for (y = 0; match && y < crop.y + crop.height; y++) { match = (color == gdImageGetPixel(im, x,y)); } } crop.width = x - crop.x + 2; return gdImageCrop(im, &crop); }
static VALUE fastimage_native_resize( VALUE self, VALUE rb_in, VALUE rb_out, VALUE rb_w, VALUE rb_h, VALUE rb_image_type, VALUE rb_jpeg_quality, VALUE rb_orientation ) { char *filename_in = StringValuePtr(rb_in); char *filename_out = StringValuePtr(rb_out); int w = NUM2INT(rb_w); int h = NUM2INT(rb_h); int image_type = NUM2INT(rb_image_type); int jpeg_quality = NUM2INT(rb_jpeg_quality); int orientation = NUM2INT(rb_orientation); gdImagePtr im_in, im_out; FILE *in, *out; int trans = 0, x = 0, y = 0, f = 0; in = fopen(filename_in, "rb"); if (!in) return Qnil; switch(image_type) { case 0: im_in = gdImageCreateFromJpeg(in); break; case 1: im_in = gdImageCreateFromPng(in); break; case 2: im_in = gdImageCreateFromGif(in); trans = gdImageGetTransparent(im_in); /* find a transparent pixel, then turn off transparency so that it copies correctly */ if (trans >= 0) { for (x=0; x<gdImageSX(im_in); x++) { for (y=0; y<gdImageSY(im_in); y++) { if (gdImageGetPixel(im_in, x, y) == trans) { f = 1; break; } } if (f) break; } gdImageColorTransparent(im_in, -1); if (!f) trans = -1; /* no transparent pixel found */ } break; } if (!im_in) { fclose(in); return Qnil; } /* Handle orientation */ if (orientation == 5 || orientation == 6) { im_in = gdImageRotateInterpolated(im_in, 270.0, 0); } if (orientation == 7 || orientation == 8) { im_in = gdImageRotateInterpolated(im_in, 90.0, 0); } if (!im_in) { fclose(in); return Qnil; } if (orientation == 2 || orientation == 5 || orientation == 7) { gdImageFlipHorizontal(im_in); } if (orientation == 3) { gdImageFlipBoth(im_in); } if (orientation == 4) { gdImageFlipVertical(im_in); } /* Compute target size */ if (w == 0 || h == 0) { int originalWidth = gdImageSX(im_in); int originalHeight = gdImageSY(im_in); if (h != 0) { w = (int)(h * originalWidth / originalHeight); } else if (w != 0) { h = (int)(w * originalHeight / originalWidth); } else { w = originalWidth; h = originalHeight; } } im_out = gdImageCreateTrueColor(w, h); /* must be truecolor */ if (im_out) { if (image_type == 1) { gdImageAlphaBlending(im_out, 0); /* handle transparency correctly */ gdImageSaveAlpha(im_out, 1); } fclose(in); } else { fclose(in); return Qnil; } /* Now copy the original */ gdImageCopyResampled(im_out, im_in, 0, 0, 0, 0, gdImageSX(im_out), gdImageSY(im_out), gdImageSX(im_in), gdImageSY(im_in)); out = fopen(filename_out, "wb"); if (out) { switch(image_type) { case 0: gdImageJpeg(im_out, out, jpeg_quality); break; case 1: gdImagePng(im_out, out); break; case 2: gdImageTrueColorToPalette(im_out, 0, 256); if (trans >= 0) { trans = gdImageGetPixel(im_out, x, y); /* get the color index of our transparent pixel */ gdImageColorTransparent(im_out, trans); /* may not always work as hoped */ } gdImageGif(im_out, out); break; } fclose(out); } gdImageDestroy(im_in); gdImageDestroy(im_out); return Qnil; }
static ngx_buf_t * ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) { int sx, sy, dx, dy, ox, oy, ax, ay, size, colors, palette, transparent, sharpen, red, green, blue, t; u_char *out; ngx_buf_t *b; ngx_uint_t resize; gdImagePtr src, dst; ngx_pool_cleanup_t *cln; ngx_http_image_filter_conf_t *conf; src = ngx_http_image_source(r, ctx); if (src == NULL) { return NULL; } sx = gdImageSX(src); sy = gdImageSY(src); conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); if (!ctx->force && ctx->angle == 0 && (ngx_uint_t) sx <= ctx->max_width && (ngx_uint_t) sy <= ctx->max_height) { gdImageDestroy(src); return ngx_http_image_asis(r, ctx); } colors = gdImageColorsTotal(src); if (colors && conf->transparency) { transparent = gdImageGetTransparent(src); if (transparent != -1) { palette = colors; red = gdImageRed(src, transparent); green = gdImageGreen(src, transparent); blue = gdImageBlue(src, transparent); goto transparent; } } palette = 0; transparent = -1; red = 0; green = 0; blue = 0; transparent: gdImageColorTransparent(src, -1); dx = sx; dy = sy; if (conf->filter == NGX_HTTP_IMAGE_RESIZE) { if ((ngx_uint_t) dx > ctx->max_width) { dy = dy * ctx->max_width / dx; dy = dy ? dy : 1; dx = ctx->max_width; } if ((ngx_uint_t) dy > ctx->max_height) { dx = dx * ctx->max_height / dy; dx = dx ? dx : 1; dy = ctx->max_height; } resize = 1; } else if (conf->filter == NGX_HTTP_IMAGE_ROTATE) { resize = 0; } else if (conf->filter == NGX_HTTP_IMAGE_WATERMARK) { resize = 0; } else { /* NGX_HTTP_IMAGE_CROP */ resize = 0; if ((double) dx / dy < (double) ctx->max_width / ctx->max_height) { if ((ngx_uint_t) dx > ctx->max_width) { dy = dy * ctx->max_width / dx; dy = dy ? dy : 1; dx = ctx->max_width; resize = 1; } } else { if ((ngx_uint_t) dy > ctx->max_height) { dx = dx * ctx->max_height / dy; dx = dx ? dx : 1; dy = ctx->max_height; resize = 1; } } } if (resize) { dst = ngx_http_image_new(r, dx, dy, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } else { dst = src; } if (ctx->angle) { src = dst; ax = (dx % 2 == 0) ? 1 : 0; ay = (dy % 2 == 0) ? 1 : 0; switch (ctx->angle) { case 90: case 270: dst = ngx_http_image_new(r, dy, dx, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } if (ctx->angle == 90) { ox = dy / 2 + ay; oy = dx / 2 - ax; } else { ox = dy / 2 - ay; oy = dx / 2 + ax; } gdImageCopyRotated(dst, src, ox, oy, 0, 0, dx + ax, dy + ay, ctx->angle); gdImageDestroy(src); t = dx; dx = dy; dy = t; break; case 180: dst = ngx_http_image_new(r, dx, dy, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } gdImageCopyRotated(dst, src, dx / 2 - ax, dy / 2 - ay, 0, 0, dx + ax, dy + ay, ctx->angle); gdImageDestroy(src); break; } } if (conf->filter == NGX_HTTP_IMAGE_CROP) { src = dst; if ((ngx_uint_t) dx > ctx->max_width) { ox = dx - ctx->max_width; } else { ox = 0; } if ((ngx_uint_t) dy > ctx->max_height) { oy = dy - ctx->max_height; } else { oy = 0; } if (ox || oy) { dst = ngx_http_image_new(r, dx - ox, dy - oy, colors); if (dst == NULL) { gdImageDestroy(src); return NULL; } ox /= 2; oy /= 2; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image crop: %d x %d @ %d x %d", dx, dy, ox, oy); if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } } if (transparent != -1 && colors) { gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue)); } if (conf->filter == NGX_HTTP_IMAGE_WATERMARK && conf->watermark.data) { FILE *watermark_file = fopen((const char *)conf->watermark.data, "r"); if (watermark_file) { gdImagePtr watermark, watermark_mix; ngx_int_t wdx = 0, wdy = 0; watermark = gdImageCreateFromPng(watermark_file); if(watermark != NULL) { watermark_mix = gdImageCreateTrueColor(watermark->sx, watermark->sy); if (ngx_strcmp(conf->watermark_position.data, "bottom-right") == 0) { wdx = dx - watermark->sx - 10; wdy = dy - watermark->sy - 10; } else if (ngx_strcmp(conf->watermark_position.data, "top-left") == 0) { wdx = wdy = 10; } else if (ngx_strcmp(conf->watermark_position.data, "top-right") == 0) { wdx = dx - watermark->sx - 10; wdy = 10; } else if (ngx_strcmp(conf->watermark_position.data, "bottom-left") == 0) { wdx = 10; wdy = dy - watermark->sy - 10; } else if (ngx_strcmp(conf->watermark_position.data, "center") == 0) { wdx = dx / 2 - watermark->sx / 2; wdy = dy / 2 - watermark->sy / 2; } gdImageCopy(watermark_mix, dst, 0, 0, wdx, wdy, watermark->sx, watermark->sy); gdImageCopy(watermark_mix, watermark, 0, 0, 0, 0, watermark->sx, watermark->sy); gdImageCopyMerge(dst, watermark_mix, wdx, wdy, 0, 0, watermark->sx, watermark->sy, 75); gdFree(watermark); gdFree(watermark_mix); } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "watermark file '%s' is not PNG", conf->watermark.data);} } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "watermark file '%s' not found", conf->watermark.data); } } sharpen = ngx_http_image_filter_get_value(r, conf->shcv, conf->sharpen); if (sharpen > 0) { gdImageSharpen(dst, sharpen); } gdImageInterlace(dst, (int) conf->interlace); out = ngx_http_image_out(r, ctx->type, dst, &size); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image: %d x %d %d", sx, sy, colors); gdImageDestroy(dst); ngx_pfree(r->pool, ctx->image); if (out == NULL) { return NULL; } cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { gdFree(out); return NULL; } b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { gdFree(out); return NULL; } cln->handler = ngx_http_image_cleanup; cln->data = out; b->pos = out; b->last = out + size; b->memory = 1; b->last_buf = 1; ngx_http_image_length(r, b); return b; }
static ngx_buf_t * ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) { int sx, sy, dx, dy, ox, oy, ax, ay, size, colors, palette, transparent, sharpen, red, green, blue, t, offset_x, offset_y; u_char *out; ngx_buf_t *b; ngx_uint_t resize; gdImagePtr src, dst; ngx_pool_cleanup_t *cln; ngx_http_image_filter_conf_t *conf; src = ngx_http_image_source(r, ctx); if (src == NULL) { return NULL; } sx = gdImageSX(src); sy = gdImageSY(src); conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); if (!ctx->force && ctx->angle == 0 && (ngx_uint_t) sx <= ctx->max_width && (ngx_uint_t) sy <= ctx->max_height) { gdImageDestroy(src); return ngx_http_image_asis(r, ctx); } colors = gdImageColorsTotal(src); if (colors && conf->transparency) { transparent = gdImageGetTransparent(src); if (transparent != -1) { palette = colors; red = gdImageRed(src, transparent); green = gdImageGreen(src, transparent); blue = gdImageBlue(src, transparent); goto transparent; } } palette = 0; transparent = -1; red = 0; green = 0; blue = 0; transparent: gdImageColorTransparent(src, -1); dx = sx; dy = sy; if (conf->filter == NGX_HTTP_IMAGE_RESIZE) { if ((ngx_uint_t) dx > ctx->max_width) { dy = dy * ctx->max_width / dx; dy = dy ? dy : 1; dx = ctx->max_width; } if ((ngx_uint_t) dy > ctx->max_height) { dx = dx * ctx->max_height / dy; dx = dx ? dx : 1; dy = ctx->max_height; } resize = 1; } else if (conf->filter == NGX_HTTP_IMAGE_ROTATE) { resize = 0; } else { /* NGX_HTTP_IMAGE_CROP */ resize = 0; if ((double) dx / dy < (double) ctx->max_width / ctx->max_height) { if ((ngx_uint_t) dx > ctx->max_width) { dy = dy * ctx->max_width / dx; dy = dy ? dy : 1; dx = ctx->max_width; resize = 1; } } else { if ((ngx_uint_t) dy > ctx->max_height) { dx = dx * ctx->max_height / dy; dx = dx ? dx : 1; dy = ctx->max_height; resize = 1; } } } if (resize) { dst = ngx_http_image_new(r, dx, dy, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } else { dst = src; } if (ctx->angle) { src = dst; ax = (dx % 2 == 0) ? 1 : 0; ay = (dy % 2 == 0) ? 1 : 0; switch (ctx->angle) { case 90: case 270: dst = ngx_http_image_new(r, dy, dx, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } if (ctx->angle == 90) { ox = dy / 2 + ay; oy = dx / 2 - ax; } else { ox = dy / 2 - ay; oy = dx / 2 + ax; } gdImageCopyRotated(dst, src, ox, oy, 0, 0, dx + ax, dy + ay, ctx->angle); gdImageDestroy(src); t = dx; dx = dy; dy = t; break; case 180: dst = ngx_http_image_new(r, dx, dy, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } gdImageCopyRotated(dst, src, dx / 2 - ax, dy / 2 - ay, 0, 0, dx + ax, dy + ay, ctx->angle); gdImageDestroy(src); break; } } if (conf->filter == NGX_HTTP_IMAGE_CROP) { src = dst; if ((ngx_uint_t) dx > ctx->max_width) { ox = dx - ctx->max_width; } else { ox = 0; } if ((ngx_uint_t) dy > ctx->max_height) { oy = dy - ctx->max_height; } else { oy = 0; } if (ox || oy) { dst = ngx_http_image_new(r, dx - ox, dy - oy, colors); if (dst == NULL) { gdImageDestroy(src); return NULL; } offset_x = ngx_http_image_filter_get_value(r, conf->oxcv, conf->offset_x); offset_y = ngx_http_image_filter_get_value(r, conf->oycv, conf->offset_y); if (offset_x == NGX_HTTP_IMAGE_OFFSET_LEFT) { ox = 0; } else if (offset_x == NGX_HTTP_IMAGE_OFFSET_CENTER) { ox /= 2; } if (offset_y == NGX_HTTP_IMAGE_OFFSET_TOP) { oy = 0; } else if (offset_y == NGX_HTTP_IMAGE_OFFSET_CENTER) { oy /= 2; } ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image crop: %d x %d @ %d x %d", dx, dy, ox, oy); if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } } if (transparent != -1 && colors) { gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue)); } sharpen = ngx_http_image_filter_get_value(r, conf->shcv, conf->sharpen); if (sharpen > 0) { gdImageSharpen(dst, sharpen); } out = ngx_http_image_out(r, ctx->type, dst, &size); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image: %d x %d %d", sx, sy, colors); gdImageDestroy(dst); ngx_pfree(r->pool, ctx->image); if (out == NULL) { return NULL; } cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { gdFree(out); return NULL; } b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { gdFree(out); return NULL; } cln->handler = ngx_http_image_cleanup; cln->data = out; b->pos = out; b->last = out + size; b->memory = 1; b->last_buf = 1; ngx_http_image_length(r, b); return b; }
ngx_int_t ngx_http_small_light_gd_process(ngx_http_request_t *r, ngx_http_small_light_ctx_t *ctx) { ngx_http_small_light_gd_ctx_t *ictx; ngx_http_small_light_image_size_t sz; gdImagePtr src, dst, canvas; ngx_int_t colors, transparent, palette, red, green, blue; ngx_int_t ax, ay, ox, oy, type; int iw, ih, radius, ccolor, bcolor; char *sharpen, *of; u_char *out; int size; double q; ictx = (ngx_http_small_light_gd_ctx_t *)ctx->ictx; src = ngx_http_small_light_gd_src(ictx); if (src == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to get image source %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } /* adjust image size */ iw = gdImageSX(src); ih = gdImageSY(src); ngx_http_small_light_calc_image_size(r, ctx, &sz, iw, ih); colors = gdImageColorsTotal(src); palette = 0; transparent = -1; red = 0; green = 0; blue = 0; if (colors) { transparent = gdImageGetTransparent(src); if (transparent != -1) { palette = colors; red = gdImageRed(src, transparent); green = gdImageGreen(src, transparent); blue = gdImageBlue(src, transparent); } } gdImageColorTransparent(src, -1); /* rotate. */ if (sz.angle) { dst = src; ax = (iw % 2 == 0) ? 1 : 0; ay = (ih % 2 == 0) ? 1 : 0; switch (sz.angle) { case 90: case 270: dst = ngx_http_small_light_gd_new(ih, iw, palette); if (dst == NULL) { gdImageDestroy(src); return NGX_ERROR; } if (sz.angle == 90) { ox = ih / 2 - ay; oy = iw / 2 + ax; } else { ox = ih / 2 + ay; oy = iw / 2 - ax; } gdImageCopyRotated(dst, src, ox, oy, 0, 0, iw, ih, -sz.angle); gdImageDestroy(src); break; case 180: dst = ngx_http_small_light_gd_new(iw, ih, palette); if (dst == NULL) { gdImageDestroy(src); return NGX_ERROR; } gdImageCopyRotated(dst, src, iw / 2 - ax, ih / 2 - ay, 0, 0, iw + ax, ih + ay, sz.angle); gdImageDestroy(src); break; default: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "image not rotated. 'angle'(%ui) must be 90 or 180 or 270. %s:%d", sz.angle, __FUNCTION__, __LINE__); break; } src = dst; } /* calc size. */ iw = gdImageSX(src); ih = gdImageSY(src); ngx_http_small_light_calc_image_size(r, ctx, &sz, iw, ih); /* pass through. */ if (sz.pt_flg != 0) { gdImageDestroy(src); ctx->of = ctx->inf; return NGX_OK; } /* crop, scale. */ if (sz.scale_flg != 0) { dst = ngx_http_small_light_gd_new(sz.dw, sz.dh, palette); if (dst == NULL) { gdImageDestroy(src); return NGX_ERROR; } if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopyResampled(dst, src, 0, 0, sz.sx, sz.sy, sz.dw, sz.dh, sz.sw, sz.sh); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } else { dst = src; } if (transparent != -1 && colors) { gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue)); } /* effects. */ sharpen = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "sharpen"); if (sharpen != NULL) { radius = ngx_http_small_light_parse_int(sharpen); if (radius > 0) { gdImageSharpen(dst, radius); } } /* interlace */ gdImageInterlace(dst, 1); /* create canvas then draw image to the canvas. */ if (sz.cw > 0.0 && sz.ch > 0.0) { canvas = gdImageCreateTrueColor(sz.cw, sz.ch); if (canvas == NULL) { gdImageDestroy(dst); return NGX_ERROR; } ccolor = gdImageColorAllocateAlpha(canvas, sz.cc.r, sz.cc.g, sz.cc.b, sz.cc.a); gdImageFilledRectangle(canvas, 0, 0, sz.cw, sz.ch, ccolor); gdImageCopy(canvas, dst, sz.dx, sz.dy, 0, 0, sz.dw, sz.dh); gdImageDestroy(dst); dst = canvas; } /* border. */ if (sz.bw > 0.0 || sz.bh > 0.0) { bcolor = gdImageColorAllocateAlpha(dst, sz.bc.r, sz.bc.g, sz.bc.b, sz.bc.a); if (sz.cw > 0.0 && sz.ch > 0.0) { gdImageFilledRectangle(dst, 0, 0, sz.cw, sz.bh, bcolor); gdImageFilledRectangle(dst, 0, 0, sz.bw, sz.ch, bcolor); gdImageFilledRectangle(dst, 0, sz.ch - sz.bh, sz.cw - 1, sz.ch - 1, bcolor); gdImageFilledRectangle(dst, sz.cw - sz.bw, 0, sz.cw - 1, sz.ch - 1, bcolor); } else { gdImageFilledRectangle(dst, 0, 0, sz.dw, sz.bh, bcolor); gdImageFilledRectangle(dst, 0, 0, sz.bw, sz.dh, bcolor); gdImageFilledRectangle(dst, 0, sz.dh - sz.bh, sz.dw - 1, sz.dh - 1, bcolor); gdImageFilledRectangle(dst, sz.dw - sz.bw, 0, sz.dw - 1, sz.dh - 1, bcolor); } } of = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "of"); if (ngx_strlen(of) > 0) { type = ngx_http_small_light_type(of); if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_NONE) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "of is invalid(%s) %s:%d", of, __FUNCTION__, __LINE__); } else if (type == NGX_HTTP_SMALL_LIGHT_IMAGE_WEBP) { #ifdef NGX_HTTP_SMALL_LIGHT_GD_WEBP_ENABLED ictx->type = type; #else ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "WebP is not supported %s:%d", __FUNCTION__, __LINE__); #endif } else { ictx->type = type; } } ctx->of = ngx_http_small_light_image_types[ictx->type - 1]; q = ngx_http_small_light_parse_double(NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "q")); if (q == 0) { q = 100; } out = ngx_http_small_light_gd_out(dst, ictx->type, (int *)&size, q); gdImageDestroy(dst); if (out == NULL) { return NGX_ERROR; } /* get small_lighted image as binary. */ ctx->content = out; ctx->content_length = size; ngx_pfree(r->pool, ctx->content_orig); ictx->complete = 1; return NGX_OK; }
int main(int argc, char **argv) { FILE *in; FILE *out; char outFn[20]; int useStdinStdout=0; /* Declare our image pointer */ gdImagePtr im = 0; int i; /* We'll clear 'no' once we know the user has made a reasonable request. */ int no = 1; /* We'll set 'write' once we know the user's request requires that the image be written back to disk. */ int write = 0; /* C programs always get at least one argument; we want at least one more (the image), more in practice. */ if (argc < 2 || !strcmp(argv[1], "--help")) { no = 1; goto usage; } /* The last argument should be the image. Open the file. */ if (strcmp("-", argv[argc-1])==0) { /* - is synonymous with STDIN */ useStdinStdout = 1; in = stdin; } else { in = fopen(argv[argc-1], "rb"); } if (!in) { fprintf(stderr, "Error: can't open file %s.\n", argv[argc-1]); exit(1); } /* Now load the image. */ im = gdImageCreateFromPng(in); fclose(in); /* If the load failed, it must not be a PNG file. */ if (!im) { fprintf(stderr, "Error: %s is not a valid PNG file.\n", argv[argc-1]); exit(1); } /* Consider each argument in turn. */ for (i=1; (i < (argc-1)); i++) { /* -i turns on and off interlacing. */ if (!strcmp(argv[i], "--help")) { /* Every program should use this for help! :) */ no = 1; goto usage; } else if (!strcmp(argv[i], "-i")) { if (i == (argc-2)) { fprintf(stderr, "Error: -i specified without y or n.\n"); no = 1; goto usage; } if (!strcmp(argv[i+1], "y")) { /* Set interlace. */ gdImageInterlace(im, 1); } else if (!strcmp(argv[i+1], "n")) { /* Clear interlace. */ gdImageInterlace(im, 0); } else { fprintf(stderr, "Error: -i specified without y or n.\n"); no = 1; goto usage; } i++; no = 0; write = 1; } else if (!strcmp(argv[i], "-t")) { /* Set transparent index (or none). */ int index; if (i == (argc-2)) { fprintf(stderr, "Error: -t specified without a color table index.\n"); no = 1; goto usage; } if (!strcmp(argv[i+1], "none")) { /* -1 means not transparent. */ gdImageColorTransparent(im, -1); } else { /* OK, get an integer and set the index. */ index = atoi(argv[i+1]); gdImageColorTransparent(im, index); } i++; write = 1; no = 0; } else if (!strcmp(argv[i], "-l")) { /* List the colors in the color table. */ int j; /* Tabs used below. */ printf("Index Red Green Blue\n"); for (j=0; (j < gdImageColorsTotal(im)); j++) { /* Use access macros to learn colors. */ printf("%d %d %d %d\n", j, gdImageRed(im, j), gdImageGreen(im, j), gdImageBlue(im, j)); } no = 0; } else if (!strcmp(argv[i], "-d")) { /* Output dimensions, etc. */ int t; printf("Width: %d Height: %d Colors: %d\n", gdImageSX(im), gdImageSY(im), gdImageColorsTotal(im)); t = gdImageGetTransparent(im); if (t != (-1)) { printf("Transparent index: %d\n", t); } else { /* -1 means the image is not transparent. */ printf("Transparent index: none\n"); } if (gdImageGetInterlaced(im)) { printf("Interlaced: yes\n"); } else { printf("Interlaced: no\n"); } no = 0; } else { fprintf(stderr, "Unknown argument: %s\n", argv[i]); break; } } usage: if (no) { /* If the command failed, output an explanation. */ fprintf(stderr, "Usage: webpng [-i y|n ] [-l] [-t index|none ] [-d] pngname.png\n" " -i [y|n] Turns on/off interlace\n" " -l Prints the table of color indexes\n" " -t [index] Set the transparent color to the specified index (0-255 or \"none\")\n" " -d Reports the dimensions and other characteristics of the image.\n" "\n" "If you specify '-' as the input file, stdin/stdout will be used input/output.\n" ); } if (write) { if (useStdinStdout) { out = stdout; } else { /* Open a temporary file. */ /* "temp.tmp" is not good temporary filename. */ sprintf(outFn, "webpng.tmp%d", getpid()); out = fopen(outFn, "wb"); if (!out) { fprintf(stderr, "Unable to write to %s -- exiting\n", outFn); exit(1); } } /* Write the new PNG. */ gdImagePng(im, out); if (!useStdinStdout) { fclose(out); /* Erase the old PNG. */ unlink(argv[argc-1]); /* Rename the new to the old. */ if (rename(outFn, argv[argc-1])!=0) { perror("rename"); exit(1); } } } /* Delete the image from memory. */ if (im) { gdImageDestroy(im); } /* All's well that ends well. */ return 0; }
/** * Function: gdImageAutoCrop * Automatic croping of the src image using the given mode * (see <gdCropMode>) * * * Parameters: * im - Source image * mode - crop mode * * Returns: * <gdImagePtr> on success or NULL * * See also: * <gdCropMode> */ gdImagePtr gdImageCropAuto(gdImagePtr im, const unsigned int mode) { const int width = gdImageSX(im); const int height = gdImageSY(im); int x,y; int color, corners, match; gdRect crop; crop.x = 0; crop.y = 0; crop.width = 0; crop.height = 0; switch (mode) { case GD_CROP_TRANSPARENT: color = gdImageGetTransparent(im); break; case GD_CROP_BLACK: color = gdImageColorClosestAlpha(im, 0, 0, 0, 0); break; case GD_CROP_WHITE: color = gdImageColorClosestAlpha(im, 255, 255, 255, 0); break; case GD_CROP_SIDES: corners = gdGuessBackgroundColorFromCorners(im, &color); break; case GD_CROP_DEFAULT: default: color = gdImageGetTransparent(im); if (color == -1) { corners = gdGuessBackgroundColorFromCorners(im, &color); } break; } /* TODO: Add gdImageGetRowPtr and works with ptr at the row level * for the true color and palette images * new formats will simply work with ptr */ match = 1; for (y = 0; match && y < height; y++) { for (x = 0; match && x < width; x++) { int c2 = gdImageGetPixel(im, x, y); match = (color == c2); } } /* Nothing to do > bye * Duplicate the image? */ if (y == height - 1) { return NULL; } crop.y = y -1; match = 1; for (y = height - 1; match && y >= 0; y--) { for (x = 0; match && x < width; x++) { match = (color == gdImageGetPixel(im, x,y)); } } if (y == 0) { crop.height = height - crop.y + 1; } else { crop.height = y - crop.y + 2; } match = 1; for (x = 0; match && x < width; x++) { for (y = 0; match && y < crop.y + crop.height - 1; y++) { match = (color == gdImageGetPixel(im, x,y)); } } crop.x = x - 1; match = 1; for (x = width - 1; match && x >= 0; x--) { for (y = 0; match && y < crop.y + crop.height - 1; y++) { match = (color == gdImageGetPixel(im, x,y)); } } crop.width = x - crop.x + 2; if (crop.x <= 0 || crop.y <= 0 || crop.width <= 0 || crop.height <= 0) { return NULL; } return gdImageCrop(im, &crop); }
result_t Image::getData(int32_t format, int32_t quality, obj_ptr<Buffer_base> &retVal, AsyncEvent *ac) { if (!m_image) return CHECK_ERROR(CALL_E_INVALID_CALL); if (!ac) return CHECK_ERROR(CALL_E_NOSYNC); int32_t size = 0; void *data = NULL; int32_t sx = gdImageSX(m_image); int32_t sy = gdImageSY(m_image); int32_t i, j; int32_t trans = -1; if (gdImageTrueColor(m_image)) { for (i = 0; i < sx && trans == -1; i ++) for (j = 0; j < sy && trans == -1; j++) if ((gdImageGetPixel(m_image, i, j) & 0xff000000) != 0) trans = 0; } else trans = gdImageGetTransparent(m_image); gdImagePtr nowImage = m_image; if (trans != -1) { if (format != gd_base::_PNG) { if (gdImageTrueColor(m_image)) nowImage = gdImageCreateTrueColor(sx, sy); else { nowImage = gdImageCreate(sx, sy); gdImagePaletteCopy(nowImage, m_image); } gdImageFilledRectangle(nowImage, 0, 0, sx, sy, gdImageColorAllocate(nowImage, 255, 255, 255)); gdImageCopy(nowImage, m_image, 0, 0, 0, 0, sx, sy); } else if (gdImageTrueColor(m_image)) gdImageSaveAlpha(m_image, 1); } switch (format) { case gd_base::_GIF: data = gdImageGifPtr(nowImage, &size); break; case gd_base::_PNG: data = gdImagePngPtr(nowImage, &size); break; case gd_base::_JPEG: { unsigned char *ed_data = NULL; uint32_t ed_size = 0; data = gdImageJpegPtr(nowImage, &size, quality, ed_data, ed_size); if (ed_data) free(ed_data); break; } case gd_base::_TIFF: data = gdImageTiffPtr(nowImage, &size); break; case gd_base::_BMP: data = gdImageBmpPtr(nowImage, &size, 1); break; case gd_base::_WEBP: data = gdImageWebpPtrEx(nowImage, &size, quality); break; } if (nowImage != m_image) gdImageDestroy(nowImage); if (data == NULL) return CHECK_ERROR(CALL_E_INVALIDARG); retVal = new Buffer(std::string((char *) data, size)); gdFree(data); return 0; }
static ngx_buf_t * ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) { int sx, sy, dx, dy, ox, oy, size, colors, palette, transparent, red, green, blue; u_char *out; ngx_buf_t *b; ngx_uint_t resize; gdImagePtr src, dst; ngx_pool_cleanup_t *cln; ngx_http_image_filter_conf_t *conf; src = ngx_http_image_source(r, ctx); if (src == NULL) { return NULL; } sx = gdImageSX(src); sy = gdImageSY(src); conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); if (!ctx->force && (ngx_uint_t) sx <= ctx->max_width && (ngx_uint_t) sy <= ctx->max_height) { gdImageDestroy(src); return ngx_http_image_asis(r, ctx); } colors = gdImageColorsTotal(src); if (colors && conf->transparency) { transparent = gdImageGetTransparent(src); if (transparent != -1) { palette = colors; red = gdImageRed(src, transparent); green = gdImageGreen(src, transparent); blue = gdImageBlue(src, transparent); goto transparent; } } palette = 0; transparent = -1; red = 0; green = 0; blue = 0; transparent: gdImageColorTransparent(src, -1); dx = sx; dy = sy; if (conf->filter == NGX_HTTP_IMAGE_RESIZE) { if ((ngx_uint_t) dx > ctx->max_width) { dy = dy * ctx->max_width / dx; dy = dy ? dy : 1; dx = ctx->max_width; } if ((ngx_uint_t) dy > ctx->max_height) { dx = dx * ctx->max_height / dy; dx = dx ? dx : 1; dy = ctx->max_height; } resize = 1; } else { /* NGX_HTTP_IMAGE_CROP */ resize = 0; if ((ngx_uint_t) (dx * 100 / dy) < ctx->max_width * 100 / ctx->max_height) { if ((ngx_uint_t) dx > ctx->max_width) { dy = dy * ctx->max_width / dx; dy = dy ? dy : 1; dx = ctx->max_width; resize = 1; } } else { if ((ngx_uint_t) dy > ctx->max_height) { dx = dx * ctx->max_height / dy; dx = dx ? dx : 1; dy = ctx->max_height; resize = 1; } } } if (resize) { dst = ngx_http_image_new(r, dx, dy, palette); if (dst == NULL) { gdImageDestroy(src); return NULL; } if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } else { dst = src; } if (conf->filter == NGX_HTTP_IMAGE_CROP) { src = dst; if ((ngx_uint_t) dx > ctx->max_width) { ox = dx - ctx->max_width; } else { ox = 0; } if ((ngx_uint_t) dy > ctx->max_height) { oy = dy - ctx->max_height; } else { oy = 0; } if (ox || oy) { dst = ngx_http_image_new(r, dx - ox, dy - oy, colors); if (dst == NULL) { gdImageDestroy(src); return NULL; } ox /= 2; oy /= 2; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image crop: %d x %d @ %d x %d", dx, dy, ox, oy); if (colors == 0) { gdImageSaveAlpha(dst, 1); gdImageAlphaBlending(dst, 0); } gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy); if (colors) { gdImageTrueColorToPalette(dst, 1, 256); } gdImageDestroy(src); } } if (transparent != -1 && colors) { gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue)); } out = ngx_http_image_out(r, ctx->type, dst, &size); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image: %d x %d %d", sx, sy, colors); gdImageDestroy(dst); ngx_pfree(r->pool, ctx->image); if (out == NULL) { return NULL; } cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { gdFree(out); return NULL; } b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { gdFree(out); return NULL; } cln->handler = ngx_http_image_cleanup; cln->data = out; b->pos = out; b->last = out + size; b->memory = 1; b->last_buf = 1; ngx_http_image_length(r, b); return b; }
int msSaveImageGDAL( mapObj *map, imageObj *image, char *filename ) { int bFileIsTemporary = MS_FALSE; GDALDatasetH hMemDS, hOutputDS; GDALDriverH hMemDriver, hOutputDriver; int nBands = 1; int iLine; GByte *pabyAlphaLine = NULL; char **papszOptions = NULL; outputFormatObj *format = image->format; rasterBufferObj rb; GDALDataType eDataType = GDT_Byte; int bUseXmp = MS_FALSE; msGDALInitialize(); memset(&rb,0,sizeof(rasterBufferObj)); #ifdef USE_EXEMPI if( map != NULL ) { bUseXmp = msXmpPresent(map); } #endif /* -------------------------------------------------------------------- */ /* Identify the proposed output driver. */ /* -------------------------------------------------------------------- */ msAcquireLock( TLOCK_GDAL ); hOutputDriver = GDALGetDriverByName( format->driver+5 ); if( hOutputDriver == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to find %s driver.", "msSaveImageGDAL()", format->driver+5 ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* We will need to write the output to a temporary file and */ /* then stream to stdout if no filename is passed. If the */ /* driver supports virtualio then we hold the temporary file in */ /* memory, otherwise we try to put it in a reasonable temporary */ /* file location. */ /* -------------------------------------------------------------------- */ if( filename == NULL ) { const char *pszExtension = format->extension; if( pszExtension == NULL ) pszExtension = "img.tmp"; if( bUseXmp == MS_FALSE && GDALGetMetadataItem( hOutputDriver, GDAL_DCAP_VIRTUALIO, NULL ) != NULL ) { CleanVSIDir( "/vsimem/msout" ); filename = msTmpFile(map, NULL, "/vsimem/msout/", pszExtension ); } if( filename == NULL && map != NULL) filename = msTmpFile(map, map->mappath,NULL,pszExtension); else if( filename == NULL ) { filename = msTmpFile(map, NULL, NULL, pszExtension ); } bFileIsTemporary = MS_TRUE; } /* -------------------------------------------------------------------- */ /* Establish the characteristics of our memory, and final */ /* dataset. */ /* -------------------------------------------------------------------- */ if( format->imagemode == MS_IMAGEMODE_RGB ) { nBands = 3; assert( MS_RENDERER_PLUGIN(format) && format->vtable->supports_pixel_buffer ); format->vtable->getRasterBufferHandle(image,&rb); } else if( format->imagemode == MS_IMAGEMODE_RGBA ) { pabyAlphaLine = (GByte *) calloc(image->width,1); if (pabyAlphaLine == NULL) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "Out of memory allocating %u bytes.\n", "msSaveImageGDAL()", image->width); return MS_FAILURE; } nBands = 4; assert( MS_RENDERER_PLUGIN(format) && format->vtable->supports_pixel_buffer ); format->vtable->getRasterBufferHandle(image,&rb); } else if( format->imagemode == MS_IMAGEMODE_INT16 ) { nBands = format->bands; eDataType = GDT_Int16; } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) { nBands = format->bands; eDataType = GDT_Float32; } else if( format->imagemode == MS_IMAGEMODE_BYTE ) { nBands = format->bands; eDataType = GDT_Byte; } else { #ifdef USE_GD assert( format->imagemode == MS_IMAGEMODE_PC256 && format->renderer == MS_RENDER_WITH_GD ); #else { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "GD not compiled in. This is a bug.", "msSaveImageGDAL()"); return MS_FAILURE; } #endif } /* -------------------------------------------------------------------- */ /* Create a memory dataset which we can use as a source for a */ /* CreateCopy(). */ /* -------------------------------------------------------------------- */ hMemDriver = GDALGetDriverByName( "MEM" ); if( hMemDriver == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to find MEM driver.", "msSaveImageGDAL()" ); return MS_FAILURE; } hMemDS = GDALCreate( hMemDriver, "msSaveImageGDAL_temp", image->width, image->height, nBands, eDataType, NULL ); if( hMemDS == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to create MEM dataset.", "msSaveImageGDAL()" ); return MS_FAILURE; } /* -------------------------------------------------------------------- */ /* Copy the gd image into the memory dataset. */ /* -------------------------------------------------------------------- */ for( iLine = 0; iLine < image->height; iLine++ ) { int iBand; for( iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 ); if( format->imagemode == MS_IMAGEMODE_INT16 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_16bit + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Int16, 2, 0 ); } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_float + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Float32, 4, 0 ); } else if( format->imagemode == MS_IMAGEMODE_BYTE ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, image->img.raw_byte + iLine * image->width + iBand * image->width * image->height, image->width, 1, GDT_Byte, 1, 0 ); } #ifdef USE_GD else if(format->renderer == MS_RENDER_WITH_GD) { gdImagePtr img = (gdImagePtr)image->img.plugin; GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, img->pixels[iLine], image->width, 1, GDT_Byte, 0, 0 ); } #endif else { GByte *pabyData; unsigned char *pixptr = NULL; assert( rb.type == MS_BUFFER_BYTE_RGBA ); switch(iBand) { case 0: pixptr = rb.data.rgba.r; break; case 1: pixptr = rb.data.rgba.g; break; case 2: pixptr = rb.data.rgba.b; break; case 3: pixptr = rb.data.rgba.a; break; } assert(pixptr); if( pixptr == NULL ) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Missing RGB or A buffer.\n", "msSaveImageGDAL()" ); return MS_FAILURE; } pabyData = (GByte *)(pixptr + iLine*rb.data.rgba.row_step); if( rb.data.rgba.a == NULL || iBand == 3 ) { GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, pabyData, image->width, 1, GDT_Byte, rb.data.rgba.pixel_step, 0 ); } else { /* We need to un-pre-multiple RGB by alpha. */ GByte *pabyUPM = (GByte*) malloc(image->width); GByte *pabyAlpha= (GByte *)(rb.data.rgba.a + iLine*rb.data.rgba.row_step); int i; for( i = 0; i < image->width; i++ ) { int alpha = pabyAlpha[i*rb.data.rgba.pixel_step]; if( alpha == 0 ) pabyUPM[i] = 0; else { int result = (pabyData[i*rb.data.rgba.pixel_step] * 255) / alpha; if( result > 255 ) result = 255; pabyUPM[i] = result; } } GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1, pabyUPM, image->width, 1, GDT_Byte, 1, 0 ); free( pabyUPM ); } } } } if( pabyAlphaLine != NULL ) free( pabyAlphaLine ); /* -------------------------------------------------------------------- */ /* Attach the palette if appropriate. */ /* -------------------------------------------------------------------- */ #ifdef USE_GD if( format->renderer == MS_RENDER_WITH_GD ) { GDALColorEntry sEntry; int iColor; GDALColorTableH hCT; gdImagePtr img = (gdImagePtr)image->img.plugin; hCT = GDALCreateColorTable( GPI_RGB ); for( iColor = 0; iColor < img->colorsTotal; iColor++ ) { sEntry.c1 = img->red[iColor]; sEntry.c2 = img->green[iColor]; sEntry.c3 = img->blue[iColor]; if( iColor == gdImageGetTransparent( img ) ) sEntry.c4 = 0; else if( iColor == 0 && gdImageGetTransparent( img ) == -1 && format->transparent ) sEntry.c4 = 0; else sEntry.c4 = 255; GDALSetColorEntry( hCT, iColor, &sEntry ); } GDALSetRasterColorTable( GDALGetRasterBand( hMemDS, 1 ), hCT ); GDALDestroyColorTable( hCT ); } else #endif if( format->imagemode == MS_IMAGEMODE_RGB ) { GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand ); } else if( format->imagemode == MS_IMAGEMODE_RGBA ) { GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand ); GDALSetRasterColorInterpretation( GDALGetRasterBand( hMemDS, 4 ), GCI_AlphaBand ); } /* -------------------------------------------------------------------- */ /* Assign the projection and coordinate system to the memory */ /* dataset. */ /* -------------------------------------------------------------------- */ if( map != NULL ) { char *pszWKT; GDALSetGeoTransform( hMemDS, map->gt.geotransform ); pszWKT = msProjectionObj2OGCWKT( &(map->projection) ); if( pszWKT != NULL ) { GDALSetProjection( hMemDS, pszWKT ); msFree( pszWKT ); } } /* -------------------------------------------------------------------- */ /* Possibly assign a nodata value. */ /* -------------------------------------------------------------------- */ if( msGetOutputFormatOption(format,"NULLVALUE",NULL) != NULL ) { int iBand; const char *nullvalue = msGetOutputFormatOption(format, "NULLVALUE",NULL); for( iBand = 0; iBand < nBands; iBand++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 ); GDALSetRasterNoDataValue( hBand, atof(nullvalue) ); } } /* -------------------------------------------------------------------- */ /* Try to save resolution in the output file. */ /* -------------------------------------------------------------------- */ if( image->resolution > 0 ) { char res[30]; sprintf( res, "%lf", image->resolution ); GDALSetMetadataItem( hMemDS, "TIFFTAG_XRESOLUTION", res, NULL ); GDALSetMetadataItem( hMemDS, "TIFFTAG_YRESOLUTION", res, NULL ); GDALSetMetadataItem( hMemDS, "TIFFTAG_RESOLUTIONUNIT", "2", NULL ); } /* -------------------------------------------------------------------- */ /* Create a disk image in the selected output format from the */ /* memory image. */ /* -------------------------------------------------------------------- */ papszOptions = (char**)calloc(sizeof(char *),(format->numformatoptions+1)); if (papszOptions == NULL) { msReleaseLock( TLOCK_GDAL ); msSetError( MS_MEMERR, "Out of memory allocating %u bytes.\n", "msSaveImageGDAL()", (unsigned int)(sizeof(char *)*(format->numformatoptions+1))); return MS_FAILURE; } memcpy( papszOptions, format->formatoptions, sizeof(char *) * format->numformatoptions ); hOutputDS = GDALCreateCopy( hOutputDriver, filename, hMemDS, FALSE, papszOptions, NULL, NULL ); free( papszOptions ); if( hOutputDS == NULL ) { GDALClose( hMemDS ); msReleaseLock( TLOCK_GDAL ); msSetError( MS_MISCERR, "Failed to create output %s file.\n%s", "msSaveImageGDAL()", format->driver+5, CPLGetLastErrorMsg() ); return MS_FAILURE; } /* closing the memory DS also frees all associated resources. */ GDALClose( hMemDS ); GDALClose( hOutputDS ); msReleaseLock( TLOCK_GDAL ); /* -------------------------------------------------------------------- */ /* Are we writing license info into the image? */ /* If so, add it to the temp file on disk now. */ /* -------------------------------------------------------------------- */ #ifdef USE_EXEMPI if ( bUseXmp == MS_TRUE ) { if( msXmpWrite(map, filename) == MS_FAILURE ) { /* Something bad happened. */ msSetError( MS_MISCERR, "XMP write to %s failed.\n", "msSaveImageGDAL()", filename); return MS_FAILURE; } } #endif /* -------------------------------------------------------------------- */ /* Is this supposed to be a temporary file? If so, stream to */ /* stdout and delete the file. */ /* -------------------------------------------------------------------- */ if( bFileIsTemporary ) { FILE *fp; unsigned char block[4000]; int bytes_read; if( msIO_needBinaryStdout() == MS_FAILURE ) return MS_FAILURE; /* We aren't sure how far back GDAL exports the VSI*L API, so we only use it if we suspect we need it. But we do need it if holding temporary file in memory. */ fp = VSIFOpenL( filename, "rb" ); if( fp == NULL ) { msSetError( MS_MISCERR, "Failed to open %s for streaming to stdout.", "msSaveImageGDAL()", filename ); return MS_FAILURE; } while( (bytes_read = VSIFReadL(block, 1, sizeof(block), fp)) > 0 ) msIO_fwrite( block, 1, bytes_read, stdout ); VSIFCloseL( fp ); VSIUnlink( filename ); CleanVSIDir( "/vsimem/msout" ); free( filename ); } return MS_SUCCESS; }
// Generates the count image from the count string, returns true if all ok bool CreateImage(const char *pcCount, const char *pcFont, int iDigits) { // Set the spare value int iCountLen = strlen(pcCount); if (iDigits < iCountLen) iDigits = iCountLen; int iSpare = 0; if (iDigits > iCountLen) iSpare = iDigits - iCountLen; // Loop vars char pcDigitName[STR_SIZE] = ""; gdImagePtr pImg = NULL; FILE *pPic = NULL; // Load the zero digit image sprintf(pcDigitName, COUNTER_ZERO, pcFont); pPic = fopen(pcDigitName, "rb+"); if (pPic == NULL) return false; pImg = gdImageCreateFromGif(pPic); fclose(pPic); if (pImg == NULL) return false; // Create the output image gdImagePtr pOutImg = NULL; pOutImg = gdImageCreate(iDigits * pImg->sx, pImg->sy); if (pOutImg == NULL) { gdImageDestroy(pImg); return false; } // Copy the palette info from one to the other... int iColTotal = gdImageColorsTotal(pImg); for (int i = 0; i < iColTotal; i++) { gdImageColorAllocate(pOutImg, gdImageRed(pImg, i), gdImageGreen(pImg, i), gdImageBlue(pImg, i)); } int iTransCol = gdImageGetTransparent(pImg); if (iTransCol >= 0) { gdImageColorTransparent(pOutImg, iTransCol); gdImageFill(pOutImg, 0, 0, iTransCol); } // Loop through each leading zero int iPos = 0; while (iSpare-- > 0) { // paste in the image gdImageCopy(pOutImg, pImg, iPos, 0, 0, 0, pImg->sx, pImg->sy); iPos += pImg->sx; } // Delete the zero image gdImageDestroy(pImg); // Loop through each counter character const char *pcPos = pcCount; while (*pcPos != '\0') { sprintf(pcDigitName, COUNTER_PIC, pcFont, *pcPos); // Load the image pPic = fopen(pcDigitName, "rb+"); if (pPic == NULL) { gdImageDestroy(pOutImg); return false; } pImg = gdImageCreateFromGif(pPic); if (pImg == NULL) { gdImageDestroy(pOutImg); return false; } // Paste in the image gdImageCopy(pOutImg, pImg, iPos, 0, 0, 0, pImg->sx, pImg->sy); iPos += pImg->sx; // Delete the image gdImageDestroy(pImg); // Update the position counter pcPos++; } // Write out the output image if (g_oCGI.Debug()) { char pcGIFName[STR_SIZE] = COUNTER_ROOT; strcat(pcGIFName, "out.gif"); FILE *pGIFFile = NULL; pGIFFile = fopen(pcGIFName, "wb"); if (pGIFFile) { gdImageGif(pOutImg, pGIFFile); fclose(pGIFFile); } } else { gdImageInterlace(pOutImg, 1); #ifdef WIN32 _setmode(_fileno(stdout), _O_BINARY); #endif printf("Content-type: image/gif\n\n"); gdImageGif(pOutImg, stdout); } // Destroy the image gdImageDestroy(pOutImg); return true; } // CreateImage
int main(int argc, char **argv) { FILE *in; FILE *out; /* Declare our image pointer */ gdImagePtr im = 0; int i; /* We'll clear 'no' once we know the user has made a reasonable request. */ int no = 1; /* We'll set 'write' once we know the user's request requires that the image be written back to disk. */ int write = 0; /* C programs always get at least one argument; we want at least one more (the image), more in practice. */ if (argc < 2) { no = 1; goto usage; } /* The last argument should be the image. Open the file. */ in = fopen(argv[argc-1], "rb"); if (!in) { fprintf(stderr, "Error: can't open file %s.\n", argv[argc-1]); } /* Now load the image. */ im = gdImageCreateFromGif(in); fclose(in); /* If the load failed, it must not be a GIF file. */ if (!im) { fprintf(stderr, "Error: %s is not a valid gif file.\n", argv[1]); exit(1); } /* Consider each argument in turn. */ for (i=1; (i < (argc-1)); i++) { /* -i turns on and off interlacing. */ if (!strcmp(argv[i], "-i")) { if (i == (argc-2)) { fprintf(stderr, "Error: -i specified without y or n.\n"); no = 1; goto usage; } if (!strcmp(argv[i+1], "y")) { /* Set interlace. */ gdImageInterlace(im, 1); } else if (!strcmp(argv[i+1], "n")) { /* Clear interlace. */ gdImageInterlace(im, 0); } else { fprintf(stderr, "Error: -i specified without y or n.\n"); no = 1; goto usage; } i++; no = 0; write = 1; } else if (!strcmp(argv[i], "-t")) { /* Set transparent index (or none). */ int index; if (i == (argc-2)) { fprintf(stderr, "Error: -t specified without a color table index.\n"); no = 1; goto usage; } if (!strcmp(argv[i+1], "none")) { /* -1 means not transparent. */ gdImageColorTransparent(im, -1); } else { /* OK, get an integer and set the index. */ index = atoi(argv[i+1]); gdImageColorTransparent(im, index); } i++; write = 1; no = 0; } else if (!strcmp(argv[i], "-l")) { /* List the colors in the color table. */ int j; /* Tabs used below. */ printf("Index Red Green Blue\n"); for (j=0; (j < gdImageColorsTotal(im)); j++) { /* Use access macros to learn colors. */ printf("%d %d %d %d\n", j, gdImageRed(im, j), gdImageGreen(im, j), gdImageBlue(im, j)); } no = 0; } else if (!strcmp(argv[i], "-d")) { /* Output dimensions, etc. */ int t; printf("Width: %d Height: %d Colors: %d\n", gdImageSX(im), gdImageSY(im), gdImageColorsTotal(im)); t = gdImageGetTransparent(im); if (t != (-1)) { printf("Transparent index: %d\n", t); } else { /* -1 means the image is not transparent. */ printf("Transparent index: none\n"); } if (gdImageGetInterlaced(im)) { printf("Interlaced: yes\n"); } else { printf("Interlaced: no\n"); } no = 0; } else { fprintf(stderr, "Unknown argument: %s\n", argv[i]); break; } } usage: if (no) { /* If the command failed, output an explanation. */ fprintf(stderr, "Usage: webgif [-i y|n ] [-l] [-t index|off ] [-d] gifname.gif\n"); fprintf(stderr, "Where -i controls interlace (specify y or n for yes or no),\n"); fprintf(stderr, "-l outputs a table of color indexes, -t sets the specified\n"); fprintf(stderr, "color index (0-255 or none) to be the transparent color, and\n"); fprintf(stderr, "-d reports the dimensions and other characteristics of the image.\n"); fprintf(stderr, "Note: you may wish to pipe to \"more\" when using the -l option.\n"); } if (write) { /* Open a temporary file. */ out = fopen("temp.tmp", "wb"); if (!out) { fprintf(stderr, "Unable to write to temp.tmp -- exiting\n"); exit(1); } /* Write the new gif. */ gdImageGif(im, out); fclose(out); /* Erase the old gif. */ unlink(argv[argc-1]); /* Rename the new to the old. */ rename("temp.tmp", argv[argc-1]); } /* Delete the image from memory. */ if (im) { gdImageDestroy(im); } /* All's well that ends well. */ return 0; }
static VALUE fir_resize_image(VALUE self, VALUE raw_filename_in, VALUE raw_filename_out, VALUE raw_width, VALUE raw_height, VALUE raw_image_type, VALUE raw_jpeg_quality) { gdImagePtr im_in, im_out; FILE *in, *out; char *filename_in; char *filename_out; int w; int h; int image_type; int jpeg_quality; int trans = 0, x = 0, y = 0, f = 0; filename_in = RSTRING_PTR(raw_filename_in); filename_out = RSTRING_PTR(raw_filename_out); w = NUM2INT(raw_width); h = NUM2INT(raw_height); image_type = NUM2INT(raw_image_type); jpeg_quality = NUM2INT(raw_jpeg_quality); in = fopen(filename_in, "rb"); if (!in) return Qnil; switch(image_type) { case 0: im_in = gdImageCreateFromJpeg(in); break; case 1: im_in = gdImageCreateFromPng(in); break; case 2: im_in = gdImageCreateFromGif(in); trans = gdImageGetTransparent(im_in); /* find a transparent pixel, then turn off transparency so that it copies correctly */ if (trans >= 0) { for (x=0; x<gdImageSX(im_in); x++) { for (y=0; y<gdImageSY(im_in); y++) { if (gdImageGetPixel(im_in, x, y) == trans) { f = 1; break; } } if (f) break; } gdImageColorTransparent(im_in, -1); if (!f) trans = -1; /* no transparent pixel found */ } break; default: return Qnil; } if (w == 0 || h == 0) { int originalWidth = gdImageSX(im_in); int originalHeight = gdImageSY(im_in); if (w == 0) { w = (int)(h * originalWidth / originalHeight); } else { h = (int)(w * originalHeight / originalWidth); } } im_out = gdImageCreateTrueColor(w, h); /* must be truecolor */ if (image_type == 1) { gdImageAlphaBlending(im_out, 0); /* handle transparency correctly */ gdImageSaveAlpha(im_out, 1); } fclose(in); /* Now copy the original */ gdImageCopyResampled(im_out, im_in, 0, 0, 0, 0, gdImageSX(im_out), gdImageSY(im_out), gdImageSX(im_in), gdImageSY(im_in)); out = fopen(filename_out, "wb"); if (out) { switch(image_type) { case 0: gdImageJpeg(im_out, out, jpeg_quality); break; case 1: gdImagePng(im_out, out); break; case 2: gdImageTrueColorToPalette(im_out, 0, 256); if (trans >= 0) { trans = gdImageGetPixel(im_out, x, y); /* get the color index of our transparent pixel */ gdImageColorTransparent(im_out, trans); /* may not always work as hoped */ } gdImageGif(im_out, out); break; } fclose(out); } gdImageDestroy(im_in); gdImageDestroy(im_out); return Qnil; }
BGD_DECLARE(gdImagePtr) gdImageCreateFromXpm(char *filename) { XpmInfo info; XpmImage image; unsigned int i, j, k, number, len; char buf[5]; gdImagePtr im = 0; int *pointer; int red = 0, green = 0, blue = 0; int *colors; int ret; ret = XpmReadFileToXpmImage(filename, &image, &info); if(ret != XpmSuccess) { return 0; } number = image.ncolors; if(overflow2(sizeof(int), number)) { goto done; } colors = (int *)gdMalloc(sizeof(int) * number); if(colors == NULL) { goto done; } if(!(im = gdImageCreate(image.width, image.height))) { gdFree(colors); goto done; } for(i = 0; i < number; i++) { char *c_color = image.colorTable[i].c_color; if(strcmp(c_color, "None") == 0) { colors[i] = gdImageGetTransparent(im); if(colors[i] == -1) colors[i] = gdImageColorAllocate(im, 0, 0, 0); if(colors[i] != -1) gdImageColorTransparent(im, colors[i]); continue; } len = strlen(c_color); if(len < 1) continue; if(c_color[0] == '#') { switch(len) { case 4: buf[2] = '\0'; buf[0] = buf[1] = c_color[1]; red = strtol(buf, NULL, 16); buf[0] = buf[1] = c_color[2]; green = strtol(buf, NULL, 16); buf[0] = buf[1] = c_color[3]; blue = strtol(buf, NULL, 16); break; case 7: buf[2] = '\0'; buf[0] = c_color[1]; buf[1] = c_color[2]; red = strtol(buf, NULL, 16); buf[0] = c_color[3]; buf[1] = c_color[4]; green = strtol(buf, NULL, 16); buf[0] = c_color[5]; buf[1] = c_color[6]; blue = strtol(buf, NULL, 16); break; case 10: buf[3] = '\0'; buf[0] = c_color[1]; buf[1] = c_color[2]; buf[2] = c_color[3]; red = strtol(buf, NULL, 16); red /= 64; buf[0] = c_color[4]; buf[1] = c_color[5]; buf[2] = c_color[6]; green = strtol(buf, NULL, 16); green /= 64; buf[0] = c_color[7]; buf[1] = c_color[8]; buf[2] = c_color[9]; blue = strtol(buf, NULL, 16); blue /= 64; break; case 13: buf[4] = '\0'; buf[0] = c_color[1]; buf[1] = c_color[2]; buf[2] = c_color[3]; buf[3] = c_color[4]; red = strtol(buf, NULL, 16); red /= 256; buf[0] = c_color[5]; buf[1] = c_color[6]; buf[2] = c_color[7]; buf[3] = c_color[8]; green = strtol(buf, NULL, 16); green /= 256; buf[0] = c_color[9]; buf[1] = c_color[10]; buf[2] = c_color[11]; buf[3] = c_color[12]; blue = strtol(buf, NULL, 16); blue /= 256; break; } } else if(!gdColorMapLookup(GD_COLOR_MAP_X11, c_color, &red, &green, &blue)) { continue; } colors[i] = gdImageColorResolve(im, red, green, blue); } pointer = (int *)image.data; for(i = 0; i < image.height; i++) { for(j = 0; j < image.width; j++) { k = *pointer++; gdImageSetPixel(im, j, i, colors[k]); } } gdFree(colors); done: XpmFreeXpmImage(&image); XpmFreeXpmInfo(&info); return im; }