ngx_http_autohome_dis_opencv_module.c
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <sys/types.h>
#include <image_file_block.h>
/* Module config */
typedef struct {
ngx_str_t ed;
} ngx_http_autohome_dis_opencv_loc_conf_t;
extern void nginx_module_invoke_opencv_resize(empty_struct * p,image_file_t * retval);
empty_struct p;
static char *ngx_http_autohome_dis_opencv(ngx_conf_t *cf, ngx_command_t *cmd,void *conf);
static void *ngx_http_autohome_dis_opencv_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_autohome_dis_opencv_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
/* Directives */
static ngx_command_t ngx_http_autohome_dis_opencv_commands[] = { {
ngx_string("autohome_dis_opencv"), NGX_HTTP_LOC_CONF
| NGX_CONF_NOARGS, ngx_http_autohome_dis_opencv, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_autohome_dis_opencv_loc_conf_t, ed), NULL },
ngx_null_command };
/* Http context of the module */
static ngx_http_module_t ngx_http_autohome_dis_opencv_module_ctx = { NULL, /* preconfiguration */
NULL, /* postconfiguration (在创建和读取该模块的配置信息之后被调用)*/
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_autohome_dis_opencv_create_loc_conf, /* create location configration */
ngx_http_autohome_dis_opencv_merge_loc_conf /* merge location configration */
};
/* Module */
ngx_module_t ngx_http_autohome_dis_opencv_module = { NGX_MODULE_V1,
&ngx_http_autohome_dis_opencv_module_ctx, /* module context */
ngx_http_autohome_dis_opencv_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING };
static char* ngx_str_replace(char *search, char *replace, char *subject) {
char *p = NULL, *old = NULL, *new_subject = NULL;
int c = 0, search_size;
search_size = strlen(search);
//Count how many occurences
for (p = strstr(subject, search); p != NULL ;
p = strstr(p + search_size, search)) {
c++;
}
//Final size
c = (strlen(replace) - search_size) * c + strlen(subject);
//New subject with new size
new_subject = malloc(c);
memset(new_subject,0,sizeof(char)*c);
//Set it to blank
strcpy(new_subject, "");
//The start position
old = subject;
for (p = strstr(subject, search); p != NULL ;
p = strstr(p + search_size, search)) {
//move ahead and copy some text from original subject , from a certain position
strncpy(new_subject + strlen(new_subject), old, p - old);
//move ahead and copy the replacement text
strcpy(new_subject + strlen(new_subject), replace);
//The new start position after this search match
old = p + search_size;
}
//Copy the part after the last search match
strcpy(new_subject + strlen(new_subject), old);
return new_subject;
}
static char *ngx_str_copy(const char *str) {
int len = strlen(str) + 1;
char *buf = malloc(len);
if (NULL == buf)
return NULL ;
memcpy(buf, str, len);
return buf;
}
static int ngx_str_split(const char *str, char *parts[], const char *delimiter) {
char *pch;
int i = 0;
char *tmp = ngx_str_copy(str);
pch = strtok(tmp, delimiter);
parts[i++] = ngx_str_copy(pch);
while (pch) {
pch = strtok(NULL, delimiter);
if (NULL == pch)
break;
parts[i++] = ngx_str_copy(pch);
}
free(tmp);
free(pch);
return i;
}
static image_file_t * ngx_get_image(ngx_http_request_t *r) {
image_file_t *images;
images = malloc(sizeof(image_file_t));
//get uri
ngx_str_t uri = r->unparsed_uri;
u_char* ngx_string_uri;
ngx_string_uri = ngx_pcalloc(r->pool, (uri.len + 1) * sizeof(u_char));
///ngx_memset(ngx_string_uri, 0, sizeof(u_char) * (uri.len + 1));
ngx_sprintf(ngx_string_uri, "%V", &uri);
//split uri /data/logo/80x60_30_1_logo.jpg
char **ngx_array_uri = ngx_pcalloc(r->pool,(uri.len + 1) * sizeof(char));
size_t uri_size = ngx_str_split((const char *) ngx_string_uri, ngx_array_uri,
"/");
//split filename 80x60_30_1_logo.jpg
char **ngx_array_image = ngx_pcalloc(r->pool,(uri.len+1) * sizeof(char));
size_t image_size = ngx_str_split(ngx_array_uri[uri_size - 1], ngx_array_image,
"_");
char* str_image_resize;
char* str_image_quality;
char* str_image_watermark;
char* str_image;
if (image_size >= 2) {
char ** ngx_array_image_size = ngx_pcalloc(r->pool,(uri.len+1) * sizeof(char));
size_t image_size = ngx_str_split(ngx_array_image[0], ngx_array_image_size,
"x");
// width hegith
if (image_size == 2) {
images->width = atoi(ngx_array_image_size[0]);
images->height = atoi(ngx_array_image_size[1]);
}
str_image_resize = ngx_pcalloc(r->pool, sizeof(char) * (strlen(ngx_array_image[0])+2));
strcpy(str_image_resize, ngx_array_image[0]);
strcat(str_image_resize, "_");
}
if (image_size >= 3) {
//quality
images->quality = atof(ngx_array_image[1]);
str_image_quality = ngx_pcalloc(r->pool, sizeof(char) * (strlen(ngx_array_image[1])+2));
strcpy(str_image_quality, ngx_array_image[1]);
strcat(str_image_quality, "_");
}
if (image_size > 3) {
images->watermark = atoi(ngx_array_image[2]);
str_image_watermark = ngx_pcalloc(r->pool, sizeof(char) * (strlen(ngx_array_image[2])+2));
strcpy(str_image_watermark, ngx_array_image[2]);
strcat(str_image_watermark, "_");
}
if(str_image_resize != NULL && str_image_quality != NULL && str_image_watermark == NULL){
str_image = ngx_pcalloc(r->pool, sizeof(char) * (strlen(str_image_resize)+strlen(str_image_quality)+1));
strcat(str_image, str_image_resize);
strcat(str_image, str_image_quality);
}else if(str_image_resize != NULL && str_image_quality != NULL && str_image_watermark != NULL){
str_image = ngx_pcalloc(r->pool, sizeof(char) * (strlen(str_image_resize)+strlen(str_image_quality)+strlen(str_image_watermark)+1));
strcat(str_image, str_image_resize);
strcat(str_image, str_image_quality);
strcat(str_image, str_image_watermark);
}else{
return NULL;
}
char* new_uri = ngx_str_replace(str_image, "", (char *)ngx_string_uri);
images->path = ngx_pcalloc(r->pool,(strlen(new_uri) + 1) * sizeof(char));
ngx_cpystrn((u_char *)images->path,(u_char *)new_uri,(strlen(new_uri) + 1)* sizeof(char));
free(new_uri);
return images;
}
/* Handler function */
static ngx_int_t ngx_http_autohome_dis_opencv_handler(ngx_http_request_t *r) {
ngx_int_t rc;
ngx_buf_t *b;
ngx_chain_t out;
ngx_http_autohome_dis_opencv_loc_conf_t *elcf;
elcf = ngx_http_get_module_loc_conf(r, ngx_http_autohome_dis_opencv_module);
if (!(r->method & (NGX_HTTP_HEAD | NGX_HTTP_GET | NGX_HTTP_POST))) {
return NGX_HTTP_NOT_ALLOWED;
}
r->headers_out.content_type.len = sizeof("image/jpeg") - 1;
r->headers_out.content_type.data = (u_char *) "image/jpeg";
image_file_t* images = ngx_get_image(r);
if(images == NULL){
return NGX_HTTP_NOT_ALLOWED;
}
// process image begin
nginx_module_invoke_opencv_resize(&p,images);
if (images->code != NGX_HTTP_OK) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "");
}
if (images->len == 0 || images->data == NULL ) {
if (images->code == NGX_HTTP_NOT_FOUND)//���UNC������ͼƬ��ֻ����404�ļ�������
{
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"##########image data 's len = 0 or is NULL, statusCode=404\n");
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,images->path);
return images->code;
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,images->path);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
r->headers_out.status = images->code;
r->headers_out.content_length_n = images->len; //��ʱͼƬ���ȱض�����0
if (r->method == NGX_HTTP_HEAD) {
rc = ngx_http_send_header(r);
if (rc != NGX_OK) {
return rc;
}
}
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (b == NULL ) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"Failed to allocate response buffer.");
free(images->data);
free(images->path);
free(images);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
out.buf = b;
out.next = NULL;
int len = images->len;
u_char * ngx_data = ngx_pcalloc(r->pool, len * sizeof(u_char));
ngx_memcpy(ngx_data, images->data, len);
free(images->data); //���ͷ�opencv���
free(images);
b->pos = ngx_data;
b->last = ngx_data + len;
b->memory = 1;
b->last_buf = 1;
rc = ngx_http_send_header(r);
if (rc != NGX_OK) {
return rc;
}
return ngx_http_output_filter(r, &out);
}
static char *ngx_http_autohome_dis_opencv(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf) {
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module) ;
clcf->handler = ngx_http_autohome_dis_opencv_handler;
ngx_conf_set_str_slot(cf, cmd, conf);
return NGX_CONF_OK ;
}
static void *ngx_http_autohome_dis_opencv_create_loc_conf(ngx_conf_t *cf) {
ngx_http_autohome_dis_opencv_loc_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_autohome_dis_opencv_loc_conf_t));
if (conf == NULL ) {
return NGX_CONF_ERROR ;
}
conf->ed.len = 0;
conf->ed.data = NULL;
return conf;
}
static char *ngx_http_autohome_dis_opencv_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) {
ngx_http_autohome_dis_opencv_loc_conf_t *prev = parent;
ngx_http_autohome_dis_opencv_loc_conf_t *conf = child;
ngx_conf_merge_str_value(conf->ed, prev->ed, "");
return NGX_CONF_OK;
}
image_file_block.h
#pragma once
#ifndef IMAGE_FILE_BLOCK_H
#define IMAGE_FILE_BLOCK_H
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
typedef unsigned char u_char;
typedef struct {
size_t width;
size_t height;
size_t quality;
size_t code;
size_t watermark;
char* path;
u_char* data;
size_t len;
} image_file_t;
typedef struct {
} empty_struct;
#endif /* IMAGE_FILE_BLOCK_H */
opencv_resize.h
#pragma once
#ifndef OPENCV_RESIZE_H_
#define OPENCV_RESIZE_H_
#include "image_file_block.h"
//opencvͼƬ������
class OpenCvCompressPicture
{
public:
OpenCvCompressPicture();
~OpenCvCompressPicture();
void resize_image(image_file_t * retVal);
};
#endif //DIS_DATA_OPENCV_COMPRESS_PICTURE_H_
opencv_resize.cpp
#include "opencv_resize.h"
#include <cv.h>
#include <highgui.h>
using namespace cv;
OpenCvCompressPicture::OpenCvCompressPicture(void)
{
}
OpenCvCompressPicture::~OpenCvCompressPicture(void)
{
}
void OpenCvCompressPicture::resize_image(image_file_t * images)
{
string fullpath("/tmp/images_data");
fullpath.append(images->path);
IplImage* source =cvLoadImage(fullpath.c_str());
if(source == NULL)
{
return;
}
IplImage * dst = NULL;
dst = cvCreateImage(cvSize(images->width,images->height), source->depth, source->nChannels); //����Ŀ��ͼ��
cvResize(source, dst, CV_INTER_AREA); //����Դͼ��Ŀ��ͼ��
Mat img = cv::cvarrToMat(dst, true);
cvReleaseImage(&dst);
cvReleaseImage(&source);
int params[3] = {0};
params[0] = CV_IMWRITE_JPEG_QUALITY; //jpeg��������
params[1] = images->quality; //��������
cv::vector<u_char> buf;
cv::imencode(".jpg", img, buf, std::vector<int>(params, params+2));
u_char* result = reinterpret_cast<u_char *> (&buf[0]);
images->len=buf.size();
images->data=(u_char *)malloc(sizeof(u_char)*buf.size());
memcpy(images->data, result, images->len);
//�ͷ��ڴ�
cv::vector<u_char> b;
buf.swap(b);
images->code=200;
/*FILE* target = fopen("resultl.jpg", "wb");
fwrite(images->data, sizeof(u_char),images->len, target);
fclose(target); */
}
extern "C"
void nginx_module_invoke_opencv_resize(empty_struct * p,image_file_t * images)
{
OpenCvCompressPicture * urlParser = (OpenCvCompressPicture *)p;
urlParser->resize_image(images);
}
config
ngx_feature="ngx_http_autohome_dis_opencv_module"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs=
ngx_feature_path="$ngx_addon_dir /usr/local/opencv/include/ /usr/local/opencv/include/opencv"
ngx_feature_libs="-L/usr/local/opencv/lib/ -L/usr/local/lib/ -L/usr/lib64/"
ngx_feature_deps="$ngx_addon_dir/opencv_resize.h $ngx_addon_dir/image_file_block.h"
ngx_check_src="$ngx_addon_dir/ngx_http_autohome_dis_opencv_module.c $ngx_addon_dir/opencv_resize.cpp"
ngx_feature_test="int a;"
. auto/feature
ngx_addon_name=ngx_http_autohome_dis_opencv_module
HTTP_MODULES="$HTTP_MODULES ngx_http_autohome_dis_opencv_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_check_src"
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_feature_deps"
CORE_DEPS="$CORE_DEPS $ngx_feature_deps"
CORE_INCS="$CORE_INCS $ngx_feature_path"
CORE_LIBS="$CORE_LIBS $ngx_feature_libs -lstdc++ -lopencv_core -lopencv_highgui -Wl,-E -lpthread -lcrypt -lz -lc -lrt"
nginx opencv image resize
1.安装opencv:
a.opencv所依赖的一些包:(部分lib已安装,如需要安装通过yum install libpng,或者自行下载,相关软件放入软件包,此步骤可先省略)
yum install -y pkgconfig libpng zlib libjpeg libtiff cmake
b.cmake安装(opencv官方建议cmake最好在cmake-2.8.x以上):
cmake-2.8.9.tar.gz
tar –zxvf cmake-2.8.9
cd cmake-2.8.9
./configure –-prefix=/usr/local/cmake
make && make install
cp -r /usr/local/cmake/bin/ /usr/bin/
c.下载安装:
wget http://aarnet.dl.sourceforge.net/project/opencvlibrary/opencv-unix/2.4.2/OpenCV-2.4.1.tar.bz2
tar –xvf OpenCV-2.4.1.tar.bz2
cd OpenCV-2.4.1
(确认cmake必须安装)
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local/opencv .
make && make install
d.环境变量配置:
vim /etc/ld.so.conf
最后一行加入
/usr/local/opencv/lib/
e.复制到系统目录:
cp -r /usr/local/opencv/include/ /usr/local/include/
f.生效:
ldconfig
2.安装nginx:
./configure --prefix=/usr/local/nginx --add-module=module/ngx_http_opencv_module
nginx.conf
location / { autohome_dis_opencv; }
ll /tmp/images_data/vendor/o/201308/15/a.jpg
127.0.0.1/vendor/o/201308/15/800x600_87_1_a.jpg
说明:
800x600_60_1_201208212013510914122.jpg
800x600 要压缩的图像尺寸(可随意调整)
60 图像质量参数(可随意调整)
1 水印