t_mlx *new_mlx(t_mlx *mlx, int av, char *name) { mlx->w = 500; mlx->h = 500; mlx->av = av; mlx->menu = 0; mlx->mouse_on = 0; mlx->x1 = -1.5; mlx->x2 = 1.5; mlx->y1 = -1.5; mlx->y2 = 1.5; mlx->max = 20; mlx->movex = 0; mlx->movey = 0; mlx->zoom = 1; if (av == 6) mlx->max = 1; mlx->change_color = 0; if (!(mlx->mlx = mlx_init())) str_exit(-1, "new.c : Error line 75"); if (!(mlx->win = mlx_new_window(mlx->mlx, mlx->w, mlx->h, str_maj(name)))) str_exit(-1, "new.c : Error line 77"); mlx->img = new_img(mlx); return (mlx); }
/* * write_new_image -- write one output image based on component + image data; * new image contains portion of original image * corresponding to a given color; other pixels are black * INPUTS: width -- image width in pixels * height -- image height in pixels * buf -- image data in 3-byte RGB form, top to bottom, left to right * (English reading order) * edge -- edge/color data (array of rows) * color -- component color for image extraction * img_num -- image id for output file name * OUTPUTS: none * RETURN VALUE: 0 on success, -1 on failure * SIDE EFFECTS: writes a file (see also save_jpeg_file for other side * effects) */ int32_t write_new_image (JPG_RGBImage image, const EdgeMap& edge, int32_t color, int32_t img_num,const struct edge_img_info info) { int32_t height = info.y_max-info.y_min+1; int32_t width = info.x_max-info.x_min+1; JPG_RGBImage new_img(height,width); char fname[30]; int32_t x; int32_t y; int32_t mid; int32_t ret_val; for (y = 0; height > y; y++) { for (x = 0; width > x; x++) { if (color==edge[info.y_min+y][info.x_min+x]) { new_img[y][x].r = image[info.y_min+y][info.x_min+x].r; new_img[y][x].g = image[info.y_min+y][info.x_min+x].g; new_img[y][x].b = image[info.y_min+y][info.x_min+x].b; } } } sprintf (fname, "output%03d.jpg", img_num); new_img.save(fname); }
int draw(t_mlx *f) { int x; int y; x = 0; if (f->draw == 1) new_img(f); while (x < f->x - 1) { y = 0; while (y <= f->y - 1) { draw_square(f, get_pt(x, y, f->map[x][y]),\ get_pt(x + 1, y, f->map[x + 1][y]),\ get_pt(x, y + 1, f->map[x][y + 1])); draw_square(f, get_pt(x + 1, y + 1, f->map[x + 1][y + 1]),\ get_pt(x + 1, y, f->map[x + 1][y]),\ get_pt(x, y + 1, f->map[x][y + 1])); y++; } x++; } f->draw = 1; mlx_put_image_to_window(f->mlx, f->win, f->img, 0, 0); display(f); return (0); }
/*----------------------------------------------------------------- * Core routine for msskl_filter * - suffix "np" stands for "no padding" * - assumes image is properly padded! * - does not trimm result * - assume shp already allocated * - useful inside loops *-----------------------------------------------------------------*/ AnimalExport int msskl_filter_np(Img *shp, Img *sklimg, annotated_skl *skl, int thresh) { int i,j,k; int maxrad, r, c, *pt; SEDR *sedr; unsigned d; unsigned p, pf; r = skl->skl->rows; c = skl->skl->cols; maxrad = skl->maxradius; if (thresh > 0) { sklimg = new_img(r, c); for (i=0; i < r * c; i++) sklimg->data[i] = (skl->skl->data[i] >= (puint32) thresh); } sedr = grow_sedr(maxrad); if (!sedr) return false; pt = sedr->pt; for (i=maxrad; i<shp->rows-maxrad; i++) for (j=maxrad; j<shp->cols-maxrad; j++) if ( RC(sklimg, i-maxrad, j-maxrad) == 1 ) { // found skeleton /* Paints digital circle around the skeleton with radius equal to the distance-transform value at each point. There should be a more efficient way to do this without using SEDR. */ d = RC(skl->dt, i-maxrad, j-maxrad); /* distance 0 */ RC(shp,i,j) = FG; p = 2; for (k=1; k < (int)sedr->length && sedr->sqrd_dist[k] <= d; k++) { pf = sedr->npts[k]; do { RC(shp,i + pt[p], j + pt[p+1]) = FG; p+=2; // unrolling RC(shp,i + pt[p], j + pt[p+1]) = FG; p+=2; RC(shp,i + pt[p], j + pt[p+1]) = FG; p+=2; RC(shp,i + pt[p], j + pt[p+1]) = FG; p+=2; } while (p < pf); } } return true; }
t_mlx *new_mlx(t_mlx *mlx) { mlx->w = 1280; mlx->h = 720; if (!(mlx->mlx = mlx_init())) { ft_putstr("ERROR"); exit(-1); } if (!(mlx->win = mlx_new_window(mlx->mlx, mlx->w, mlx->h, "W O L F 3 D"))) { ft_putstr("ERROR"); exit(-1); } mlx->imgsky = new_xpm(mlx, mlx->w, mlx->h); mlx->imgview = new_img(mlx, mlx->w, mlx->h); mlx->imgmap = new_img(mlx, mlx->mapw * 10, mlx->maph * 10); mlx->deg = 90; return (mlx); }
void launch(int fd) { t_env e; e.mlx = mlx_init(); e.win = mlx_new_window(e.mlx, WIN_X, WIN_Y, "insert a funny title here"); load_textures(e.mlx); e.draw_img = new_img(e.mlx, WIN_X, WIN_Y); if (!(e.map = new_map_with_fd(fd))) return (ft_putstr("Map error\n")); init_kernel(&e); draw_env(&e); mlx_loop(e.mlx); }
main(int argc, char *argv[]) { Img *img, *tmp, *overpose; char filename[100] = "../images/bicycle.png"; annotated_skl *skl; int thresh=25, i; animal_err_set_trace(ANIMAL_ERR_TRACE_ON); if (--argc >=1) strncpy(filename, argv[1],99); if (argc == 2) sscanf(argv[2], "%d",&thresh); img=imread(filename); im2binary_ip(img); // regularize the image tmp = img; img = imregularize(img, NULL); imfree(&tmp); skl = msskl(img,INTERIOR,SKL_IFT); if (!skl) animal_err_default_reporter(); overpose = new_img(img->rows,img->cols); for (i=0; i<img->rows*img->cols; i++) overpose->data[i] =(skl->skl->data[i] >= (puint32) thresh) + img->data[i]; if (!imshow(overpose,0,-1)) printf("err\n"); tmp=msskl_filter(NULL, skl, thresh); for (i=0; i<img->rows*img->cols; i++) overpose->data[i] = (skl->skl->data[i] >= (puint32) thresh) + tmp->data[i]; imshow(overpose,0,-1); imwrite(overpose,"teste.png",true); free_ann_skl(&skl); imfree(&img); imfree(&tmp); imfree(&overpose); animal_heap_report(NULL); return 0; }
void *img_read_quantel(const T_CHAR *fname, int *w, int *h, int type) { FILE *fileyuv; IMAGE *image; LPIXEL *bufout1, *bufout2, *buf; int xsize, ysize, imgoffs, quantel_xsize; int y, exit = 0; fileyuv = _wfopen(fname, L"rb"); if (fileyuv == NULL) { /*printf("img_read_quantel error: unable to open file %s\n", fname);*/ return NIL; } if (type == VPB_FORMAT) { if (!vpb_get_info(fileyuv, &xsize, &ysize, &imgoffs)) { fclose(fileyuv); return NIL; } fseek(fileyuv, imgoffs, SEEK_SET); quantel_xsize = xsize; } else { if (!quantel_get_info(fname, type, &xsize, &ysize)) { fclose(fileyuv); return NIL; } quantel_xsize = QUANTEL_XSIZE; } image = new_img(); image->type = TOONZRGB; if (!allocate_pixmap(image, xsize, ysize)) return NIL; bufout1 = bufout2 = (LPIXEL *)image->buffer; bufout1 += ysize * xsize - 1; bufout2 += (ysize - 1) * xsize - 1; if (type == SDL_FORMAT) { for (y = 0; y < ysize; y += 2) { buf = bufout1 - (quantel_xsize - 1); QUANTEL_GET_YUV_LINE(fileyuv, buf, quantel_xsize) if (exit) break; bufout1 -= quantel_xsize * 2; } for (y = 1; y < ysize; y += 2) { buf = bufout2 - (quantel_xsize - 1); QUANTEL_GET_YUV_LINE(fileyuv, buf, quantel_xsize) if (exit) break; bufout2 -= quantel_xsize * 2; } } else { for (y = 0; y < ysize; y++) {
/* subtracao de media local 2D (vizinhanca circular) outside param: indicates value to assume outside the image when it will be padded. */ AnimalExport Img * smedia2d(Img *img, int radius, pixval outside) { int i,j, cod; unsigned k; double sum; Img *out; DblM *aux; nhood *nh; /* pad image */ img = impad(img,radius,radius,outside); aux = new_dbl_m(img->rows,img->cols); nh = circular_nhood((double)radius); /* @@@@@@@ This is better done in scilab using fft convolution by a disk image. This technique might be used with exact dilation as well as with morphological dilation. */ sum=0; for (i=radius; i<img->rows-radius-1; i++) for (j=radius; j<img->cols-radius-1; j++) { for (k=0; k < nh->n; k++) sum += (double)RC(img,i+nh->dy[k],j+nh->dx[k])/(double)nh->n; RC(aux,i,j) = (double)RC(img,i,j)-(double)sum; sum=0; } /* normalize */ /* @@@ if speed is needed, maybe normalize within the above loop */ cod = normal_dbl_m(aux,0,255); if (!cod) return NULL; out = new_img(img->rows-2*radius, img->cols-2*radius); for (i=0; i<out->rows; i++) for (j=0; j<out->cols; j++) RC(out,i,j) =(pixval) RC(aux,i+radius,j+radius); free_dbl_m(&aux); imfree(&img); return out; }
/*--------------------------------------------------------------------- * Multiscale Shape Reconstruction using Multiscale Skeletons * - if thresh is negative, assume already thresholded skeleton * - if thresh is positive, sklimg is not used at all (may be null) *---------------------------------------------------------------------*/ AnimalExport Img * msskl_filter(Img *sklimg, annotated_skl *skl, int thresh) { Img *shp, *result; int maxrad, r, c; r = skl->skl->rows; c = skl->skl->cols; maxrad = skl->maxradius; shp= new_img(r + 2*maxrad,c + 2*maxrad); shp->isbinary=true; // calls core routine if (!msskl_filter_np(shp, sklimg, skl, thresh)) return NULL; result = imtrim(shp,maxrad,maxrad); imfree(&shp); return result; }
main(int argc, char *argv[]) { Img *img; nhood *nh; int i,radius=10; if (--argc == 1) sscanf(argv[1],"%d",&radius); img=new_img(2*radius+1,2*radius+1); nh = circular_nhood(radius); for (i=0; i<nh->n; i++) RC(img,radius+nh->dy[i],radius+nh->dx[i]) = 1; imshow(img,0,-1); free_nhood(&nh); imfree(&img); return 0; }
t_mlx *new_mlx(t_mlx *mlx, char *av) { mlx->w = 2560; mlx->h = 1440; if (!(mlx->mlx = mlx_init())) str_exit(-1, "new.c : Error line 34"); if (!(mlx->win = mlx_new_window(mlx->mlx, mlx->w, mlx->h, "F D F"))) str_exit(-1, "new.c : Error line 36"); mlx->img = new_img(mlx); mlx->decalx = 300; mlx->decaly = 300; mlx->perspx = 0; mlx->perspy = 0; mlx->space = 10; mlx->dim = 3; mlx->erasing = 0; mlx->av = av; mlx->menu = 0; mlx->change_color = 11; return (mlx); }
AnimalExport int thinzs_np(Img *A) { bool repeat; Img *B; int i,j,n; B = new_img(A->rows,A->cols); if (!B) return false; do { repeat=false; for (i=1; i < A->rows-1; i++) for (j=1; j < A->cols-1; j++) if ((RC(B,i,j) = RC(A,i,j)) == FG) { n = nh8count_np(A,i,j,FG); if ( n>=2 && n<=6 && crossing_index_np(A,i,j) == 2 ) if((RC(A,i-1,j)==BG || RC(A,i,j+1)==BG || RC(A,i+1,j)==BG) && (RC(A,i-1,j)==BG || RC(A,i+1,j)==BG || RC(A,i,j-1)==BG)){ RC(B,i,j) = BG; repeat=true; } } for (i=1; i < A->rows-1; i++) for (j=1; j < A->cols-1; j++) if ((RC(A,i,j) = RC(B,i,j)) == FG) { n = nh8count_np(B,i,j,FG); if ( n>=2 && n<=6 && crossing_index_np(B,i,j) == 2 ) if((RC(B,i,j+1)==BG || RC(B,i,j-1)==BG || RC(B,i-1,j)==BG) && (RC(B,i-1,j)==BG || RC(B,i,j-1)==BG || RC(B,i+1,j)==BG)){ RC(A,i,j) = BG; repeat=true; } } } while (repeat); imfree(&B); return true; }
wxBitmap *PointMan::CreateDimBitmap( wxBitmap *pBitmap, double factor ) { wxImage img = pBitmap->ConvertToImage(); int sx = img.GetWidth(); int sy = img.GetHeight(); wxImage new_img( img ); for( int i = 0; i < sx; i++ ) { for( int j = 0; j < sy; j++ ) { if( !img.IsTransparent( i, j ) ) { new_img.SetRGB( i, j, (unsigned char) ( img.GetRed( i, j ) * factor ), (unsigned char) ( img.GetGreen( i, j ) * factor ), (unsigned char) ( img.GetBlue( i, j ) * factor ) ); } } } wxBitmap *pret = new wxBitmap( new_img ); return pret; }
/** * @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; }
void corpus_gen::sort_blocks(image_u8& img) { const uint num_blocks_x = img.get_width() / 4; const uint num_blocks_y = img.get_height() / 4; const uint total_blocks = num_blocks_x * num_blocks_y; console::printf("Sorting %u blocks...", total_blocks); crnlib::vector<float> block_std_dev(total_blocks); for (uint by = 0; by < num_blocks_y; by++) { for (uint bx = 0; bx < num_blocks_x; bx++) { color_quad_u8 c[4 * 4]; for (uint y = 0; y < 4; y++) for (uint x = 0; x < 4; x++) c[x+y*4] = img(bx*4+x, by*4+y); double std_dev = 0.0f; for (uint i = 0; i < 3; i++) std_dev += image_utils::compute_std_dev(16, c, i, 1); block_std_dev[bx + by * num_blocks_x] = (float)std_dev; } } crnlib::vector<uint> block_indices0(total_blocks); crnlib::vector<uint> block_indices1(total_blocks); const uint* pIndices = indirect_radix_sort(total_blocks, &block_indices0[0], &block_indices1[0], &block_std_dev[0], 0, sizeof(float), true); image_u8 new_img(img.get_width(), img.get_height()); uint dst_block_index = 0; //float prev_std_dev = -999; for (uint i = 0; i < total_blocks; i++) { uint src_block_index = pIndices[i]; //float std_dev = block_std_dev[src_block_index]; //crnlib_ASSERT(std_dev >= prev_std_dev); //prev_std_dev = std_dev; uint src_block_x = src_block_index % num_blocks_x; uint src_block_y = src_block_index / num_blocks_x; uint dst_block_x = dst_block_index % num_blocks_x; uint dst_block_y = dst_block_index / num_blocks_x; new_img.unclipped_blit(src_block_x * 4, src_block_y * 4, 4, 4, dst_block_x * 4, dst_block_y * 4, img); dst_block_index++; } #if 0 //new_img.swap(img); #else crnlib::vector<uint> remaining_blocks(num_blocks_x); console::printf("Arranging %u blocks...", total_blocks); for (uint by = 0; by < num_blocks_y; by++) { console::printf("%u of %u", by, num_blocks_y); remaining_blocks.resize(num_blocks_x); for (uint i = 0; i < num_blocks_x; i++) remaining_blocks[i] = i; color_quad_u8 match_block[16]; utils::zero_object(match_block); for (uint bx = 0; bx < num_blocks_x; bx++) { uint best_index = 0; uint64 best_error = cUINT64_MAX; for (uint i = 0; i < remaining_blocks.size(); i++) { uint src_block_index = remaining_blocks[i]; uint64 error = 0; for (uint y = 0; y < 4; y++) { for (uint x = 0; x < 4; x++) { const color_quad_u8& c = new_img(src_block_index*4+x, by*4+y); error += color::elucidian_distance(c, match_block[x+y*4], false); } } if (error < best_error) { best_error = error; best_index = i; } } uint src_block_index = remaining_blocks[best_index]; for (uint y = 0; y < 4; y++) { for (uint x = 0; x < 4; x++) { const color_quad_u8& c = new_img(src_block_index*4+x, by*4+y); match_block[x+y*4] = c; img(bx * 4 + x, by * 4 + y) = c; } } remaining_blocks.erase_unordered(best_index); } } #endif }
/** * @brief save_img Save buffer from POST requests * * @param buff The char * from POST request * @param len The length of buff * @param md5 Parsed md5 from url * * @return ZIMG_OK for success and ZIMG_ERR for fail */ int save_img(const char *buff, const int len, char *md5sum){ if(buff == NULL || md5sum == NULL || len <=0){ return ZIMG_ERR; } const char *image_format = get_img_format(buff); if(image_format == NULL){ return ZIMG_ERR; } calc_md5sum(buff,len,md5sum); char cache_key[45]; sprintf(cache_key, "img:%s:0:0:1:0", md5sum); if(exist_cache(cache_key) == 1){ LOG_PRINT(LOG_INFO, "File Exist, Needn't Save."); return ZIMG_OK; } LOG_PRINT(LOG_INFO, "exist_cache not found. Begin to Check File."); char *save_path = (char *)malloc(512); if(save_path == NULL){ return ZIMG_ERR; } //caculate 2-level path int lvl1 = str_hash(md5sum); int lvl2 = str_hash(md5sum + 3); sprintf(save_path, "%s/%d/%d/%s/0*0p", settings.img_path, lvl1, lvl2, md5sum); LOG_PRINT(LOG_INFO, "save_path: %s", save_path); if(is_file(save_path) == ZIMG_OK){ LOG_PRINT(LOG_INFO, "Check File Exist. Needn't Save."); //cache if(len < CACHE_MAX_SIZE) { // to gen cache_key like this: rsp_path-/926ee2f570dc50b2575e35a6712b08ce set_cache_bin(cache_key, buff, len); } free(save_path); return ZIMG_OK; }else{ char *p = strrchr(save_path,'/'); *p = '\0'; if(mk_dirs(save_path) == ZIMG_ERR){ LOG_PRINT(LOG_ERROR, "save_path[%s] Create Failed!", save_path); free(save_path); return ZIMG_ERR; } chdir(_init_path); LOG_PRINT(LOG_INFO, "save_path[%s] Create Finish.", save_path); *p = '/'; LOG_PRINT(LOG_INFO, "save_name-->: %s", save_path); if(new_img(buff, len, save_path) != ZIMG_OK){ LOG_PRINT(LOG_WARNING, "Save Image[%s] Failed!", save_path); free(save_path); return ZIMG_ERR; } //shrink as JPEG p = strrchr(save_path,'/'); memcpy(p+1,"0.jpg",5); *(p + 6) = '\0'; if(convert2jpg(buff,len,save_path) == ZIMG_OK){ LOG_PRINT(LOG_WARNING, "Convert Image to JPEG [%s] OK!", save_path); } free(save_path); return ZIMG_OK; } }
/** * @brief get_img get image from disk mode through the request * * @param req the zimg request * @param request the evhtp request * * @return 1 for OK, 2 for 304 needn't response buffer and -1 for failed */ int get_img(zimg_req_t *req, evhtp_request_t *request) { int result = -1; char rsp_cache_key[CACHE_KEY_SIZE]; int fd = -1; struct stat f_stat; char *buff = NULL; char *orig_buff = NULL; MagickWand *im = NULL; size_t len = 0; bool to_save = true; LOG_PRINT(LOG_DEBUG, "get_img() start processing zimg request..."); int lvl1 = str_hash(req->md5); int lvl2 = str_hash(req->md5 + 3); char whole_path[512]; snprintf(whole_path, 512, "%s/%d/%d/%s", settings.img_path, lvl1, lvl2, req->md5); LOG_PRINT(LOG_DEBUG, "whole_path: %s", whole_path); if(is_dir(whole_path) == -1) { LOG_PRINT(LOG_DEBUG, "Image %s is not existed!", req->md5); goto err; } if(settings.script_on == 1 && req->type != NULL) snprintf(rsp_cache_key, CACHE_KEY_SIZE, "%s:%s", req->md5, req->type); else { if(req->proportion == 0 && req->width == 0 && req->height == 0) str_lcpy(rsp_cache_key, req->md5, CACHE_KEY_SIZE); else gen_key(rsp_cache_key, req->md5, 9, req->width, req->height, req->proportion, req->gray, req->x, req->y, req->rotate, req->quality, req->fmt); } if(find_cache_bin(req->thr_arg, rsp_cache_key, &buff, &len) == 1) { LOG_PRINT(LOG_DEBUG, "Hit Cache[Key: %s].", rsp_cache_key); to_save = false; goto done; } LOG_PRINT(LOG_DEBUG, "Start to Find the Image..."); char orig_path[512]; snprintf(orig_path, 512, "%s/0*0", whole_path); LOG_PRINT(LOG_DEBUG, "0rig File Path: %s", orig_path); char rsp_path[512]; if(settings.script_on == 1 && req->type != NULL) snprintf(rsp_path, 512, "%s/t_%s", whole_path, req->type); else { char name[128]; snprintf(name, 128, "%d*%d_p%d_g%d_%d*%d_r%d_q%d.%s", req->width, req->height, req->proportion, req->gray, req->x, req->y, req->rotate, req->quality, req->fmt); if(req->width == 0 && req->height == 0 && req->proportion == 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); if((fd = open(rsp_path, O_RDONLY)) == -1) { im = NewMagickWand(); if (im == NULL) goto err; int ret; if(find_cache_bin(req->thr_arg, req->md5, &orig_buff, &len) == 1) { LOG_PRINT(LOG_DEBUG, "Hit Orignal Image Cache[Key: %s].", req->md5); ret = MagickReadImageBlob(im, (const unsigned char *)orig_buff, len); if (ret != MagickTrue) { LOG_PRINT(LOG_DEBUG, "Open Original Image From Blob Failed! Begin to Open it From Disk."); del_cache(req->thr_arg, req->md5); ret = MagickReadImage(im, orig_path); if (ret != MagickTrue) { LOG_PRINT(LOG_DEBUG, "Open Original Image From Disk Failed!"); goto err; } else { MagickSizeType size = MagickGetImageSize(im); LOG_PRINT(LOG_DEBUG, "image size = %d", size); if(size < CACHE_MAX_SIZE) { MagickResetIterator(im); char *new_buff = (char *)MagickWriteImageBlob(im, &len); if (new_buff == NULL) { LOG_PRINT(LOG_DEBUG, "Webimg Get Original Blob Failed!"); goto err; } set_cache_bin(req->thr_arg, req->md5, new_buff, len); free(new_buff); } } } } else { LOG_PRINT(LOG_DEBUG, "Not Hit Original Image Cache. Begin to Open it."); ret = MagickReadImage(im, orig_path); if (ret != MagickTrue) { LOG_PRINT(LOG_DEBUG, "Open Original Image From Disk Failed! %d != %d", ret, MagickTrue); LOG_PRINT(LOG_DEBUG, "Open Original Image From Disk Failed!"); goto err; } else { MagickSizeType size = MagickGetImageSize(im); LOG_PRINT(LOG_DEBUG, "image size = %d", size); if(size < CACHE_MAX_SIZE) { MagickResetIterator(im); char *new_buff = (char *)MagickWriteImageBlob(im, &len); if (new_buff == NULL) { LOG_PRINT(LOG_DEBUG, "Webimg Get Original Blob Failed!"); goto err; } set_cache_bin(req->thr_arg, req->md5, new_buff, len); free(new_buff); } } } if(settings.script_on == 1 && req->type != NULL) ret = lua_convert(im, req); else ret = convert(im, req); if(ret == -1) goto err; if(ret == 0) to_save = false; buff = (char *)MagickWriteImageBlob(im, &len); if (buff == NULL) { LOG_PRINT(LOG_DEBUG, "Webimg Get Blob Failed!"); goto err; } } else { to_save = false; fstat(fd, &f_stat); size_t rlen = 0; len = f_stat.st_size; if(len <= 0) { LOG_PRINT(LOG_DEBUG, "File[%s] is Empty.", rsp_path); goto err; } if((buff = (char *)malloc(len)) == NULL) { LOG_PRINT(LOG_DEBUG, "buff Malloc Failed!"); goto err; } LOG_PRINT(LOG_DEBUG, "img_size = %d", len); if((rlen = read(fd, buff, len)) == -1) { LOG_PRINT(LOG_DEBUG, "File[%s] Read Failed: %s", rsp_path, strerror(errno)); goto err; } else if(rlen < len) { LOG_PRINT(LOG_DEBUG, "File[%s] Read Not Compeletly.", rsp_path); goto err; } } //LOG_PRINT(LOG_INFO, "New Image[%s]", rsp_path); int save_new = 0; if(to_save == true) { if(req->sv == 1 || settings.save_new == 1 || (settings.save_new == 2 && req->type != NULL)) { save_new = 1; } } if(save_new == 1) { LOG_PRINT(LOG_DEBUG, "Image[%s] is Not Existed. Begin to Save it.", rsp_path); if(new_img(buff, len, 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 [%s] Needn't to Storage.", rsp_path); if(len < CACHE_MAX_SIZE) { set_cache_bin(req->thr_arg, rsp_cache_key, buff, len); } done: if(settings.etag == 1) { result = zimg_etag_set(request, buff, len); if(result == 2) goto err; } result = evbuffer_add(request->buffer_out, buff, len); if(result != -1) { result = 1; } err: if(fd != -1) close(fd); if(im != NULL) DestroyMagickWand(im); free(buff); free(orig_buff); return result; }
/** * @brief save_img Save buffer from POST requests * * @param thr_arg Thread arg struct. * @param buff The char * from POST request * @param len The length of buff * @param md5 Parsed md5 from url * * @return 1 for success and -1 for fail */ int save_img(thr_arg_t *thr_arg, const char *buff, const int len, char *md5) { int result = -1; LOG_PRINT(LOG_DEBUG, "Begin to Caculate MD5..."); md5_state_t mdctx; md5_byte_t md_value[16]; char md5sum[33]; int i; int h, l; md5_init(&mdctx); md5_append(&mdctx, (const unsigned char*)(buff), len); md5_finish(&mdctx, md_value); for(i=0; i<16; ++i) { h = md_value[i] & 0xf0; h >>= 4; l = md_value[i] & 0x0f; md5sum[i * 2] = (char)((h >= 0x0 && h <= 0x9) ? (h + 0x30) : (h + 0x57)); md5sum[i * 2 + 1] = (char)((l >= 0x0 && l <= 0x9) ? (l + 0x30) : (l + 0x57)); } md5sum[32] = '\0'; strcpy(md5, md5sum); LOG_PRINT(LOG_DEBUG, "md5: %s", md5sum); char cache_key[CACHE_KEY_SIZE]; char save_path[512]; char save_name[512]; gen_key(cache_key, md5sum, 0); if(exist_cache(thr_arg, cache_key) == 1) { LOG_PRINT(LOG_DEBUG, "File Exist, Needn't Save."); result = 1; goto done; } LOG_PRINT(LOG_DEBUG, "exist_cache not found. Begin to Save File."); if(settings.mode != 1) { if(save_img_db(thr_arg, cache_key, buff, len) == -1) { LOG_PRINT(LOG_DEBUG, "save_img_db failed."); goto done; } else { LOG_PRINT(LOG_DEBUG, "save_img_db succ."); result = 1; goto done; } } //caculate 2-level path int lvl1 = str_hash(md5sum); int lvl2 = str_hash(md5sum + 3); snprintf(save_path, 512, "%s/%d/%d/%s", settings.img_path, lvl1, lvl2, md5sum); LOG_PRINT(LOG_DEBUG, "save_path: %s", save_path); if(is_dir(save_path) == 1) { LOG_PRINT(LOG_DEBUG, "Check File Exist. Needn't Save."); goto cache; } if(mk_dirs(save_path) == -1) { LOG_PRINT(LOG_DEBUG, "save_path[%s] Create Failed!", save_path); goto done; } LOG_PRINT(LOG_DEBUG, "save_path[%s] Create Finish.", save_path); snprintf(save_name, 512, "%s/0*0", save_path); LOG_PRINT(LOG_DEBUG, "save_name-->: %s", save_name); if(new_img(buff, len, save_name) == -1) { LOG_PRINT(LOG_DEBUG, "Save Image[%s] Failed!", save_name); goto done; } cache: if(len < CACHE_MAX_SIZE) { gen_key(cache_key, md5sum, 0); set_cache_bin(thr_arg, cache_key, buff, len); } result = 1; done: return result; }
/** * @brief send_document_cb The callback function of get a image request. * * @param req The request with a list of params and the md5 of image. * @param arg It is not useful. */ void send_document_cb(evhtp_request_t *req, void *arg) { char *md5 = NULL; size_t len; zimg_req_t *zimg_req = NULL; char *buff = NULL; int req_method = evhtp_request_get_method(req); if(req_method >= 16) req_method = 16; LOG_PRINT(LOG_INFO, "Method: %d", req_method); if(strcmp(method_strmap[req_method], "POST") == 0) { LOG_PRINT(LOG_INFO, "POST Request."); post_request_cb(req, NULL); return; } else if(strcmp(method_strmap[req_method], "GET") != 0) { LOG_PRINT(LOG_INFO, "Request Method Not Support."); goto err; } const char *uri; uri = req->uri->path->full; const char *rfull = req->uri->path->full; const char *rpath = req->uri->path->path; const char *rfile= req->uri->path->file; LOG_PRINT(LOG_INFO, "uri->path->full: %s", rfull); LOG_PRINT(LOG_INFO, "uri->path->path: %s", rpath); LOG_PRINT(LOG_INFO, "uri->path->file: %s", rfile); if(strlen(uri) == 1 && uri[0] == '/') { LOG_PRINT(LOG_INFO, "Root Request."); int fd = -1; struct stat st; if((fd = open(settings.root_path, O_RDONLY)) == -1) { LOG_PRINT(LOG_WARNING, "Root_page Open Failed. Return Default Page."); evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg World!</h1>\n</body>\n</html>\n"); } else { if (fstat(fd, &st) < 0) { /* Make sure the length still matches, now that we * opened the file :/ */ LOG_PRINT(LOG_WARNING, "Root_page Length fstat Failed. Return Default Page."); evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg World!</h1>\n</body>\n</html>\n"); } else { evbuffer_add_file(req->buffer_out, fd, 0, st.st_size); } } evbuffer_add_printf(req->buffer_out, "<html>\n </html>\n"); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_INFO, "============send_document_cb() DONE!==============="); goto done; } if(strstr(uri, "favicon.ico")) { LOG_PRINT(LOG_INFO, "favicon.ico Request, Denied."); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); goto done; } LOG_PRINT(LOG_INFO, "Got a GET request for <%s>", uri); /* Don't allow any ".."s in the path, to avoid exposing stuff outside * of the docroot. This test is both overzealous and underzealous: * it forbids aceptable paths like "/this/one..here", but it doesn't * do anything to prevent symlink following." */ if (strstr(uri, "..")) goto err; md5 = (char *)malloc(strlen(uri) + 1); if(uri[0] == '/') strcpy(md5, uri+1); else strcpy(md5, uri); LOG_PRINT(LOG_INFO, "md5 of request is <%s>", md5); if(is_md5(md5) == -1) { LOG_PRINT(LOG_WARNING, "Url is Not a zimg Request."); goto err; } /* This holds the content we're sending. */ int width, height, proportion, gray; evhtp_kvs_t *params; params = req->uri->query; if(!params) { width = 0; height = 0; proportion = 1; gray = 0; } else { const char *str_w, *str_h; str_w = evhtp_kv_find(params, "w"); if(str_w == NULL) str_w = "0"; str_h = evhtp_kv_find(params, "h"); if(str_h == NULL) str_h = "0"; LOG_PRINT(LOG_INFO, "w() = %s; h() = %s;", str_w, str_h); if(strcmp(str_w, "g") == 0 && strcmp(str_h, "w") == 0) { LOG_PRINT(LOG_INFO, "Love is Eternal."); evbuffer_add_printf(req->buffer_out, "<html>\n <head>\n" " <title>Love is Eternal</title>\n" " </head>\n" " <body>\n" " <h1>Single1024</h1>\n" "Since 2008-12-22, there left no room in my heart for another one.</br>\n" "</body>\n</html>\n" ); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_INFO, "============send_document_cb() DONE!==============="); goto done; } else { width = atoi(str_w); height = atoi(str_h); const char *str_p = evhtp_kv_find(params, "p"); const char *str_g = evhtp_kv_find(params, "g"); if(str_p) proportion = atoi(str_p); else proportion = 1; if(str_g) gray = atoi(str_g); else gray = 0; } } zimg_req = (zimg_req_t *)malloc(sizeof(zimg_req_t)); zimg_req -> md5 = md5; zimg_req -> width = width; zimg_req -> height = height; zimg_req -> proportion = proportion; zimg_req -> gray = gray; int get_img_rst = get_img(zimg_req, &buff, &len); if(get_img_rst == -1) { LOG_PRINT(LOG_ERROR, "zimg Requset Get Image[MD5: %s] Failed!", zimg_req->md5); goto err; } LOG_PRINT(LOG_INFO, "get buffer length: %d", len); evbuffer_add(req->buffer_out, buff, len); LOG_PRINT(LOG_INFO, "Got the File!"); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "image/jpeg", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_INFO, "============send_document_cb() DONE!==============="); if(get_img_rst == 2) { if(new_img(buff, len, zimg_req->rsp_path) == -1) { LOG_PRINT(LOG_WARNING, "New Image[%s] Save Failed!", zimg_req->rsp_path); } } goto done; err: evbuffer_add_printf(req->buffer_out, "<html><body><h1>404 Not Found!</h1></body></html>"); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_NOTFOUND); LOG_PRINT(LOG_INFO, "============send_document_cb() ERROR!==============="); done: if(buff) free(buff); if(zimg_req) { if(zimg_req->md5) free(zimg_req->md5); if(zimg_req->rsp_path) free(zimg_req->rsp_path); free(zimg_req); } }