int mergeRasterBufferGD(imageObj *dest, rasterBufferObj *overlay, double opacity, int srcX, int srcY, int dstX, int dstY, int width, int height) { assert(dest && overlay); assert(overlay->type == MS_BUFFER_GD); gdImageCopyMerge(MS_IMAGE_GET_GDIMAGEPTR(dest),overlay->data.gd_img,dstX,dstY,srcX,srcY,width,height,opacity*100); return MS_SUCCESS; }
result_t Image::copyMerge(Image_base *source, int32_t dstX, int32_t dstY, int32_t srcX, int32_t srcY, int32_t width, int32_t height, int32_t percent, AsyncEvent *ac) { if (width <= 0 || height <= 0) return CHECK_ERROR(CALL_E_INVALIDARG); if (!m_image) return CHECK_ERROR(CALL_E_INVALID_CALL); if (!ac) return CHECK_ERROR(CALL_E_NOSYNC); Image *src = (Image *) source; if (!src->m_image) return CHECK_ERROR(CALL_E_INVALID_CALL); gdImageCopyMerge(m_image, src->m_image, dstX, dstY, srcX, srcY, width, height, percent); return 0; }
int main (int argc, char **argv) { #ifdef HAVE_LIBPNG gdImagePtr im, ref, im2, im3; FILE *in, *out; void *iptr; int sz; char of[256]; int colRed, colBlu; gdSource imgsrc; gdSink imgsnk; int foreground; int i; if (argc != 2) { fprintf (stderr, "Usage: gdtest filename.png\n"); exit (1); } in = fopen (argv[1], "rb"); if (!in) { fprintf (stderr, "Input file does not exist!\n"); exit (1); } im = gdImageCreateFromPng (in); rewind (in); ref = gdImageCreateFromPng (in); fclose (in); printf ("Reference File has %d Palette entries\n", ref->colorsTotal); CompareImages ("Initial Versions", ref, im); /* */ /* Send to PNG File then Ptr */ /* */ #ifdef VMS sprintf (of, "%s-png", argv[1]); #else sprintf (of, "%s.png", argv[1]); #endif out = fopen (of, "wb"); gdImagePng (im, out); fclose (out); in = fopen (of, "rb"); if (!in) { fprintf (stderr, "PNG Output file does not exist!\n"); exit (1); } im2 = gdImageCreateFromPng (in); fclose (in); CompareImages ("GD->PNG File->GD", ref, im2); unlink (of); gdImageDestroy (im2); /* 2.0.21: use the new From*Ptr functions */ iptr = gdImagePngPtr (im, &sz); im2 = gdImageCreateFromPngPtr (sz, iptr); gdFree (iptr); CompareImages ("GD->PNG ptr->GD", ref, im2); gdImageDestroy (im2); /* */ /* Send to GD2 File then Ptr */ /* */ #ifdef VMS sprintf (of, "%s-gd2", argv[1]); #else sprintf (of, "%s.gd2", argv[1]); #endif out = fopen (of, "wb"); gdImageGd2 (im, out, 128, 2); fclose (out); in = fopen (of, "rb"); if (!in) { fprintf (stderr, "GD2 Output file does not exist!\n"); exit (1); } im2 = gdImageCreateFromGd2 (in); fclose (in); CompareImages ("GD->GD2 File->GD", ref, im2); unlink (of); gdImageDestroy (im2); iptr = gdImageGd2Ptr (im, 128, 2, &sz); /*printf("Got ptr %d (size %d)\n",iptr, sz); */ im2 = gdImageCreateFromGd2Ptr (sz, iptr); gdFree (iptr); /*printf("Got img2 %d\n",im2); */ CompareImages ("GD->GD2 ptr->GD", ref, im2); gdImageDestroy (im2); /* */ /* Send to GD File then Ptr */ /* */ #ifdef VMS sprintf (of, "%s-gd", argv[1]); #else sprintf (of, "%s.gd", argv[1]); #endif out = fopen (of, "wb"); gdImageGd (im, out); fclose (out); in = fopen (of, "rb"); if (!in) { fprintf (stderr, "GD Output file does not exist!\n"); exit (1); } im2 = gdImageCreateFromGd (in); fclose (in); CompareImages ("GD->GD File->GD", ref, im2); unlink (of); gdImageDestroy (im2); iptr = gdImageGdPtr (im, &sz); /*printf("Got ptr %d (size %d)\n",iptr, sz); */ im2 = gdImageCreateFromGdPtr (sz, iptr); gdFree (iptr); /*printf("Got img2 %d\n",im2); */ CompareImages ("GD->GD ptr->GD", ref, im2); gdImageDestroy (im2); /* * Test gdImageCreateFromPngSource' */ in = fopen (argv[1], "rb"); imgsrc.source = freadWrapper; imgsrc.context = in; im2 = gdImageCreateFromPngSource (&imgsrc); fclose (in); if (im2 == NULL) { printf ("GD Source: ERROR Null returned by gdImageCreateFromPngSource\n"); } else { CompareImages ("GD Source", ref, im2); gdImageDestroy (im2); }; /* * Test gdImagePngToSink' */ #ifdef VMS sprintf (of, "%s-snk", argv[1]); #else sprintf (of, "%s.snk", argv[1]); #endif out = fopen (of, "wb"); imgsnk.sink = fwriteWrapper; imgsnk.context = out; gdImagePngToSink (im, &imgsnk); fclose (out); in = fopen (of, "rb"); if (!in) { fprintf (stderr, "GD Sink: ERROR - GD Sink Output file does not exist!\n"); } else { im2 = gdImageCreateFromPng (in); fclose (in); CompareImages ("GD Sink", ref, im2); gdImageDestroy (im2); }; unlink (of); /* */ /* Test Extraction */ /* */ in = fopen ("test/gdtest_200_300_150_100.png", "rb"); if (!in) { fprintf (stderr, "gdtest_200_300_150_100.png does not exist!\n"); exit (1); } im2 = gdImageCreateFromPng (in); fclose (in); in = fopen ("test/gdtest.gd2", "rb"); if (!in) { fprintf (stderr, "gdtest.gd2 does not exist!\n"); exit (1); } im3 = gdImageCreateFromGd2Part (in, 200, 300, 150, 100); fclose (in); CompareImages ("GD2Part (gdtest_200_300_150_100.png, gdtest.gd2(part))", im2, im3); gdImageDestroy (im2); gdImageDestroy (im3); /* */ /* Copy Blend */ /* */ in = fopen ("test/gdtest.png", "rb"); if (!in) { fprintf (stderr, "gdtest.png does not exist!\n"); exit (1); } im2 = gdImageCreateFromPng (in); fclose (in); im3 = gdImageCreate (100, 60); colRed = gdImageColorAllocate (im3, 255, 0, 0); colBlu = gdImageColorAllocate (im3, 0, 0, 255); gdImageFilledRectangle (im3, 0, 0, 49, 30, colRed); gdImageFilledRectangle (im3, 50, 30, 99, 59, colBlu); gdImageCopyMerge (im2, im3, 150, 200, 10, 10, 90, 50, 50); gdImageCopyMerge (im2, im3, 180, 70, 10, 10, 90, 50, 50); gdImageCopyMergeGray (im2, im3, 250, 160, 10, 10, 90, 50, 50); gdImageCopyMergeGray (im2, im3, 80, 70, 10, 10, 90, 50, 50); gdImageDestroy (im3); in = fopen ("test/gdtest_merge.png", "rb"); if (!in) { fprintf (stderr, "gdtest_merge.png does not exist!\n"); exit (1); } im3 = gdImageCreateFromPng (in); fclose (in); printf ("[Merged Image has %d colours]\n", im2->colorsTotal); CompareImages ("Merged (gdtest.png, gdtest_merge.png)", im2, im3); gdImageDestroy (im2); gdImageDestroy (im3); #ifdef HAVE_LIBJPEG out = fopen ("test/gdtest.jpg", "wb"); if (!out) { fprintf (stderr, "Can't create file test/gdtest.jpg.\n"); exit (1); } gdImageJpeg (im, out, -1); fclose (out); in = fopen ("test/gdtest.jpg", "rb"); if (!in) { fprintf (stderr, "Can't open file test/gdtest.jpg.\n"); exit (1); } im2 = gdImageCreateFromJpeg (in); fclose (in); if (!im2) { fprintf (stderr, "gdImageCreateFromJpeg failed.\n"); exit (1); } gdImageDestroy (im2); printf ("Created test/gdtest.jpg successfully. Compare this image\n" "to the input image manually. Some difference must be\n" "expected as JPEG is a lossy file format.\n"); #endif /* HAVE_LIBJPEG */ /* Assume the color closest to black is the foreground color for the B&W wbmp image. */ fprintf (stderr, "NOTE: the WBMP output image will NOT match the original unless the original\n" "is also black and white. This is OK!\n"); foreground = gdImageColorClosest (im, 0, 0, 0); fprintf (stderr, "Foreground index is %d\n", foreground); if (foreground == -1) { fprintf (stderr, "Source image has no colors, skipping wbmp test.\n"); } else { out = fopen ("test/gdtest.wbmp", "wb"); if (!out) { fprintf (stderr, "Can't create file test/gdtest.wbmp.\n"); exit (1); } gdImageWBMP (im, foreground, out); fclose (out); in = fopen ("test/gdtest.wbmp", "rb"); if (!in) { fprintf (stderr, "Can't open file test/gdtest.wbmp.\n"); exit (1); } im2 = gdImageCreateFromWBMP (in); fprintf (stderr, "WBMP has %d colors\n", gdImageColorsTotal (im2)); fprintf (stderr, "WBMP colors are:\n"); for (i = 0; (i < gdImageColorsTotal (im2)); i++) { fprintf (stderr, "%02X%02X%02X\n", gdImageRed (im2, i), gdImageGreen (im2, i), gdImageBlue (im2, i)); } fclose (in); if (!im2) { fprintf (stderr, "gdImageCreateFromWBMP failed.\n"); exit (1); } CompareImages ("WBMP test (gdtest.png, gdtest.wbmp)", ref, im2); out = fopen ("test/gdtest_wbmp_to_png.png", "wb"); if (!out) { fprintf (stderr, "Can't create file test/gdtest_wbmp_to_png.png.\n"); exit (1); } gdImagePng (im2, out); fclose (out); gdImageDestroy (im2); } gdImageDestroy (im); gdImageDestroy (ref); #else fprintf (stderr, "No PNG library support.\n"); #endif /* HAVE_LIBPNG */ return 0; }
static void water_mark(void *conf) { ngx_image_conf_t *info = conf; int water_w=0;//水印宽度 int water_h=0;//水印高度 int posX = 0;//X位置 int posY = 0;//Y位置 int water_color = 0;//文字水印GD颜色值 char *water_text;//图片文字 char *water_font;//文字字体 char *water_color_text;//图片颜色值 water_text = NULL; water_font = NULL; water_color_text = NULL; if(info->water_status)//如果水印功能打开了 { if(info->water_type == 0)//如果为图片水印 { if(file_exists((char *)info->water_image.data) == 0)//判断水印图片是否存在 { water_image_from(conf);//获取水印图片信息 if(info->water_im == NULL)//判断对象是否为空 { return;//水印文件异常 }else{ water_w = info->water_im->sx; water_h = info->water_im->sy; } } else { return;//水印图片不存在 } } else//文字水印 { water_text = (char *) info->water_text.data; water_color_text = (char *) info->water_color.data; water_font = (char *)info->water_font.data; if(file_exists((char *)water_font) == 0)//如果水印字体存在 { int R,G,B; char R_str[3],G_str[3],B_str[3]; int brect[8]; gdImagePtr font_im; font_im = gdImageCreateTrueColor(info->dst_im->sx,info->dst_im->sy); sprintf(R_str,"%.*s",2,water_color_text+1); sprintf(G_str,"%.*s",2,water_color_text+3); sprintf(B_str,"%.*s",2,water_color_text+5); sscanf(R_str,"%x",&R); sscanf(G_str,"%x",&G); sscanf(B_str,"%x",&B); water_color = gdImageColorAllocate(info->dst_im,R,G,B); gdImageStringFT(font_im, &brect[0], water_color, water_font, info->water_font_size, 0.0, 0, 0,water_text/*, &strex*/); //water_w = abs(brect[2] - brect[6] + 10); water_w = abs(brect[2] - brect[6] + 10); water_h = abs(brect[3] - brect[7]); gdImageDestroy(font_im); } } if( (info->width < info->water_width_min) || info->height < info->water_height_min) { return;//如果图片宽度/高度比配置文件里规定的宽度/高度宽度小 } if ((info->width < water_w) || (info->height < water_h)) { return;//如果图片宽度/高度比水印宽度/高度宽度小 } if(info->water_pos < 1 ||info->water_pos > 9) { srand((unsigned)time(NULL)); //info->water_pos = rand() % 9 + 1; info->water_pos = 1+(int)(9.0*rand()/(RAND_MAX+1.0)); //info->water_pos = rand() % 9; } switch(info->water_pos) { case 1: posX = 10; posY = 15; break; case 2: posX = (info->width - water_w) / 2; posY = 15; break; case 3: posX = info->width - water_w; posY = 15; break; case 4: posX = 0; posY = (info->height - water_h) / 2; break; case 5: posX = (info->width - water_w) / 2; posY = (info->height - water_h) / 2; break; case 6: posX = info->width - water_w; posY = (info->height - water_h) / 2; break; case 7: posX = 0; posY = (info->height - water_h); break; case 8: posX = (info->width - water_w) /2; posY = info->width - water_h; break; case 9: posX = info->width - water_w; posY = info->height - water_h; break; default: posX = info->width - water_w; posY = info->height - water_h; break; } if(info->water_type == 0) { gdImagePtr tmp_im; tmp_im = NULL; tmp_im = gdImageCreateTrueColor(water_w, water_h); gdImageCopy(tmp_im, info->dst_im, 0, 0, posX, posY, water_w, water_h); gdImageCopy(tmp_im, info->water_im, 0, 0, 0, 0, water_w, water_h); gdImageCopyMerge(info->dst_im, tmp_im,posX, posY, 0, 0, water_w,water_h,info->water_transparent); gdImageDestroy(tmp_im); gdImageDestroy(info->water_im); } else { gdImageAlphaBlending(info->dst_im,-1); gdImageSaveAlpha(info->dst_im,0); gdImageStringFT(info->dst_im,0,water_color,water_font,info->water_font_size, 0.0, posX, posY,water_text); } } }
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; }