Beispiel #1
0
int main()
{
	gdImagePtr im;
	int error = 0;
	int c, c1, c2, c3, c4, color, i;

	im = gdImageCreateTrueColor(5, 5);
	c = gdImageColorExact(im, 255, 0, 255);
	c2 = gdImageColorExactAlpha(im, 255, 0, 255, 100);
	gdImageDestroy(im);

	if (gdTestAssert(c == 0xFF00FF) != 1) {
		error = -1;
	}
	if (gdTestAssert(c2 == 0x64FF00FF) != 1) {
		error = -1;
	}

	im = gdImageCreate(5, 5);
	c1 = gdImageColorAllocate(im, 255, 0, 255);
	c2 = gdImageColorAllocate(im, 255, 200, 0);
	c3 = gdImageColorAllocateAlpha(im, 255, 0, 255, 100);

	c1 = gdImageColorExact(im, 255, 0, 255);
	c2 = gdImageColorExact(im, 255, 200, 0);
	c3 = gdImageColorExactAlpha(im, 255, 0, 255, 100);
	c4 = gdImageColorExactAlpha(im, 255, 34, 255, 100);

	if (gdTestAssert(c1 == 0) != 1) {
		error = -1;
	}
	if (gdTestAssert(c2 == 1) != 1) {
		error = -1;
	}
	if (gdTestAssert(c3 == 2) != 1) {
		error = -1;
	}
	if (gdTestAssert(c4 == -1) != 1) {
		error = -1;
	}

	color = gdTrueColorAlpha(gdImageRed(im, c1), gdImageGreen(im, c1),
					gdImageBlue(im, c1), 0);
	if (gdTestAssert(color == 0xFF00FF) != 1) {
		error = -1;
	}
	color = gdTrueColorAlpha(gdImageRed(im, c2), gdImageGreen(im, c2),
					gdImageBlue(im, c2), 0);
	if (gdTestAssert(color == 0xFFC800) != 1) {
		error = -1;
	}
	color = gdTrueColorAlpha(gdImageRed(im, c3), gdImageGreen(im, c3),
					gdImageBlue(im, c3), 0);
	if (gdTestAssert(color == 0xFF00FF) != 1) {
		error = -1;
	}
	gdImageDestroy(im);

	return error;
}
Beispiel #2
0
/* build a color or find the nearest color in the color table           */ 
int find_color ( gdImagePtr graph, int color ) {
	int i_col;

	if ( (i_col = gdImageColorExact(graph,r(color), g(color), b(color))) == -1 ) {
		if ( (i_col = gdImageColorAllocate(graph,r(color), g(color), b(color))) == -1 ) {
			i_col = gdImageColorClosest(graph,r(color), g(color), b(color));
		}
	}
	return (i_col);
}
JBoolean
PadColormap
	(
	gdImagePtr image
	)
{
	JSize colorCount = gdImageColorsTotal(image);
	if (colorCount >= kMinColorCount)
		{
		return kJFalse;
		}

	const JSize extraColorCount = kMinColorCount - colorCount;

	int x = gdImageSX(image) - extraColorCount;
	if (x < 0)
		{
		cerr << "image is too small to fit extra colors on single raster line" << endl;
		exit(1);
		}

	int y = gdImageSY(image) - 1;

	int c = gdImageGetPixel(image, x,y);
	int r = gdImageRed  (image, c);
	int g = gdImageGreen(image, c);
	int b = gdImageBlue (image, c);

	int delta = -1;
	if (r < 127 || g < 127 || b < 127)
		{
		delta = +1;
		}

	for (JIndex i=1; i<=extraColorCount; i++)
		{
		assert( x < gdImageSX(image) );

		while ((c = gdImageColorExact(image, r,g,b)) != -1)
			{
			r = JMax(0, JMin(r + delta, 255));
			g = JMax(0, JMin(g + delta, 255));
			b = JMax(0, JMin(b + delta, 255));
			}

		c = gdImageColorAllocate(image, r,g,b);
		assert( c != -1 );
		gdImageSetPixel(image, x,y, c);

		x++;
		}

	return kJTrue;
}
Beispiel #4
0
int allocOrExact(gdImagePtr im, int r, int g, int b)
{
  int c;

  c = gdImageColorExact(im, r,g,b);
  if(c >= 0) return c;

  c = gdImageColorAllocate(im, r, g, b);
  if(c >= 0) return c;

  return gdImageColorClosest(im, r, g, b);
}
Beispiel #5
0
result_t Image::colorExact(int32_t red, int32_t green, int32_t blue,
                           int32_t &retVal)
{
    if (!m_image)
        return CHECK_ERROR(CALL_E_INVALID_CALL);

    if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0
            || blue > 255)
        return CHECK_ERROR(CALL_E_INVALIDARG);

    retVal = gdImageColorExact(m_image, red, green, blue);
    return 0;
}
Beispiel #6
0
void wscolr ( int *Red, int *Green, int *Blue, int *iret )
/************************************************************************
 * wscolr								*
 *									*
 * This function sets the current color index for the gif image. There	*
 * will always be at least one color already in use, since black is	*
 * allocated when the image is opened. GEMPAK has only 32 colors	*
 * defined, and the GIF has 256, so there's no reason to worry about 	*
 * the color table being filled.					*
 *									*
 * wscolr ( Red, Green, Blue, iret )					*
 *									*
 * Input parameters:							*
 *  *Red		int	red index				*
 *  *Green		int	green index				*
 *  *Blue		int	blue index				*
 *									*
 * Output parameter:							*
 *  *iret		int	return value				*
 *									*
 **									*
 * Log:									*
 * D. Austin		 5/96						*
 * T. Lee/GSC	 	 7/00	Clean up; Renamed from gdr_CurrentColor	*
 ***********************************************************************/
{
	int status;

/*---------------------------------------------------------------------*/
	*iret = G_NORMAL;

	/*
	 * Check if the requested color is already in use.
	 */

	if  ( (status = gdImageColorExact (Current_Im,*Red,*Green,*Blue) )
	    == -1) {
	    CurrentColorIndex = gdImageColorAllocate 
				( Current_Im, *Red, *Green, *Blue );
	}
	else {
	    CurrentColorIndex = status; 
	}
}
void
Blend
	(
	gdImagePtr			image,
	const JFloat		alpha,
	const JRGB&			alphaColor,
	const JCharacter*	outputFileName
	)
{
	const JSize w = gdImageSX(image);
	const JSize h = gdImageSY(image);

	gdImagePtr i2 = gdImageCreate(w,h);

	for (JIndex x=0; x<w; x++)
		{
		for (JIndex y=0; y<h; y++)
			{
			const int c = gdImageGetPixel(image, x,y);
			const int r = BlendComponent(gdImageRed(image, c),   alphaColor.red,   alpha);
			const int g = BlendComponent(gdImageGreen(image, c), alphaColor.green, alpha);
			const int b = BlendComponent(gdImageBlue(image, c),  alphaColor.blue,  alpha);

			int c2 = gdImageColorExact(i2, r,g,b);
			if (c2 == -1)
				{
				c2 = gdImageColorAllocate(i2, r,g,b);
				if (c2 == -1)
					{
					c2 = gdImageColorClosest(i2, r,g,b);
					}
				}

			gdImageSetPixel(i2, x,y, c2);
			}
		}

	WriteGIF(i2, outputFileName);
	gdImageDestroy(i2);
}
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;
}
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;
}
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;
}
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;
}
Beispiel #12
0
int main(int argc, char **argv, char **env) {
/*=========== GENERIC VARIABLES ===========*/
	FILE *f_output = NULL, *f_input = NULL;
	int c, i;
	char *end;
	
/*=========== GETOPT VARIABLES ===========*/
	char const *const optstr = "hi:o:f:c:w:b:n:t:";
#ifdef _GNU_SOURCE
	static struct option long_opts[] = {
		{"help", 0, NULL, 'h'},
		{"infile", 1, NULL, 'i'},
		{"outfile", 1, NULL, 'o'},
		{"format", 1, NULL, 'f'},
		{"colors", 1, NULL, 'c'},
		{"width", 1, NULL, 'w'},
		{"bgcolor", 1, NULL, 'b'},
		{"newcolor", 1, NULL, 'n'},
		{"color-tolerance", 1, NULL, 't'},
		{NULL, 0, NULL, 0},
	};
#endif

/*=========== IMAGE-RELATED VARIABLES ===========*/
	int x, y;
	int color_idx = 0;
	int img_orig_h = 0, img_orig_w = 0;
	int img_targ_h = 0, img_targ_w = 0;
	int top = -1, bottom = -1, top_prev = -1, bottom_prev = -1;
	int color = -1, color_prev = -1;
	gdImagePtr image_data = NULL;
	gdImagePtr image_resized = NULL;
	gdImageCreateFunction image_openers[] = {
		NULL,
		(gdImageCreateFunction) gdImageCreateFromJpeg,
		(gdImageCreateFunction) gdImageCreateFromPng,
		(gdImageCreateFunction) gdImageCreateFromGif,
		(gdImageCreateFunction) gdImageCreateFromWBMP,
		(gdImageCreateFunction) gdImageCreateFromXpm	/* Accepts char * as first argument! */
	};

	
	while (true) {
#ifdef _GNU_SOURCE
		c = getopt_long(argc, argv, optstr, long_opts, NULL);
#else /* not _GNU_SOURCE */ 
		c = getopt(argc, argv, optstr);
#endif /* _GNU_SOURCE */
		if (c == -1) break;

		switch (c) {
			case 'h':
				help(stdout, EXEC_NAME);
				exit(ALL_OK);
				break;
			case 'i':
				i = strlen(optarg);
				if (i2u_conf.m_infile != NULL) free(i2u_conf.m_infile);
				if ((i2u_conf.m_infile = (char *) calloc(i+1, sizeof(char))) == NULL) {
					fprintf(stderr, "calloc() failed!\n");
					cleanup_main();
					exit(ERR_OUT_OF_MEMORY);
				}
				strncpy(i2u_conf.m_infile, optarg, i);
				break;
			case 'o':
				if (strncmp("-", optarg, 2) == 0) {
					if (i2u_conf.m_outfile != NULL) free(i2u_conf.m_outfile);
					i2u_conf.m_outfile = NULL;
					break;
				}
				else {
					i = strlen(optarg);
					if (i2u_conf.m_outfile != NULL) free(i2u_conf.m_outfile);
					if ((i2u_conf.m_outfile = (char *) calloc(i+1, sizeof(char))) == NULL) {
						fprintf(stderr, "calloc() failed!\n");
						cleanup_main();
						exit(ERR_OUT_OF_MEMORY);
					}
					strncpy(i2u_conf.m_outfile, optarg, i);
					break;
				}
			case 'f':
				i = (int) strtol(optarg, &end, 10);
				if (optarg != end) {
					i2u_conf.m_outformat = (i > 8) ? unicode : ansi;
				}
				else {	
					if (strncasecmp(optarg, "ansi", 5) == 0) i2u_conf.m_outformat = ansi;
					else {
						if (strncmp(optarg, "unicode", 8) == 0) i2u_conf.m_outformat = unicode;
						else fprintf(stderr, "Warning: invalid format specified. Defaulting to Unicode.\n"); 
					}
				}
				break;
			case 'c':
				i = (int) strtol(optarg, &end, 10);
				if (optarg != end) { 
					if (i < 9) i2u_conf.m_colors = low;
					else {
						if (i < 17) i2u_conf.m_colors = basic;
						else i2u_conf.m_colors = extended;
					}
				}
				else fprintf(stderr, "Warning: invalid color depth specified. Defaulting to 256.\n");
				break;
			case 'w':
				i = (int) strtol(optarg, &end, 10);
				if (optarg != end) i2u_conf.m_targ_width = i;
				else fprintf(stderr, "Warning: invalid width specified. Defaulting to 80.\n");
				break;
			case 't':
				i = (int) strtol(optarg, &end, 10);
				if (optarg != end) i2u_conf.m_toleranceradius = (i > 0) ? i : 0;
				else fprintf(stderr, "Warning: invalid color-tolerance radius specified. Defaulting to zero.\n");
				break;
			case 'b':
				i = strtol(optarg, &end, 16);
				if (optarg != end) i2u_conf.m_bgcolor = i;
				else fprintf(stderr, "Warning: invalid background color specified. No background-substitution will occur.\n");
				break;
			case 'n':
				i = strtol(optarg, &end, 16);
				if (optarg != end) i2u_conf.m_newcolor = i;
				else fprintf(stderr, "Warning: invalid substitution color specified. No background-substitution will occur.\n");
				break;
			case '?':
			default:
				help(stderr, EXEC_NAME);
				exit(ERR_INVALID_ARG);
		}
		if (c == 'x') break;
	}

		
		
	if (i2u_conf.m_infile == NULL) {
		fprintf(stderr, "Error: input file not set. Use option" 
#ifdef _GNU_SOURCE
			"s -i or --infile"
#else /* not _GNU_SOURCE */ 
			" -i"
#endif /* _GNU_SOURCE */
			" to specify one.\n");
		cleanup_main();
		exit(ERR_INVALID_ARG);
	}

/*=========== GD PART ==========*/
	
	i2u_conf.m_ftype = get_image_type(i2u_conf.m_infile);
	
	if (i2u_conf.m_ftype == UNKNOWN) {
		fprintf(stderr, "Error: unsupported input file type!\n" );
		cleanup_main();
		exit(ERR_UNSUPPORTED_FORMAT);
	}
	
	if (i2u_conf.m_ftype != xpm) {
			if ((f_input = fopen(i2u_conf.m_infile, "r")) == NULL) {
				perror("fopen(): ");
				cleanup_main();
				exit(ERR_FOPEN_FAIL);
			}
		
			image_data = image_openers[i2u_conf.m_ftype](f_input);
			
			fclose(f_input);
	}
	else {
			if ((image_data = image_openers[i2u_conf.m_ftype](i2u_conf.m_infile)) == NULL) {
				fprintf(stderr, "gdImageCreateFromXpm(): Error occured while opening file \'%s\'\n", i2u_conf.m_infile);
				cleanup_main();
				exit(ERR_GD_XPMOPEN_FAIL);
			}
	}
	
	img_orig_w = image_data->sx;
	img_orig_h = image_data->sy;
	img_targ_w = i2u_conf.m_targ_width;
	img_targ_h = (int) round(((double) img_targ_w)/((double) img_orig_w)*((double) img_orig_h));
	/* if (i2u_conf.m_outformat == ansi) img_targ_w /= 2; */
	
	/* change background, if requested */
	if ((i2u_conf.m_bgcolor > -1) && (i2u_conf.m_newcolor > -1)) {
			int bg_r, bg_g, bg_b;
			int nc_r, nc_g, nc_b;
			int bgcolor, newcolor;
			int radius = i2u_conf.m_toleranceradius;
			bg_r = (i2u_conf.m_bgcolor & 0x00ff0000) >> 16;
			bg_g = (i2u_conf.m_bgcolor & 0x0000ff00) >> 8;
			bg_b = (i2u_conf.m_bgcolor & 0x000000ff);
			nc_r = (i2u_conf.m_newcolor & 0x00ff0000) >> 16;
			nc_g = (i2u_conf.m_newcolor & 0x0000ff00) >> 8;
			nc_b = (i2u_conf.m_newcolor & 0x000000ff);
			
			if ((bgcolor = gdImageColorExact(image_data, bg_r, bg_g, bg_b)) != -1) {
				color_idx = gdImageGetPixel(image_data, 0, 0);
				newcolor = gdImageColorResolve(image_data, nc_r, nc_g, nc_b);
				for (y=0; y<img_orig_h; y++) {
					for (x=0; x<img_orig_w; x++) {
					  color_idx = gdImageGetPixel(image_data, x, y);
				    if (get_color_distance(gdImageRed(image_data, color_idx), gdImageRed(image_data, bgcolor), gdImageGreen(image_data, color_idx), gdImageGreen(image_data, bgcolor), gdImageBlue(image_data, color_idx), gdImageBlue(image_data, bgcolor)) <= radius) gdImageSetPixel(image_data, x, y, newcolor);
					}
				}
			}	
	}