Example #1
0
static int get_wi_quality(lua_State *L) {
    lua_arg *larg = pthread_getspecific(thread_key);
    int quality = MagickGetImageCompressionQuality(larg->img);
    quality = (quality == 0 ? 100 : quality);
    lua_pushnumber(L, quality);
    return 1;
}
Example #2
0
/**
* @brief add_info Added image info to the request
*
* @param im The image struct
* @param req The evhtp request
*/
void add_info(MagickWand *im, evhtp_request_t *req)
{
    MagickSizeType size = MagickGetImageSize(im);
    unsigned long width = MagickGetImageWidth(im);
    unsigned long height = MagickGetImageHeight(im);
    size_t quality = MagickGetImageCompressionQuality(im);
    quality = (quality == 0 ? 100 : quality);
    char *format = MagickGetImageFormat(im);

    //{"ret":true,"info":{"size":195135,"width":720,"height":480,"quality":75,"format":"JPEG"}}
    cJSON *j_ret = cJSON_CreateObject();
    cJSON *j_ret_info = cJSON_CreateObject();
    cJSON_AddBoolToObject(j_ret, "ret", 1);
    cJSON_AddNumberToObject(j_ret_info, "size", size);
    cJSON_AddNumberToObject(j_ret_info, "width", width);
    cJSON_AddNumberToObject(j_ret_info, "height", height);
    cJSON_AddNumberToObject(j_ret_info, "quality", quality);
    cJSON_AddStringToObject(j_ret_info, "format", format);
    cJSON_AddItemToObject(j_ret, "info", j_ret_info);
    char *ret_str_unformat = cJSON_PrintUnformatted(j_ret);
    LOG_PRINT(LOG_DEBUG, "ret_str_unformat: %s", ret_str_unformat);
    evbuffer_add_printf(req->buffer_out, "%s", ret_str_unformat);
    cJSON_Delete(j_ret);
    free(ret_str_unformat);
    free(format);
}
Example #3
0
apr_status_t
dims_quality_operation (dims_request_rec *d, char *args, char **err) {
    int quality = apr_strtoi64(args, NULL, 0);
    int existing_quality = MagickGetImageCompressionQuality(d->wand);

    if(existing_quality == 0 || quality < existing_quality) {
        MAGICK_CHECK(MagickSetImageCompressionQuality(d->wand, quality), d);
    }
    return DIMS_SUCCESS;
}
Example #4
0
File: zdb.c Project: haython/zimg
/**
 * @brief get_img_mode_db Get image from db mode backend.
 *
 * @param req zimg request struct
 * @param buff_ptr buff pointer
 * @param img_size buff size
 *
 * @return 1 for success and -1 for failed
 */
int get_img_mode_db(zimg_req_t *req, evhtp_request_t *request)
{
    int result = -1;
    char cache_key[CACHE_KEY_SIZE];
    char *img_format = NULL;
    char *buff_ptr = NULL;
    size_t img_size;

    MagickBooleanType status;
    MagickWand *magick_wand = NULL;

    bool got_rsp = true;
    bool got_color = false;

    LOG_PRINT(LOG_DEBUG, "get_img() start processing zimg request...");

    if(req->gray == 1)
    {
        gen_key(cache_key, req->md5, 4, req->width, req->height, req->proportion, req->gray);
    }
    else
    {
        if(req->proportion == 0 && req->width == 0 && req->height == 0)
        {
            gen_key(cache_key, req->md5, 0);
        }
        else
        {
            gen_key(cache_key, req->md5, 3, req->width, req->height, req->proportion);
        }
    }
    if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1)
    {
        LOG_PRINT(LOG_DEBUG, "Hit Cache[Key: %s].", cache_key);
        goto done;
    }
    LOG_PRINT(LOG_DEBUG, "Start to Find the Image...");
    if(get_img_db(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1)
    {
        LOG_PRINT(LOG_DEBUG, "Get image [%s] from backend db succ.", cache_key);
        if(img_size < CACHE_MAX_SIZE)
        {
            set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
        }
        goto done;
    }

    magick_wand = NewMagickWand();
    got_rsp = false;
    if(req->gray == 1)
    {
        gen_key(cache_key, req->md5, 3, req->width, req->height, req->proportion);
        if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1)
        {
            LOG_PRINT(LOG_DEBUG, "Hit Color Image Cache[Key: %s, len: %d].", cache_key, img_size);
            status = MagickReadImageBlob(magick_wand, buff_ptr, img_size);
            free(buff_ptr);
            buff_ptr = NULL;
            if(status == MagickFalse)
            {
                LOG_PRINT(LOG_DEBUG, "Color Image Cache[Key: %s] is Bad. Remove.", cache_key);
                del_cache(req->thr_arg, cache_key);
            }
            else
            {
                got_color = true;
                LOG_PRINT(LOG_DEBUG, "Read Image from Color Image Cache[Key: %s, len: %d] Succ. Goto Convert.", cache_key, img_size);
                goto convert;
            }
        }
        if(get_img_db(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1)
        {
            LOG_PRINT(LOG_DEBUG, "Get color image [%s] from backend db.", cache_key);
            status = MagickReadImageBlob(magick_wand, buff_ptr, img_size);
            if(status == MagickTrue)
            {
                got_color = true;
                LOG_PRINT(LOG_DEBUG, "Read Image from Color Image[%s] Succ. Goto Convert.", cache_key);
                if(img_size < CACHE_MAX_SIZE)
                {
                    set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
                }
                free(buff_ptr);
                buff_ptr = NULL;
                goto convert;
            }
        }
    }

    gen_key(cache_key, req->md5, 0);
    if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1)
    {
        LOG_PRINT(LOG_DEBUG, "Hit Cache[Key: %s].", cache_key);
    }
    else
    {
        if(get_img_db(req->thr_arg, cache_key, &buff_ptr, &img_size) == -1)
        {
            LOG_PRINT(LOG_DEBUG, "Get image [%s] from backend db failed.", cache_key);
            goto err;
        }
        else if(img_size < CACHE_MAX_SIZE)
        {
            set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
        }
    }

    status = MagickReadImageBlob(magick_wand, buff_ptr, img_size);
    free(buff_ptr);
    buff_ptr = NULL;
    if(status == MagickFalse)
    {
        ThrowWandException(magick_wand);
        del_cache(req->thr_arg, cache_key);
        LOG_PRINT(LOG_DEBUG, "Read image [%s] from blob failed.", cache_key);
        goto err;
    }

    if(req->width == 0 && req->height == 0)
    {
        LOG_PRINT(LOG_DEBUG, "Image [%s] needn't resize. Goto Convert.", cache_key);
        goto convert;
    }

    int width, height;
    width = req->width;
    height = req->height;
    float owidth = MagickGetImageWidth(magick_wand);
    float oheight = MagickGetImageHeight(magick_wand);
    if(width <= owidth && height <= oheight)
    {
        if(req->proportion == 1 || (req->proportion == 0 && req->width * req->height == 0))
        {
            if(req->height == 0)
            {
                height = width * oheight / owidth;
            }
            else
            {
                width = height * owidth / oheight;
            }
        }
        status = MagickResizeImage(magick_wand, width, height, LanczosFilter, 1.0);
        if(status == MagickFalse)
        {
            LOG_PRINT(LOG_DEBUG, "Image[%s] Resize Failed!", cache_key);
            goto err;
        }

        LOG_PRINT(LOG_DEBUG, "Resize img succ.");
    }
    else
    {
        got_rsp = true;
        LOG_PRINT(LOG_DEBUG, "Args width/height is bigger than real size, return original image.");
    }

convert:

    //compress image
    if(got_color == false)
    {
        LOG_PRINT(LOG_DEBUG, "Start to Compress the Image!");
        img_format = MagickGetImageFormat(magick_wand);
        LOG_PRINT(LOG_DEBUG, "Image Format is %s", img_format);
        if(strcmp(img_format, "JPEG") != 0)
        {
            LOG_PRINT(LOG_DEBUG, "Convert Image Format from %s to JPEG.", img_format);
            status = MagickSetImageFormat(magick_wand, "JPEG");
            if(status == MagickFalse)
            {
                LOG_PRINT(LOG_DEBUG, "Image[%s] Convert Format Failed!", cache_key);
            }
            LOG_PRINT(LOG_DEBUG, "Compress Image with JPEGCompression");
            status = MagickSetImageCompression(magick_wand, JPEGCompression);
            if(status == MagickFalse)
            {
                LOG_PRINT(LOG_DEBUG, "Image[%s] Compression Failed!", cache_key);
            }
        }
        size_t quality = MagickGetImageCompressionQuality(magick_wand);
        LOG_PRINT(LOG_DEBUG, "Image Compression Quality is %u.", quality);
        if(quality > WAP_QUALITY)
        {
            quality = WAP_QUALITY;
        }
        LOG_PRINT(LOG_DEBUG, "Set Compression Quality to 75%.");
        status = MagickSetImageCompressionQuality(magick_wand, quality);
        if(status == MagickFalse)
        {
            LOG_PRINT(LOG_DEBUG, "Set Compression Quality Failed!");
        }

        //strip image EXIF infomation
        LOG_PRINT(LOG_DEBUG, "Start to Remove Exif Infomation of the Image...");
        status = MagickStripImage(magick_wand);
        if(status == MagickFalse)
        {
            LOG_PRINT(LOG_DEBUG, "Remove Exif Infomation of the ImageFailed!");
        }

        buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size);
        if(buff_ptr == NULL)
        {
            LOG_PRINT(LOG_DEBUG, "Magick Get Image Blob Failed!");
            goto err;
        }
        gen_key(cache_key, req->md5, 3, req->width, req->height, req->proportion);
        if(got_rsp == false)
        {
            save_img_db(req->thr_arg, cache_key, buff_ptr, img_size);
        }
        if(img_size < CACHE_MAX_SIZE)
        {
            set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
        }
        if(req->gray == 1)
        {
            free(buff_ptr);
            buff_ptr = NULL;
        }
        else
        {
            goto done;
        }
    } 

    //gray image
    if(req->gray == 1)
    {
        LOG_PRINT(LOG_DEBUG, "Start to Remove Color!");
        status = MagickSetImageColorspace(magick_wand, GRAYColorspace);
        if(status == MagickFalse)
        {
            LOG_PRINT(LOG_DEBUG, "Image[%s] Remove Color Failed!", cache_key);
            goto err;
        }
        LOG_PRINT(LOG_DEBUG, "Image Remove Color Finish!");


        buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size);
        if(buff_ptr == NULL)
        {
            LOG_PRINT(LOG_DEBUG, "Magick Get Image Blob Failed!");
            goto err;
        }
        gen_key(cache_key, req->md5, 4, req->width, req->height, req->proportion, req->gray);
        if(got_rsp == false)
        {
            save_img_db(req->thr_arg, cache_key, buff_ptr, img_size);
        }
        if(img_size < CACHE_MAX_SIZE)
        {
            set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
        }
    }

done:
    result = evbuffer_add(request->buffer_out, buff_ptr, img_size);
    if(result != -1)
    {
        result = 1;
    }

err:
    if(magick_wand)
    {
        magick_wand=DestroyMagickWand(magick_wand);
    }
    if(img_format)
        free(img_format);
    if(buff_ptr)
        free(buff_ptr);
    return result;
}
Example #5
0
/**
 * @brief get_img The function of getting a image buffer and it's length.
 *
 * @param req The zimg_req_t from zhttp and it has the params of a request.
 * @param buff_ptr This function return image buffer in it.
 * @param img_size Get_img will change this number to return the size of image buffer.
 *
 * @return 1 for success and -1 for fail.
 */
int get_img(zimg_req_t *req, evhtp_request_t *request)
{
    int result = -1;
    char cache_key[CACHE_KEY_SIZE];
    char *img_format = NULL;
    int fd = -1;
    struct stat f_stat;
    char *buff_ptr;
    size_t img_size;

    MagickBooleanType status;
    MagickWand *magick_wand = NULL;

    bool got_rsp = true;
    bool got_color = false;

    LOG_PRINT(LOG_DEBUG, "get_img() start processing zimg request...");

    // to gen cache_key like this: 926ee2f570dc50b2575e35a6712b08ce:0:0:1:0
    gen_key(cache_key, req->md5, 4, req->width, req->height, req->proportion, req->gray);
    if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1)
    {
        LOG_PRINT(LOG_DEBUG, "Hit Cache[Key: %s].", cache_key);
        goto done;
    }
    LOG_PRINT(LOG_DEBUG, "Start to Find the Image...");

    char whole_path[512];
    int lvl1 = str_hash(req->md5);
    int lvl2 = str_hash(req->md5 + 3);
    snprintf(whole_path, 512, "%s/%d/%d/%s", settings.img_path, lvl1, lvl2, req->md5);
    LOG_PRINT(LOG_DEBUG, "docroot: %s", settings.img_path);
    LOG_PRINT(LOG_DEBUG, "req->md5: %s", req->md5);
    LOG_PRINT(LOG_DEBUG, "whole_path: %s", whole_path);

    char name[128];
    if(req->proportion && req->gray)
        snprintf(name, 128, "%d*%dpg", req->width, req->height);
    else if(req->proportion && !req->gray)
        snprintf(name, 128, "%d*%dp", req->width, req->height);
    else if(!req->proportion && req->gray)
        snprintf(name, 128, "%d*%dg", req->width, req->height);
    else
        snprintf(name, 128, "%d*%d", req->width, req->height);

    char color_name[128];
    if(req->proportion)
        snprintf(color_name, 128, "%d*%dp", req->width, req->height);
    else
        snprintf(color_name, 128, "%d*%d", req->width, req->height);

    char orig_path[512];
    snprintf(orig_path, strlen(whole_path) + 6, "%s/0*0", whole_path);
    LOG_PRINT(LOG_DEBUG, "0rig File Path: %s", orig_path);

    char rsp_path[512];
    if(req->width == 0 && req->height == 0 && req->proportion == 0 && req->gray == 0)
    {
        LOG_PRINT(LOG_DEBUG, "Return original image.");
        strncpy(rsp_path, orig_path, 512);
    }
    else
    {
        snprintf(rsp_path, 512, "%s/%s", whole_path, name);
    }
    LOG_PRINT(LOG_DEBUG, "Got the rsp_path: %s", rsp_path);

    char color_path[512];
    snprintf(color_path, 512, "%s/%s", whole_path, color_name);


    //status=MagickReadImage(magick_wand, rsp_path);
    if((fd = open(rsp_path, O_RDONLY)) == -1)
    {
        magick_wand = NewMagickWand();
        got_rsp = false;

        if(req->gray == 1)
        {
            gen_key(cache_key, req->md5, 3, req->width, req->height, req->proportion);
            if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1)
            {
                LOG_PRINT(LOG_DEBUG, "Hit Color Image Cache[Key: %s, len: %d].", cache_key, img_size);
                status = MagickReadImageBlob(magick_wand, buff_ptr, img_size);
                free(buff_ptr);
                buff_ptr = NULL;
                if(status == MagickFalse)
                {
                    LOG_PRINT(LOG_DEBUG, "Color Image Cache[Key: %s] is Bad. Remove.", cache_key);
                    del_cache(req->thr_arg, cache_key);
                }
                else
                {
                    got_color = true;
                    LOG_PRINT(LOG_DEBUG, "Read Image from Color Image Cache[Key: %s, len: %d] Succ. Goto Convert.", cache_key, img_size);
                    goto convert;
                }
            }

            status=MagickReadImage(magick_wand, color_path);
            if(status == MagickTrue)
            {
                got_color = true;
                LOG_PRINT(LOG_DEBUG, "Read Image from Color Image[%s] Succ. Goto Convert.", rsp_path);
                buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size);
                if(img_size < CACHE_MAX_SIZE)
                {
                    set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
                }
                free(buff_ptr);
                buff_ptr = NULL;

                goto convert;
            }
        }

        // to gen cache_key like this: rsp_path-/926ee2f570dc50b2575e35a6712b08ce
        gen_key(cache_key, req->md5, 0);
        if(find_cache_bin(req->thr_arg, cache_key, &buff_ptr, &img_size) == 1)
        {
            LOG_PRINT(LOG_DEBUG, "Hit Orignal Image Cache[Key: %s].", cache_key);
            status = MagickReadImageBlob(magick_wand, buff_ptr, img_size);
            free(buff_ptr);
            buff_ptr = NULL;
            if(status == MagickFalse)
            {
                LOG_PRINT(LOG_DEBUG, "Open Original Image From Blob Failed! Begin to Open it From Disk.");
                ThrowWandException(magick_wand);
                del_cache(req->thr_arg, cache_key);
                status = MagickReadImage(magick_wand, orig_path);
                if(status == MagickFalse)
                {
                    ThrowWandException(magick_wand);
                    goto err;
                }
                else
                {
                    buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size);
                    if(img_size < CACHE_MAX_SIZE)
                    {
                        set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
                    }
                    free(buff_ptr);
                    buff_ptr = NULL;
                }
            }
        }
        else
        {
            LOG_PRINT(LOG_DEBUG, "Not Hit Original Image Cache. Begin to Open it.");
            status = MagickReadImage(magick_wand, orig_path);
            if(status == MagickFalse)
            {
                ThrowWandException(magick_wand);
                goto err;
            }
            else
            {
                buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size);
                if(img_size < CACHE_MAX_SIZE)
                {
                    set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
                }
                free(buff_ptr);
                buff_ptr = NULL;
            }
        }

        int width, height;
        width = req->width;
        height = req->height;
        if(width == 0 && height == 0)
        {
            LOG_PRINT(LOG_DEBUG, "Image[%s] needn't resize. Goto Convert.", orig_path);
            goto convert;
        }
        float owidth = MagickGetImageWidth(magick_wand);
        float oheight = MagickGetImageHeight(magick_wand);
        if(width <= owidth && height <= oheight)
        {
            if(req->proportion == 1 || (req->proportion == 0 && req->width * req->height == 0))
            {
                if(req->height == 0)
                {
                    height = width * oheight / owidth;
                }
                else
                {
                    width = height * owidth / oheight;
                }
            }
            status = MagickResizeImage(magick_wand, width, height, LanczosFilter, 1.0);
            if(status == MagickFalse)
            {
                LOG_PRINT(LOG_DEBUG, "Image[%s] Resize Failed!", orig_path);
                goto err;
            }
            LOG_PRINT(LOG_DEBUG, "Resize img succ.");
        }
        else
        {
            // Note this strcpy because rsp_path is not useful. We needn't to save the new image.
            got_rsp = true;
            LOG_PRINT(LOG_DEBUG, "Args width/height is bigger than real size, return original image.");
        }
    }
    else
    {
        fstat(fd, &f_stat);
        size_t rlen = 0;
        img_size = f_stat.st_size;
        if(img_size <= 0)
        {
            LOG_PRINT(LOG_DEBUG, "File[%s] is Empty.", rsp_path);
            goto err;
        }
        if((buff_ptr = (char *)malloc(img_size)) == NULL)
        {
            LOG_PRINT(LOG_DEBUG, "buff_ptr Malloc Failed!");
            goto err;
        }
        LOG_PRINT(LOG_DEBUG, "img_size = %d", img_size);
        if((rlen = read(fd, buff_ptr, img_size)) == -1)
        {
            LOG_PRINT(LOG_DEBUG, "File[%s] Read Failed.", rsp_path);
            LOG_PRINT(LOG_DEBUG, "Error: %s.", strerror(errno));
            goto err;
        }
        else if(rlen < img_size)
        {
            LOG_PRINT(LOG_DEBUG, "File[%s] Read Not Compeletly.", rsp_path);
            goto err;
        }
        if(img_size < CACHE_MAX_SIZE)
        {
            set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
        }
        goto done;
    }

convert:

    if(got_color == false)
    {
        //compress image
        LOG_PRINT(LOG_DEBUG, "Start to Compress the Image!");
        img_format = MagickGetImageFormat(magick_wand);
        LOG_PRINT(LOG_DEBUG, "Image Format is %s", img_format);
        if(strcmp(img_format, "JPEG") != 0)
        {
            LOG_PRINT(LOG_DEBUG, "Convert Image Format from %s to JPEG.", img_format);
            status = MagickSetImageFormat(magick_wand, "JPEG");
            if(status == MagickFalse)
            {
                LOG_PRINT(LOG_DEBUG, "Image[%s] Convert Format Failed!", orig_path);
            }
            LOG_PRINT(LOG_DEBUG, "Compress Image with JPEGCompression");
            status = MagickSetImageCompression(magick_wand, JPEGCompression);
            if(status == MagickFalse)
            {
                LOG_PRINT(LOG_DEBUG, "Image[%s] Compression Failed!", orig_path);
            }
        }
        size_t quality = MagickGetImageCompressionQuality(magick_wand);
        LOG_PRINT(LOG_DEBUG, "Image Compression Quality is %u.", quality);
        if(quality > WAP_QUALITY)
        {
            quality = WAP_QUALITY;
        }
        LOG_PRINT(LOG_DEBUG, "Set Compression Quality to 75%.");
        status = MagickSetImageCompressionQuality(magick_wand, quality);
        if(status == MagickFalse)
        {
            LOG_PRINT(LOG_DEBUG, "Set Compression Quality Failed!");
        }

        //strip image EXIF infomation
        LOG_PRINT(LOG_DEBUG, "Start to Remove Exif Infomation of the Image...");
        status = MagickStripImage(magick_wand);
        if(status == MagickFalse)
        {
            LOG_PRINT(LOG_DEBUG, "Remove Exif Infomation of the ImageFailed!");
        }

        buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size);
        if(buff_ptr == NULL)
        {
            LOG_PRINT(LOG_DEBUG, "Magick Get Image Blob Failed!");
            goto err;
        }
        gen_key(cache_key, req->md5, 3, req->width, req->height, req->proportion);
        if(img_size < CACHE_MAX_SIZE)
        {
            set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
        }
        if(got_rsp == false)
        {
            LOG_PRINT(LOG_DEBUG, "Color Image[%s] is Not Existed. Begin to Save it.", color_path);
            if(new_img(buff_ptr, img_size, color_path) == -1)
            {
                LOG_PRINT(LOG_DEBUG, "Color Image[%s] Save Failed!", color_path);
                LOG_PRINT(LOG_WARNING, "fail save %s", color_path);
            }
        }
        if(req->gray == 1)
        {
            free(buff_ptr);
            buff_ptr = NULL;
        }
        else
        {
            goto done;
        }
    }

    //gray image
    if(req->gray == 1)
    {
        LOG_PRINT(LOG_DEBUG, "Start to Remove Color!");
        status = MagickSetImageColorspace(magick_wand, GRAYColorspace);
        if(status == MagickFalse)
        {
            LOG_PRINT(LOG_DEBUG, "Image[%s] Remove Color Failed!", orig_path);
            goto err;
        }
        LOG_PRINT(LOG_DEBUG, "Image Remove Color Finish!");

        buff_ptr = (char *)MagickGetImageBlob(magick_wand, &img_size);
        if(buff_ptr == NULL)
        {
            LOG_PRINT(LOG_DEBUG, "Magick Get Image Blob Failed!");
            goto err;
        }
        gen_key(cache_key, req->md5, 4, req->width, req->height, req->proportion, req->gray);
        if(img_size < CACHE_MAX_SIZE)
        {
            set_cache_bin(req->thr_arg, cache_key, buff_ptr, img_size);
        }
        if(got_rsp == false)
        {
            if(new_img(buff_ptr, img_size, rsp_path) == -1)
            {
                LOG_PRINT(LOG_DEBUG, "New Image[%s] Save Failed!", rsp_path);
                LOG_PRINT(LOG_WARNING, "fail save %s", rsp_path);
            }
        }
        else
            LOG_PRINT(LOG_DEBUG, "Image Needn't to Storage.", rsp_path);
    }

done:
    result = evbuffer_add(request->buffer_out, buff_ptr, img_size);
    if(result != -1)
    {
        result = 1;
    }

err:
    if(fd != -1)
        close(fd);
    if(magick_wand)
    {
        magick_wand=DestroyMagickWand(magick_wand);
    }
    if(img_format)
        free(img_format);
    if(buff_ptr)
        free(buff_ptr);
    return result;
}
Example #6
0
File: zimg.c Project: Codefor/zimg
/**
 * @brief get_img The function of getting a image buffer and it's length.
 *
 * @param req The zimg_req_t from zhttp and it has the params of a request.
 * @param buff_ptr This function return image buffer in it.
 * @param img_size Get_img will change this number to return the size of image buffer.
 *
 * @return ZIMG_OK for success and ZIMG_ERR for fail.
 */
int get_img(zimg_req_t *req, char **buff_ptr, size_t *img_size)
{
    int result = -1;
    char *rsp_path = NULL;
    char *whole_path = NULL;
    char *orig_path = NULL;
    char *color_path = NULL;
    char *img_format = NULL;
    size_t len;
    int fd = -1;
    struct stat f_stat;

    MagickBooleanType status;
    MagickWand *magick_wand = NULL;

    LOG_PRINT(LOG_INFO, "get_img() start processing zimg request...");

    char *cache_key = (char *)malloc(strlen(req->md5) + 32);
    if(cache_key == NULL){
	LOG_PRINT(LOG_INFO, "malloc failed!");
	return ZIMG_ERR;
    }
    // to gen cache_key like this: img:926ee2f570dc50b2575e35a6712b08ce:0:0:1:0
    sprintf(cache_key, "img:%s:%d:%d:%d:%d", req->md5, req->width, req->height, req->proportion, req->gray);
    if(find_cache_bin(cache_key, buff_ptr, img_size) == 1){
	LOG_PRINT(LOG_INFO, "Hit Cache[Key: %s].", cache_key);
	//        sprintf(cache_key, "type:%s:%d:%d:%d:%d", req->md5, req->width, req->height, req->proportion, req->gray);
	//        if(find_cache(cache_key, img_format) == -1)
	//        {
	//            LOG_PRINT(LOG_WARNING, "Cannot Hit Type Cache[Key: %s]. Use jpeg As Default.", cache_key);
	//            strcpy(img_format, "jpeg");
	//        }
	free(cache_key);
	return ZIMG_OK;
    }
    free(cache_key);

    LOG_PRINT(LOG_INFO, "Start to Find the Image...");

    //check img dir
    // /1023/1023/xxxxxxxxxxxxxxx.png
    len = strlen(req->md5) + strlen(settings.img_path) + 12;
    whole_path = malloc(len);

    if (whole_path == NULL){
	LOG_PRINT(LOG_ERROR, "whole_path malloc failed!");
	return ZIMG_ERR;
    }

    int lvl1 = str_hash(req->md5);
    int lvl2 = str_hash(req->md5 + 3);
    sprintf(whole_path, "%s/%d/%d/%s", settings.img_path, lvl1, lvl2, req->md5);
    LOG_PRINT(LOG_INFO, "docroot: %s", settings.img_path);
    LOG_PRINT(LOG_INFO, "req->md5: %s", req->md5);
    LOG_PRINT(LOG_INFO, "whole_path: %s", whole_path);

    char name[128];
    if(req->proportion && req->gray)
	sprintf(name, "%d*%dpg", req->width, req->height);
    else if(req->proportion && !req->gray)
	sprintf(name, "%d*%dp", req->width, req->height);
    else if(!req->proportion && req->gray)
	sprintf(name, "%d*%dg", req->width, req->height);
    else
	sprintf(name, "%d*%d", req->width, req->height);

    orig_path = (char *)malloc(strlen(whole_path) + 6);
    sprintf(orig_path, "%s/0*0p", whole_path);
    LOG_PRINT(LOG_INFO, "0rig File Path: %s", orig_path);

    rsp_path = (char *)malloc(512);
    if(req->width == 0 && req->height == 0 && req->gray == 0)
    {
	LOG_PRINT(LOG_INFO, "Return original image.");
	strcpy(rsp_path, orig_path);
    }
    else
    {
	sprintf(rsp_path, "%s/%s", whole_path, name);
    }
    LOG_PRINT(LOG_INFO, "Got the rsp_path: %s", rsp_path);
    bool got_rsp = true;
    bool got_color = false;


    //status=MagickReadImage(magick_wand, rsp_path);
    if((fd = open(rsp_path, O_RDONLY)) == -1)
	//if(status == MagickFalse)
    {
	magick_wand = NewMagickWand();
	got_rsp = false;

	if(req->gray == 1)
	{
	    sprintf(cache_key, "img:%s:%d:%d:%d:0", req->md5, req->width, req->height, req->proportion);
	    if(find_cache_bin(cache_key, buff_ptr, img_size) == 1)
	    {
		LOG_PRINT(LOG_INFO, "Hit Color Image Cache[Key: %s, len: %d].", cache_key, *img_size);
		status = MagickReadImageBlob(magick_wand, *buff_ptr, *img_size);
		if(status == MagickFalse)
		{
		    LOG_PRINT(LOG_WARNING, "Color Image Cache[Key: %s] is Bad. Remove.", cache_key);
		    del_cache(cache_key);
		}
		else
		{
		    got_color = true;
		    LOG_PRINT(LOG_INFO, "Read Image from Color Image Cache[Key: %s, len: %d] Succ. Goto Convert.", cache_key, *img_size);
		    goto convert;
		}
	    }

	    len = strlen(rsp_path);
	    color_path = (char *)malloc(len);
	    strncpy(color_path, rsp_path, len);
	    color_path[len - 1] = '\0';
	    LOG_PRINT(LOG_INFO, "color_path: %s", color_path);
	    status=MagickReadImage(magick_wand, color_path);
	    if(status == MagickTrue)
	    {
		got_color = true;
		LOG_PRINT(LOG_INFO, "Read Image from Color Image[%s] Succ. Goto Convert.", color_path);
		*buff_ptr = (char *)MagickGetImageBlob(magick_wand, img_size);
		if(*img_size < CACHE_MAX_SIZE)
		{
		    set_cache_bin(cache_key, *buff_ptr, *img_size);
		    //                    img_format = MagickGetImageFormat(magick_wand);
		    //                    sprintf(cache_key, "type:%s:%d:%d:%d:0", req->md5, req->width, req->height, req->proportion);
		    //                    set_cache(cache_key, img_format);
		}

		goto convert;
	    }
	}

	// to gen cache_key like this: rsp_path-/926ee2f570dc50b2575e35a6712b08ce
	sprintf(cache_key, "img:%s:0:0:1:0", req->md5);
	if(find_cache_bin(cache_key, buff_ptr, img_size) == 1)
	{
	    LOG_PRINT(LOG_INFO, "Hit Orignal Image Cache[Key: %s].", cache_key);
	    status = MagickReadImageBlob(magick_wand, *buff_ptr, *img_size);
	    if(status == MagickFalse)
	    {
		LOG_PRINT(LOG_WARNING, "Open Original Image From Blob Failed! Begin to Open it From Disk.");
		ThrowWandException(magick_wand);
		del_cache(cache_key);
		status = MagickReadImage(magick_wand, orig_path);
		if(status == MagickFalse)
		{
		    ThrowWandException(magick_wand);
		    goto err;
		}
		else
		{
		    *buff_ptr = (char *)MagickGetImageBlob(magick_wand, img_size);
		    if(*img_size < CACHE_MAX_SIZE)
		    {
			set_cache_bin(cache_key, *buff_ptr, *img_size);
			//                        img_format = MagickGetImageFormat(magick_wand);
			//                        sprintf(cache_key, "type:%s:0:0:1:0", req->md5);
			//                        set_cache(cache_key, img_format);
		    }
		}
	    }
	}
	else
	{
	    LOG_PRINT(LOG_INFO, "Not Hit Original Image Cache. Begin to Open it.");
	    status = MagickReadImage(magick_wand, orig_path);
	    if(status == MagickFalse)
	    {
		ThrowWandException(magick_wand);
		goto err;
	    }
	    else
	    {
		*buff_ptr = (char *)MagickGetImageBlob(magick_wand, img_size);
		if(*img_size < CACHE_MAX_SIZE)
		{
		    set_cache_bin(cache_key, *buff_ptr, *img_size);
		    //                    img_format = MagickGetImageFormat(magick_wand);
		    //                    sprintf(cache_key, "type:%s:0:0:1:0", req->md5);
		    //                    set_cache(cache_key, img_format);
		}
	    }
	}
	int width, height;
	width = req->width;
	height = req->height;
	float owidth = MagickGetImageWidth(magick_wand);
	float oheight = MagickGetImageHeight(magick_wand);
	if(width <= owidth && height <= oheight)
	{
	    if(req->proportion == 1)
	    {
		if(req->width != 0 && req->height == 0)
		{
		    height = width * oheight / owidth;
		}
		//else if(height != 0 && width == 0)
		else
		{
		    width = height * owidth / oheight;
		}
	    }
	    status = MagickResizeImage(magick_wand, width, height, LanczosFilter, 1.0);
	    if(status == MagickFalse)
	    {
		LOG_PRINT(LOG_ERROR, "Image[%s] Resize Failed!", orig_path);
		goto err;
	    }
	    LOG_PRINT(LOG_INFO, "Resize img succ.");
	}
	/* this section can caculate the correct rsp_path, but not use, so I note them
	   else if(req->gray == true)
	   {
	   strcpy(rsp_path, orig_path);
	   rsp_path[strlen(orig_path)] = 'g';
	   rsp_path[strlen(orig_path) + 1] = '\0';
	   got_rsp = true;
	   LOG_PRINT(LOG_INFO, "Args width/height is bigger than real size, return original gray image.");
	   LOG_PRINT(LOG_INFO, "Original Gray Image: %s", rsp_path);
	   }
	 */
	else
	{
	    // Note this strcpy because rsp_path is not useful. We needn't to save the new image.
	    //strcpy(rsp_path, orig_path);
	    got_rsp = true;
	    LOG_PRINT(LOG_INFO, "Args width/height is bigger than real size, return original image.");
	}
    }
    else
    {
	fstat(fd, &f_stat);
	size_t rlen = 0;
	*img_size = f_stat.st_size;
	if(*img_size <= 0)
	{
	    LOG_PRINT(LOG_ERROR, "File[%s] is Empty.", rsp_path);
	    goto err;
	}
	if((*buff_ptr = (char *)malloc(*img_size)) == NULL)
	{
	    LOG_PRINT(LOG_ERROR, "buff_ptr Malloc Failed!");
	    goto err;
	}
	LOG_PRINT(LOG_INFO, "img_size = %d", *img_size);
	//*buff_ptr = (char *)MagickGetImageBlob(magick_wand, img_size);
	if((rlen = read(fd, *buff_ptr, *img_size)) == -1)
	{
	    LOG_PRINT(LOG_ERROR, "File[%s] Read Failed.", rsp_path);
	    LOG_PRINT(LOG_ERROR, "Error: %s.", strerror(errno));
	    goto err;
	}
	else if(rlen < *img_size)
	{
	    LOG_PRINT(LOG_ERROR, "File[%s] Read Not Compeletly.", rsp_path);
	    goto err;
	}
	goto done;
    }



convert:
    //gray image
    if(req->gray == true)
    {
	LOG_PRINT(LOG_INFO, "Start to Remove Color!");
	status = MagickSetImageColorspace(magick_wand, GRAYColorspace);
	if(status == MagickFalse)
	{
	    LOG_PRINT(LOG_ERROR, "Image[%s] Remove Color Failed!", orig_path);
	    goto err;
	}
	LOG_PRINT(LOG_INFO, "Image Remove Color Finish!");
    }

    if(got_color == false || (got_color == true && req->width == 0) )
    {
	//compress image
	LOG_PRINT(LOG_INFO, "Start to Compress the Image!");
	img_format = MagickGetImageFormat(magick_wand);
	LOG_PRINT(LOG_INFO, "Image Format is %s", img_format);
	if(strcmp(img_format, "JPEG") != 0)
	{
	    LOG_PRINT(LOG_INFO, "Convert Image Format from %s to JPEG.", img_format);
	    status = MagickSetImageFormat(magick_wand, "JPEG");
	    if(status == MagickFalse)
	    {
		LOG_PRINT(LOG_WARNING, "Image[%s] Convert Format Failed!", orig_path);
	    }
	    LOG_PRINT(LOG_INFO, "Compress Image with JPEGCompression");
	    status = MagickSetImageCompression(magick_wand, JPEGCompression);
	    if(status == MagickFalse)
	    {
		LOG_PRINT(LOG_WARNING, "Image[%s] Compression Failed!", orig_path);
	    }
	}
	size_t quality = MagickGetImageCompressionQuality(magick_wand) * 0.75;
	LOG_PRINT(LOG_INFO, "Image Compression Quality is %u.", quality);
	if(quality == 0)
	{
	    quality = 75;
	}
	LOG_PRINT(LOG_INFO, "Set Compression Quality to 75%.");
	status = MagickSetImageCompressionQuality(magick_wand, quality);
	if(status == MagickFalse)
	{
	    LOG_PRINT(LOG_WARNING, "Set Compression Quality Failed!");
	}

	//strip image EXIF infomation
	LOG_PRINT(LOG_INFO, "Start to Remove Exif Infomation of the Image...");
	status = MagickStripImage(magick_wand);
	if(status == MagickFalse)
	{
	    LOG_PRINT(LOG_WARNING, "Remove Exif Infomation of the ImageFailed!");
	}
    }
    *buff_ptr = (char *)MagickGetImageBlob(magick_wand, img_size);
    if(*buff_ptr == NULL)
    {
	LOG_PRINT(LOG_ERROR, "Magick Get Image Blob Failed!");
	goto err;
    }


done:
    if(*img_size < CACHE_MAX_SIZE)
    {
	// to gen cache_key like this: rsp_path-/926ee2f570dc50b2575e35a6712b08ce
	sprintf(cache_key, "img:%s:%d:%d:%d:%d", req->md5, req->width, req->height, req->proportion, req->gray);
	set_cache_bin(cache_key, *buff_ptr, *img_size);
	//        sprintf(cache_key, "type:%s:%d:%d:%d:%d", req->md5, req->width, req->height, req->proportion, req->gray);
	//        set_cache(cache_key, img_format);
    }

    result = 1;
    if(got_rsp == false)
    {
	LOG_PRINT(LOG_INFO, "Image[%s] is Not Existed. Begin to Save it.", rsp_path);
	result = 2;
    }
    else
	LOG_PRINT(LOG_INFO, "Image Needn't to Storage.", rsp_path);

err:
    if(fd != -1)
	close(fd);
    req->rsp_path = rsp_path;
    if(magick_wand)
    {
	magick_wand=DestroyMagickWand(magick_wand);
    }
    if(img_format)
	free(img_format);
    if(cache_key)
	free(cache_key);
    if (orig_path)
	free(orig_path);
    if (whole_path)
	free(whole_path);
    return result;
}