//Routine for reading an input image void read_image(image *I, const char file_name[]) { char s[128]; FILE *f; int i,j; f=fopen(file_name,"rb"); if(!f) printf("Error opening image file\n"), exit(-1); for(i=0 ; i<3 ; i++){ fgets(s,99,f); if(s[0]=='#') //it is a comment i--; else if(i==1) sscanf(s,"%d %d",&I->width,&I->height); } alloc_image(I); for(i=0; i < I->height; i++) for(j=0; j < I->width; j++) I->pixels[i*I->width+j] = (unsigned char)fgetc(f); fclose(f); return; }
/** * Initialise initrd * * @ret rc Return status code */ static int initrd_init ( void ) { struct image *image; int rc; /* Do nothing if no initrd was specified */ if ( ! initrd_phys ) { DBGC ( colour, "RUNTIME found no initrd\n" ); return 0; } if ( ! initrd_len ) { DBGC ( colour, "RUNTIME found empty initrd\n" ); return 0; } DBGC ( colour, "RUNTIME found initrd at [%x,%x)\n", initrd_phys, ( initrd_phys + initrd_len ) ); /* Allocate image */ image = alloc_image(); if ( ! image ) { DBGC ( colour, "RUNTIME could not allocate image for " "initrd\n" ); rc = -ENOMEM; goto err_alloc_image; } image_set_name ( image, "<INITRD>" ); /* Allocate and copy initrd content */ image->data = umalloc ( initrd_len ); if ( ! image->data ) { DBGC ( colour, "RUNTIME could not allocate %zd bytes for " "initrd\n", initrd_len ); rc = -ENOMEM; goto err_umalloc; } image->len = initrd_len; memcpy_user ( image->data, 0, phys_to_user ( initrd_phys ), 0, initrd_len ); /* Mark initrd as consumed */ initrd_phys = 0; /* Register image */ if ( ( rc = register_image ( image ) ) != 0 ) { DBGC ( colour, "RUNTIME could not register initrd: %s\n", strerror ( rc ) ); goto err_register_image; } /* Drop our reference to the image */ image_put ( image ); return 0; err_register_image: err_umalloc: image_put ( image ); err_alloc_image: return rc; }
void fill_borders(rgba_surface* dst, rgba_surface* src, int block_width, int block_height) { int full_width = idiv_ceil(src->width, block_width) * block_width; int full_height = idiv_ceil(src->height, block_height) * block_height; alloc_image(dst, full_width, full_height); ReplicateBorders(dst, src, 0, 0, 32); }
ENTRYPOINT void init_slideshow (ModeInfo *mi) { int screen = MI_SCREEN(mi); slideshow_state *ss; int wire = MI_IS_WIREFRAME(mi); if (sss == NULL) { if ((sss = (slideshow_state *) calloc (MI_NUM_SCREENS(mi), sizeof(slideshow_state))) == NULL) return; } ss = &sss[screen]; if ((ss->glx_context = init_GL(mi)) != NULL) { reshape_slideshow (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); } else { MI_CLEARWINDOW(mi); } if (debug_p) fprintf (stderr, "%s: pan: %d; fade: %d; img: %d; zoom: %d%%\n", blurb(), pan_seconds, fade_seconds, image_seconds, zoom); sanity_check(mi); if (debug_p) fprintf (stderr, "%s: pan: %d; fade: %d; img: %d; zoom: %d%%\n\n", blurb(), pan_seconds, fade_seconds, image_seconds, zoom); glDisable (GL_LIGHTING); glDisable (GL_DEPTH_TEST); glDepthMask (GL_FALSE); glEnable (GL_CULL_FACE); glCullFace (GL_BACK); if (! wire) { glEnable (GL_TEXTURE_2D); glShadeModel (GL_SMOOTH); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } if (debug_p) glLineWidth (3); ss->font_data = load_texture_font (mi->dpy, "titleFont"); if (debug_p) hack_resources(); ss->now = double_time(); ss->dawn_of_time = ss->now; ss->prev_frame_time = ss->now; ss->awaiting_first_image_p = True; alloc_image (mi); }
void compute_sift_keypoints(float *input, keypointslist& keys, int width, int height, siftPar &par) { flimage image; /// Make zoom of image if necessary float octSize = 1.0f; if (par.DoubleImSize){ //printf("... compute_sift_keypoints :: applying zoom\n"); image = alloc_image<float>(2*width, 2*height); apply_zoom(input,image.data,2.0,par.order,width,height); octSize *= 0.5f; } else image = alloc_image( make_image(input,width,height) ); /// Apply initial smoothing to input image to raise its smoothing to par.InitSigma. /// We assume image from camera has smoothing of sigma = 0.5, which becomes sigma = 1.0 if image has been doubled. /// increase = sqrt(Init^2 - Current^2) float curSigma=0.5f; if (par.DoubleImSize) curSigma *= 2.0f; if (par.InitSigma > curSigma ) { if (DEBUG) printf("Convolving initial image to achieve std: %f \n", par.InitSigma); float sigma = (float)sqrt(par.InitSigma*par.InitSigma - curSigma*curSigma); gaussian_convolution(image.data, image.data, image.w, image.h, sigma); } /// Convolve by par.InitSigma at each step inside OctaveKeypoints by steps of /// Subsample of factor 2 while reasonable image size /// Keep reducing image by factors of 2 until one dimension is /// smaller than minimum size at which a feature could be detected. int minsize = 2 * par.BorderDist + 2; //printf("... compute_sift_keypoints :: maximum number of scales : %d\n", par.OctaveMax); for(int i=(par.DoubleImSize?-1:0); i<=par.OctaveMax && image.w>minsize && image.h>minsize; i++) { if(DEBUG) printf("Calling OctaveKeypoints \n"); OctaveKeypoints(image, octSize, keys,par); // image is blurred inside OctaveKeypoints and therefore can be sampled flimage aux = alloc_image<float>(image.w/2, image.h/2); if(DEBUG) printf("Sampling initial image \n"); sample(image.data, aux.data, 2.0f, image.w, image.h); free(image.data); image = aux; octSize *= 2.0f; } free(image.data); /* printf("sift:: %d keypoints\n", keys.size()); printf("sift:: plus non correctly localized: %d \n", par.noncorrectlylocalized);*/ }
void gaussian_blur(image* im0, int sigma) { assert(sigma > 0); size_t ww = im0->width; size_t hh = im0->height; int rr = 3 * sigma; /* Generate the blur vector */ double bvec[2 * rr + 1]; double bsum = 0.0; for (int kk = -rr; kk <= rr; ++kk) { int ii = kk + rr; bvec[ii] = gauss(kk, 0.0, sigma); bsum += bvec[ii]; } for (int ii = 0; ii < 2 * rr + 1; ++ii) { bvec[ii] *= 1.0 / bsum; } image* im1 = alloc_image(ww, hh); /* Blur horizontally */ for (int ii = 0; ii < hh; ++ii) { for (int jj = 0; jj < ww; ++jj) { double p1 = 0.0; for (int kk = -rr; kk <= rr; ++kk) { int jj0 = clamp(jj + kk, 0, ww - 1); p1 += bvec[kk + rr] * im0->data[ww*ii + jj0]; } im1->data[ww*ii + jj] = clamp(round(p1), 0, 255); } } /* Blur vertically */ for (int jj = 0; jj < ww; ++jj) { for (int ii = 0; ii < hh; ++ii) { double p0 = 0.0; for (int kk = -rr; kk <= rr; ++kk) { int ii0 = clamp(ii + kk, 0, hh - 1); p0 += bvec[kk + rr] * im1->data[ww*ii0 + jj]; } im0->data[ww*ii + jj] = clamp(round(p0), 0, 255); } } free_image(im1); }
/* read a pnm image */ void read_pnm(char* path, struct image* img) { int fd, bytes_read, bytes_left; char image_type[IMAGE_TYPE_LEN]; unsigned char *ptr; unsigned int max_color; fd = open(path, O_RDONLY); if (fd < 0){ PRINT_ERR_MSG_AND_EXIT("Error opening %s\n", path); exit(1); } /* read image type; should be P6 */ bytes_read = read(fd, image_type, IMAGE_TYPE_LEN); if (bytes_read != IMAGE_TYPE_LEN){ PRINT_ERR_MSG_AND_EXIT("Couldn't read image type for %s\n", path); } if (strncmp(image_type, "P6", IMAGE_TYPE_LEN)){ PRINT_ERR_MSG_AND_EXIT("Expecting P6 image type for %s. Got %s\n", path, image_type); } /* read \n */ read_char(fd, path); /* read width, height and max color value */ img->width = read_until(fd, ' ', path); img->height = read_until(fd, '\n', path); max_color = read_until(fd, '\n', path); if (max_color != MAX_COLOR){ PRINT_ERR_MSG_AND_EXIT("Unsupported max color value %d for %s\n", max_color, path); } /* allocate image data */ alloc_image(img); /* read the actual data */ bytes_left = img->width * img->height * NUM_CHANNELS; ptr = img->data; while (bytes_left > 0){ bytes_read = read(fd, ptr, bytes_left); if (bytes_read <= 0){ PRINT_ERR_MSG_AND_EXIT("Error reading from %s\n", path); } ptr += bytes_read; bytes_left -= bytes_read; } close(fd); }
void load_img(const char *fname) { int i; GLubyte *src, *dst; GLfloat pix, avg; img = read_texture(fname, &w, &h, &comp); if (!img) { fprintf(stderr, "Could not open %s\n", fname); exit(1); } black = alloc_image(); memset(black, 0, w * h * sizeof(GLuint)); lum = alloc_image(); src = (GLubyte *)img; dst = (GLubyte *)lum; avg = 0.; /* compute average luminance at same time that we set luminance image. * note that little care is taken to avoid mathematical error when * computing overall average... */ for (i = 0; i < w * h; i++) { pix = (float)src[0]*RW + (float)src[1]*GW + (float)src[2]*BW; if (pix > 255) pix = 255; dst[0] = dst[1] = dst[2] = pix; avg += pix / 255.; src += 4; dst += 4; } avgLum = alloc_image(); pix = avg * 255. / (float)(w*h); dst = (GLubyte *)avgLum; for (i = 0; i < w * h; i++) { dst[0] = dst[1] = dst[2] = pix; dst += 4; } }
image* read_image(const char* filename) { char* line = alloca(16); size_t size = 16; size_t ww, hh; int cc; int rv; FILE* imf = fopen(filename, "r"); rv = getline(&line, &size, imf); assert(rv != -1); if (!streq(line, "P2\n")) carp("Bad image file; not ASCII PGM"); /* Assume leading comments only */ while ((cc = getc(imf))) { if (cc == '#') { // throw away the line while (getc(imf) != '\n'); } else { ungetc(cc, imf); break; } } rv = fscanf(imf, "%ld", &ww); assert(rv == 1); rv = fscanf(imf, "%ld", &hh); assert(rv == 1); rv = fscanf(imf, "%d", &cc); assert(rv == 1); assert(cc == 255); image* im = alloc_image(ww, hh); for (int ii = 0; ii < ww * hh; ++ii) { rv = fscanf(imf, "%d", &cc); assert(rv == 1); im->data[ii] = (byte) cc; } fclose(imf); return im; }
void fill_borders(rgba_surface* dst, rgba_surface* src, int block_width, int block_height) { int full_width = idiv_ceil(src->width, block_width) * block_width; int full_height = idiv_ceil(src->height, block_height) * block_height; alloc_image(dst, full_width, full_height); for (int y = 0; y < dst->height; y++) for (int x = 0; x < dst->width; x++) { int clipped_y = min(y, src->height - 1); int clipped_x = min(x, src->width - 1); for (int p = 0; p < 3; p++) { int value = src->ptr[src->stride * clipped_y + clipped_x * 4 + p]; dst->ptr[dst->stride * y + x * 4 + p] = value; } } }
static int parse_image(xmlTextReaderPtr reader, tmx_image **img_adr, short strict, const char *filename) { tmx_image *res; char *value; if (!(res = alloc_image())) return 0; *img_adr = res; if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"source"))) { /* source */ res->source = value; if (!(load_image(&(res->resource_image), filename, value))) { tmx_err(E_UNKN, "xml parser: an error occured in the delegated image loading function"); return 0; } } else { tmx_err(E_MISSEL, "xml parser: missing 'source' attribute in the 'image' element"); return 0; } if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"height"))) { /* height */ res->height = atoi(value); tmx_free_func(value); } else if (strict) { tmx_err(E_MISSEL, "xml parser: missing 'height' attribute in the 'image' element"); return 0; } if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"width"))) { /* width */ res->width = atoi(value); tmx_free_func(value); } else if (strict) { tmx_err(E_MISSEL, "xml parser: missing 'width' attribute in the 'image' element"); return 0; } if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"trans"))) { /* trans */ res->trans = get_color_rgb(value); res->uses_trans = 1; tmx_free_func(value); } return 1; }
/* Return an image to use for a sprite. If it's time for a new one, get a new one. Otherwise, use an old one. Might return 0 if the machine is really slow. */ static image * get_image (ModeInfo *mi) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; image *img = 0; double now = ss->now; Bool want_new_p = (ss->change_now_p || ss->image_load_time + image_seconds <= now); image *new_img = 0; image *old_img = 0; image *loading_img = 0; int i; for (i = 0; i < ss->nimages; i++) { image *img2 = ss->images[i]; if (!img2) abort(); if (!img2->loaded_p) loading_img = img2; else if (!img2->used_p) new_img = img2; else old_img = img2; } if (want_new_p && new_img) img = new_img, new_img = 0, ss->change_now_p = False; else if (old_img) img = old_img, old_img = 0; else if (new_img) img = new_img, new_img = 0, ss->change_now_p = False; /* Make sure that there is always one unused image in the pipe. */ if (!new_img && !loading_img) alloc_image (mi); return img; }
image_t * decode_image (unsigned orig_width, unsigned orig_height, format_e format, unsigned *dec_timer, const wfa_t *wfa) /* * Compute image which is represented by the given 'wfa'. * 'orig_width'x'orig_height' gives the resolution of the image at * coding time. Use 4:2:0 subsampling or 4:4:4 'format' for color images. * If 'dec_timer' is given, accumulate running time statistics. * * Return value: * pointer to decoded image * * Side effects: * '*dectimer' is changed if 'dectimer' != NULL. */ { unsigned root_state [3]; /* root of bintree for each band */ unsigned width, height; /* computed image size */ image_t *frame; /* regenerated frame */ word_t **images; /* pointer to array of pointers to state images */ u_word_t *offsets; /* pointer to array of state image offsets */ unsigned max_level; /* max. level of state with approx. */ unsigned state; clock_t ptimer; prg_timer (&ptimer, START); /* * Compute root of bintree for each color band */ if (wfa->wfainfo->color) { root_state [Y] = wfa->tree [wfa->tree [wfa->root_state][0]][0]; root_state [Cb] = wfa->tree [wfa->tree [wfa->root_state][0]][1]; root_state [Cr] = wfa->tree [wfa->tree [wfa->root_state][1]][0]; } else root_state [GRAY] = wfa->root_state; /* * Compute maximum level of a linear combination */ for (max_level = 0, state = wfa->basis_states; state < wfa->states; state++) if (isedge (wfa->into [state][0][0]) || isedge (wfa->into [state][1][0])) max_level = max (max_level, wfa->level_of_state [state]); /* * Allocate frame buffer for decoded image */ compute_actual_size (format == FORMAT_4_2_0 ? root_state [Y] : MAXSTATES, &width, &height, wfa); width = max (width, orig_width); height = max (height, orig_height); frame = alloc_image (width, height, wfa->wfainfo->color, format); /* * Allocate buffers for intermediate state images */ if (wfa->wfainfo->color) { wfa->level_of_state [wfa->root_state] = 128; wfa->level_of_state [wfa->tree[wfa->root_state][0]] = 128; wfa->level_of_state [wfa->tree[wfa->root_state][1]] = 128; } alloc_state_images (&images, &offsets, frame, root_state, 0, max_level, format, wfa); if (dec_timer) dec_timer [0] += prg_timer (&ptimer, STOP); /* * Decode all state images, forming the complete image. */ prg_timer (&ptimer, START); compute_state_images (max_level, images, offsets, wfa); if (dec_timer) dec_timer [1] += prg_timer (&ptimer, STOP); /* * Cleanup buffers used for intermediate state images */ prg_timer (&ptimer, START); free_state_images (max_level, frame->color, images, offsets, root_state, 0, format, wfa); /* * Crop decoded image if the image size differs. */ if (orig_width != width || orig_height != height) { frame->height = orig_height; frame->width = orig_width; if (orig_width != width) { color_e band; /* current color band */ word_t *src, *dst; /* source and destination pointers */ unsigned y; /* current row */ for (band = first_band (frame->color); band <= last_band (frame->color); band++) { src = dst = frame->pixels [band]; for (y = orig_height; y; y--) { memmove (dst, src, orig_width * sizeof (word_t)); dst += orig_width; src += width; } if (format == FORMAT_4_2_0 && band == Y) { orig_width >>= 1; orig_height >>= 1; width >>= 1; } }
/* Does the actual processing of the frame */ static void do_work(ppu_data_t ppu_data) { struct image input; struct image big_image; dprintf("SPU[%d] ppu_data.input:%p ppu_big_img:%p sizeof(struct image):%lu\n", ppu_data.spe_id, (void *)ppu_data.input, (void *)ppu_data.big_image, sizeof(struct image)); /* Get input image and big_image details */ mfc_get((void *)(&input), (uint32_t)(ppu_data.input), (uint32_t)(sizeof(struct image)), tag_id, 0, 0); mfc_get((void *)(&big_image), (uint32_t)(ppu_data.big_image), (uint32_t)(sizeof(struct image)), tag_id, 0, 0); waittag(tag_id); dprintf("SPU[%d] got structs\n"\ "input.width=%u\tinput.height=%u\n"\ "big_image.width=%u\tbig_image.height=%u\n"\ "input.data=%p\tbig_image.data=%p\n", ppu_data.spe_id, input.width, input.height, big_image.width, big_image.height, (void *)input.data, (void *)big_image.data); struct image img_chunk; unsigned int buf_line_sz = input.width * NUM_CHANNELS; int transfer_sz = 4 * buf_line_sz; img_chunk.width = input.width; img_chunk.height = 4; alloc_image(&img_chunk); struct image img_scaled_line; img_scaled_line.width = input.width / SCALE_FACTOR; img_scaled_line.height = 1; /* Hack for memory align of local image data to have the same 4 bits in its * address as the remote corresponding address in PPU */ int left_padding = (ppu_data.spe_id % 4) * 4; unsigned char* addr_to_free = malloc_align(NUM_CHANNELS * 3 * sizeof(char) + left_padding, 4); img_scaled_line.data = addr_to_free + left_padding; unsigned int i; /* Process 4 lines from the initial image at a time */ for (i = 0; i < input.height / img_chunk.height; ++i) { /* Get the image chunk from PPU through DMA transfer */ dprintf("SPU[%d] getting image_chunk %d of size %d\n", ppu_data.spe_id, i, transfer_sz); dprintf("SPU[%d] input.data=%p img_chunk.data=%p "\ "start_addr=%p\n", ppu_data.spe_id, (void *)input.data, (void *)img_chunk.data, (void *)((uint32_t)(input.data) + i * transfer_sz)); mfc_get((void *)(img_chunk.data), (uint32_t)(input.data) + i * transfer_sz, (uint32_t)(transfer_sz), tag_id, 0, 0); waittag(tag_id); dprintf("SPU[%d] got image_chunk %d\n", ppu_data.spe_id, i); compute_lines_average(&img_chunk, buf_line_sz); /* Make average for column. avg = (c0.r + c1.r) / 2 etc*/ compute_columns_average(&img_chunk, &img_scaled_line); store_line(&img_scaled_line, ppu_data, &big_image, i); } free_image(&img_chunk); free_align(addr_to_free); }
/** * Lit un fichier image en niveau de gris au format PGM P5. * et retourne l’image stockée dans le fichier. * L’allocation mémoire est dynamique la zone allouée est contiguë * Seul le format P5 est géré. De plus, la valeur maximale des pixels dans * le fichier doit être 255 (<=> un octet) ou une erreur se produit. * Le commentaire (ligne commençant par ‘#’ dans le fichier) est ignoré. * PARAMETRES : * fileName : nom du fichier PGM à lire * RETOUR : pointeur vers l’IMAGE_T lue, ou NULL en cas d’erreur */ IMAGE_T *read_pgm_file(char *fileName) { FILE *filein; filein = fopen(fileName, "rb"); int nbc, nbl; if (filein == NULL) { fprintf(stderr, "Erreur: impossible d'ouvrir le fichier '%s'\n", fileName); } char line[256]; /*lecture de la première ligne */ if (fgets(line, sizeof(line), filein) != NULL) { if (strcmp(line, "P5\n") != 0) { fprintf(stderr, "Erreur pas un fichier P5"); return NULL; } } /*affichage du commentaire */ if (fgets(line, sizeof(line), filein) != NULL) { printf("Commmentaire: %s", line); } /*Pour récupérer nbc et nbl */ if (fgets(line, sizeof(line), filein) != NULL) { /*calcul du nombre de chiffre de nbc */ int nbc_len = 0; do { nbc_len++; } while (line[nbc_len] != ' '); nbc = atoi(line); nbl = atoi(line + nbc_len); } else { return NULL; } /*on vérifie si la valeur max dépasse pas 255 */ if (fgets(line, sizeof(line), filein) != NULL) { int len = atoi(line); if (len > 255) { fprintf(stderr, "Erreur: sur la valeur max d'un pixel\n"); } } else { return NULL; } IMAGE_T *img; img = alloc_image(nbl, nbc); int nr; nr = fread(*(img->data), sizeof(unsigned char), img->nbc * img->nbl, filein); if (nr != img->nbc * img->nbl) { fprintf(stderr, "Erreur : erreur de lecture du fichier\n"); return NULL; } fclose(filein); return img; }
int main(int argc, char** argv){ int i, j, num_frames; char buf[MAX_PATH_LEN]; char input_path[MAX_PATH_LEN]; char output_path[MAX_PATH_LEN]; struct image input[NUM_STREAMS]; struct image scaled[NUM_STREAMS]; struct image big_image; struct timeval t1, t2, t3, t4; double scale_time = 0, total_time = 0; if (argc != 4){ printf("Usage: ./serial input_path output_path num_frames\n"); exit(1); } gettimeofday(&t3, NULL); strncpy(input_path, argv[1], MAX_PATH_LEN - 1); strncpy(output_path, argv[2], MAX_PATH_LEN - 1); num_frames = atoi(argv[3]); if (num_frames > MAX_FRAMES) num_frames = MAX_FRAMES; for (i = 0; i < num_frames; i++){ printf("Processing Frame %d\n", i + 1); //read the input images for (j = 0; j < NUM_STREAMS; j++){ sprintf(buf, "%s/stream%02d/image%d.pnm", input_path, j + 1, i + 1); read_pnm(buf, &input[j]); } gettimeofday(&t1, NULL); //scale the input images for (j = 0; j < NUM_STREAMS; j++){ scaled[j].height = input[j].height / SCALE_FACTOR; scaled[j].width = input[j].width / SCALE_FACTOR; alloc_image(&scaled[j]); scale_area_avg(&input[j], &scaled[j]); } //create the big image out of the scaled images big_image.height = scaled[0].height * NUM_IMAGES_HEIGHT; big_image.width = scaled[0].width * NUM_IMAGES_WIDTH; alloc_image(&big_image); create_big_image(scaled, &big_image); gettimeofday(&t2, NULL); scale_time += GET_TIME_DELTA(t1, t2); //write the big image sprintf(buf, "%s/result%d.pnm", output_path, i + 1); write_pnm(buf, &big_image); //free the image data for (j = 0; j < NUM_STREAMS; j++){ free_image(&input[j]); free_image(&scaled[j]); } free_image(&big_image); } gettimeofday(&t4, NULL); total_time += GET_TIME_DELTA(t3, t4); printf("Scale time: %lf\n", scale_time); printf("Total time: %lf\n", total_time); return 0; }
/// Apply geometric transform to image. /// /// The transformation \a map is applied to the image \a in and the result /// stored in \a im. If \a adjustSize is \c true, \a im will be sized so that /// it contains all the transformed rectangle, otherwise it stays at original /// size. /// /// The returned pair of integers is the offset of the returned image \a im /// with respect to original image \a in. If \a adjustSize is \c false, this is /// (0,0), otherwise the location of upper-left corner of \a im in pixel /// coordinates of \a in. /// /// Interpolation is done by spline. Anti-aliasing filter is optional. /// /// \a vOut is the background value to put at pixels outside image. std::pair<int,int> map_image(LWImage<float> in, libNumerics::Homography map, LWImage<float>& im, int order, bool adjustSize, bool antiAlias, float vOut) { int w = in.w, h = in.h; float zoomOut = antiAlias? static_cast<float>( minZoomOut(map.mat(), w, h) ): 1.0f; const libNumerics::Homography oriMap(map); const int oriW=w, oriH=h; std::pair<int,int> offset(0,0); if(adjustSize) { offset = boundingBox(map, w, h); free(im.data); im = alloc_image<float>(w, h, in.comps); } if(zoomOut < 1.0f) { float zoomIn = 1.0f / zoomOut; // GF: added some extra space int wZoom=(int)std::ceil(w*zoomIn*1.5), hZoom=(int)std::ceil(h*zoomIn*1.5); LWImage<float> imZoom = alloc_image<float>(wZoom,hZoom,in.comps); libNumerics::matrix<double> mapZ(3,3); mapZ = 0.0; mapZ(0,0) = zoomIn; mapZ(1,1) = zoomIn; mapZ(2,2) = 1.0; map.mat() = mapZ*map.mat(); map_image(in, map, imZoom, order, false, false, vOut); float sigma = 0.8f*sqrt(zoomIn*zoomIn-1.0f); gauss_convol(imZoom, sigma); map.mat() = 0.0; map.mat()(0,0)=zoomOut; map.mat()(1,1)=zoomOut; map.mat()(2,2)=1.0; in = imZoom; } LWImage<float> tmp = alloc_image(in); if( prepare_spline(tmp,order) ) { libNumerics::Homography inv = map.inverse(); const int stepComp = im.stepComp(); float* out = new float[im.comps]; float* pixOut = im.data; for(int i = 0; i < im.h; i++) for(int j = 0; j < im.w; j++) { double x=j+offset.first, y=i+offset.second; inv(x,y); for(int k=0; k < im.comps; k++) out[k] = vOut; interpolate_spline(tmp, order, static_cast<float>(x+.5), static_cast<float>(y+.5), out); for(int k=0; k < im.comps; k++) pixOut[k*stepComp] = out[k]; pixOut += im.step(); } delete [] out; } free(tmp.data); if(zoomOut < 1.0f) { free(in.data); // Was allocated above if(! is_number(vOut)) { // Put back mask libNumerics::Homography inv = oriMap.inverse(); const int stepComp = im.stepComp(); float* pixOut = im.data; for(int i = 0; i < im.h; i++) for(int j = 0; j < im.w; j++) { double x=j+offset.first, y=i+offset.second; inv(x,y); if(x<0 || x>=oriW || y<0 || y>=oriH) for(int k=0; k < im.comps; k++) pixOut[k*stepComp] = NaN; pixOut += im.step(); } } } return offset; }