static ngx_int_t ngx_http_small_light_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
    ngx_http_small_light_conf_t *loc_conf;
    ngx_http_small_light_ctx_t  *ctx;
    ngx_buf_t                   *b;
    ngx_pool_cleanup_t          *cln;
    ngx_chain_t                  out;
    ngx_int_t                    rc;
    size_t                       content_type_len;

    if (in == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    loc_conf = ngx_http_get_module_loc_conf(r, ngx_http_small_light_module);

    if (!loc_conf->enable) {
        return ngx_http_next_body_filter(r, in);
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_small_light_module);

    if (ctx == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    if((rc = ngx_http_small_light_image_read(r, in, loc_conf->buffer_size, ctx)) != NGX_OK) {
        if (rc == NGX_AGAIN) {
            return NGX_OK;
        }
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "failed to read image %s:%d",
                      __FUNCTION__,
                      __LINE__);
        return ngx_http_filter_finalize_request(r,
                                                &ngx_http_small_light_module,
                                                NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
    }

    r->connection->buffered &= ~NGX_HTTP_SMALL_LIGHT_IMAGE_BUFFERED;

    rc = ctx->converter.init(r, ctx);
    if (rc != NGX_OK) {

        ngx_pfree(r->pool, ctx->content_orig);

        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "failed to process image %s:%d",
                      __FUNCTION__,
                      __LINE__);
        return ngx_http_filter_finalize_request(r,
                                                &ngx_http_small_light_module,
                                                NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
    }

    rc = ctx->converter.process(r, ctx);

    if (rc != NGX_OK) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "failed to process image %s:%d",
                      __FUNCTION__,
                      __LINE__);
        ctx->converter.term(ctx);
        return ngx_http_filter_finalize_request(r,
                                                &ngx_http_small_light_module,
                                                NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
    }

    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 memory from r->pool %s:%d",
                      __FUNCTION__,
                      __LINE__);
        ctx->converter.term(ctx);
        return NGX_ERROR;
    }
    b->pos      = ctx->content;
    b->last     = ctx->content + ctx->content_length;
    b->memory   = 1;
    b->last_buf = 1;

    out.buf  = b;
    out.next = NULL;

    r->headers_out.content_length_n = b->last - b->pos;
    if (r->headers_out.content_length) {
        r->headers_out.content_length->hash = 0;
    }
    content_type_len = ngx_strlen(ctx->of);
    r->headers_out.content_length       = NULL;
    r->headers_out.content_type_len     = content_type_len;
    r->headers_out.content_type.len     = content_type_len;
    r->headers_out.content_type.data    = (u_char *)ctx->of;
    r->headers_out.content_type_lowcase = NULL;

    cln = ngx_pool_cleanup_add(r->pool, 0);
    if (cln == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "failed to allocate memory from r->pool %s:%d",
                      __FUNCTION__,
                      __LINE__);
        ctx->converter.term(ctx);
        return NGX_ERROR;
    }
    cln->handler = ctx->converter.term;
    cln->data    = ctx;

    return ngx_http_small_light_finish(r, &out);
}
static ngx_int_t ngx_http_small_light_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
    ngx_http_small_light_conf_t            *srv_conf;
    ngx_http_small_light_conf_t            *loc_conf;
    ngx_http_small_light_ctx_t             *ctx;
    ngx_chain_t                             out;
    ngx_int_t                               rc;

    if (in == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    srv_conf = ngx_http_get_module_srv_conf(r, ngx_http_small_light_module);
    loc_conf = ngx_http_get_module_loc_conf(r, ngx_http_small_light_module);

    if (!loc_conf->enable) {
        return ngx_http_next_body_filter(r, in);
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_small_light_module);

    if (ctx == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    if (ctx->ictx == NULL) {
        ctx->ictx = ngx_pcalloc(r->pool, sizeof(ngx_http_small_light_imagemagick_ctx_t));
        if (ctx->ictx == NULL) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__);
            return NGX_ERROR;
        }
    }

    if((rc = ngx_http_small_light_image_read(r, in, ctx)) != NGX_OK) {
        if (rc == NGX_AGAIN) {
            return NGX_OK;
        }
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__);
        return NGX_ERROR;
    }

    r->connection->buffered &= ~NGX_HTTP_SMALL_LIGHT_IMAGE_BUFFERED;

    ngx_http_small_light_imagemagick_init(ctx);

    rc = ngx_http_small_light_imagemagick_process(r, ctx);

    ngx_http_small_light_imagemagick_term(ctx);

    if (rc != NGX_OK) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__);
        return NGX_ERROR;
    }

    ngx_buf_t *b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
    if (b == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__);
        return NGX_ERROR;
    }
    b->pos      = ctx->content;
    b->last     = ctx->content + ctx->content_length;
    b->memory   = 1;
    b->last_buf = 1;

    out.buf  = b;
    out.next = NULL;

    r->headers_out.content_length_n = b->last - b->pos;
    if (r->headers_out.content_length) {
        r->headers_out.content_length->hash = 0;
    }
    r->headers_out.content_length = NULL;

    ngx_pool_cleanup_t *cln;
    cln = ngx_pool_cleanup_add(r->pool, 0);
    if (cln == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__);
        return NGX_ERROR;
    }
    cln->handler = ngx_http_small_light_cleanup;
    cln->data    = ctx;

    return ngx_http_small_light_finish(r, &out);
}