void accumulator_transform(Accumulator *accumulator, Image **frame) { int height = (*frame)->height; int width = (*frame)->width; int n_channels = (*frame)->n_channels; int n_elements = height * width * n_channels; if (!accumulator->frame) { accumulator->frame = image_create(height, width, n_channels); for (int i = 0; i < n_elements; ++i) accumulator->frame->data[i] = 0.0f; } float *outputs = accumulator->frame->data; float *inputs = (*frame)->data; for (int i = 0; i < n_elements; ++i) { float input = inputs[i] >= ACCUMULATOR_THRESHOLD ? inputs[i] : 0.0f; outputs[i] = fmin(1.0, ACCUMULATOR_DECAY * outputs[i] + input); } image_release(*frame); image_acquire(accumulator->frame); *frame = accumulator->frame; }
void jpeg_info_clear(jpeginfo_t *ji) { if(ji->ji_thumbnail != NULL) image_release(ji->ji_thumbnail); rstr_release(ji->ji_manufacturer); rstr_release(ji->ji_equipment); }
void motion_sensor_release(MotionSensor *sensor) { if (sensor) sensor->n_refs--; if (sensor && !sensor->n_refs) { image_release(sensor->last_frame); free(sensor); } }
void accumulator_release(Accumulator *accumulator) { if (accumulator) accumulator->n_refs--; if (accumulator && !accumulator->n_refs) { image_release(accumulator->frame); free(accumulator); } }
static void prune_image_cache_item(loading_image_t *li) { num_cached_images--; TAILQ_REMOVE(&cached_images, li, li_cache_link); image_release(li->li_image); LIST_REMOVE(li, li_link); free(li); }
void motion_sensor_transform(MotionSensor *sensor, Image **frame) { int height = (*frame)->height; int width = (*frame)->width; int n_channels = (*frame)->n_channels; int n_elements = height * width * n_channels; Image *result = image_create(height, width, n_channels); if (sensor->last_frame) for (int i = 0; i < n_elements; ++i) result->data[i] = fabsf((*frame)->data[i] - sensor->last_frame->data[i]); else for (int i = 0; i < n_elements; ++i) result->data[i] = 0.0f; image_release(sensor->last_frame); sensor->last_frame = *frame; *frame = result; }
static void glw_text_bitmap_dtor(glw_t *w) { glw_text_bitmap_t *gtb = (void *)w; glw_root_t *gr = w->glw_root; free(gtb->gtb_description); free(gtb->gtb_caption); free(gtb->gtb_uc_buffer); rstr_release(gtb->gtb_font); image_release(gtb->gtb_image); LIST_REMOVE(gtb, gtb_global_link); glw_tex_destroy(w->glw_root, >b->gtb_texture); glw_renderer_free(>b->gtb_text_renderer); glw_renderer_free(>b->gtb_cursor_renderer); glw_renderer_free(>b->gtb_background_renderer); switch(gtb->gtb_state) { case GTB_IDLE: case GTB_DIMENSIONING: case GTB_NEED_RENDER: case GTB_RENDERING: case GTB_VALID: break; case GTB_QUEUED_FOR_DIMENSIONING: TAILQ_REMOVE(&gr->gr_gtb_dim_queue, gtb, gtb_workq_link); break; case GTB_QUEUED_FOR_RENDERING: TAILQ_REMOVE(&gr->gr_gtb_render_queue, gtb, gtb_workq_link); break; } }
static int hc_image(http_connection_t *hc, const char *remain, void *opaque, http_cmd_t method) { htsbuf_queue_t out; image_t *img; char errbuf[200]; const char *content; image_meta_t im = {0}; im.im_no_decoding = 1; rstr_t *url; const char *u = http_arg_get_req(hc, "url"); if(u != NULL) { url = rstr_alloc(u); url_deescape(rstr_data(url)); } else { if(remain == NULL) { return 404; } url = rstr_alloc(remain); } img = backend_imageloader(url, &im, NULL, errbuf, sizeof(errbuf), NULL, NULL); rstr_release(url); if(img == NULL) return http_error(hc, 404, "Unable to load image %s : %s", remain, errbuf); const image_component_t *ic = image_find_component(img, IMAGE_CODED); if(ic == NULL) { image_release(img); return http_error(hc, 404, "Unable to load image %s : Original data not available", remain); } const image_component_coded_t *icc = &ic->coded; htsbuf_queue_init(&out, 0); htsbuf_append(&out, buf_cstr(icc->icc_buf), buf_len(icc->icc_buf)); switch(icc->icc_type) { case IMAGE_JPEG: content = "image/jpeg"; break; case IMAGE_PNG: content = "image/png"; break; case IMAGE_GIF: content = "image/gif"; break; default: content = "image"; break; } image_release(img); return http_send_reply(hc, 0, content, NULL, NULL, 0, &out); }
// PNG 8/24/32 bits my_image *loadPNG(boost::filesystem::path & aPath, int nbytes, bool for_bmp, bool inverse) { if ( nbytes != 0 && nbytes != 1 && nbytes != 3 && nbytes != 4 ) return NULL; FILE *fp; fopen_s(&fp, aPath.file_string().data(), "rb"); if (!fp) return NULL; // read header char header[8]; fread(header, 1, 8, fp); if (png_sig_cmp((png_bytep)header, 0, 8)) { // not a PNG file fclose(fp); return NULL; } // create and initialize the png_struct png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fclose(fp); return NULL; } // allocate the memory for image information png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); fclose(fp); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { // free all of the memory associated with the png_ptr and info_ptr png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); return NULL; } // set up the input control (use standard C streams) png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); // read information from the PNG file png_read_info(png_ptr, info_ptr); // bytes per pixel in stored image int samples; png_byte color_type = info_ptr->color_type; png_byte bit_depth = info_ptr->bit_depth; // interlacing temporary not supported if ( info_ptr->interlace_type != PNG_INTERLACE_NONE ) { png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); return NULL; } //strip 16 bit/color files down to 8 bits/color if (bit_depth == 16) png_set_strip_16(png_ptr); // expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); // expand paletted colors into true RGB triplets if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); switch (color_type) { case PNG_COLOR_TYPE_GRAY: samples = 1; break; case PNG_COLOR_TYPE_PALETTE: color_type = PNG_COLOR_TYPE_RGB; samples = 3; break; case PNG_COLOR_TYPE_RGB: samples = 3; break; case PNG_COLOR_TYPE_RGBA: case PNG_COLOR_TYPE_GRAY_ALPHA: samples = 4; break; default: // unknown color type png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); return NULL; break; } if (nbytes == 0) nbytes = samples; if (nbytes == 1) { // convert an RGB or RGBA image to grayscale or grayscale with alpha if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_rgb_to_gray_fixed(png_ptr, 1, 21268, 71514); // strip alpha bytes if (color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png_ptr); } if (nbytes == 3) { // convert a grayscale image to RGB if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); // strip alpha bytes if (color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png_ptr); } if (nbytes == 4) { // convert a grayscale image to RGB if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); // add alpha bytes if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) png_set_add_alpha(png_ptr, 255, PNG_FILLER_AFTER); } // call to update the users info_ptr structure png_read_update_info(png_ptr, info_ptr); // allocate memory for one row png_byte *row_pointer = (png_byte*) malloc(info_ptr->rowbytes); // create new image my_image *image = image_create(info_ptr->width, info_ptr->height, nbytes, for_bmp); // can't allocate memory if ( !image || !row_pointer ) { png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); if (row_pointer) free(row_pointer); if (image) image_release(image); return NULL; } // length of row in new image int rowlen = image->width * image->nbytes; int height = image->height; int step = image->step; UCHAR *dst = image->data; if (inverse) { dst = image->data + (height - 1) * step; step = -step; } // TODO: add interlacing support // //turn on interlace handling //int number_of_passes = png_set_interlace_handling(png_ptr); // //for interlaced image (temporary, not so good !!! ) //for (int pass = 0; pass < number_of_passes - 1; pass++) // for (j = 0; j < height; j++) // png_read_rows(png_ptr, &row_pointer, png_bytepp_NULL, 1); for (int j = 0; j < height; j++) { png_read_rows(png_ptr, &row_pointer, png_bytepp_NULL, 1); memcpy(dst, (UCHAR*)row_pointer, rowlen); dst += step; } if (row_pointer) free(row_pointer); // read rest of file, and get additional chunks in info_ptr png_read_end(png_ptr, info_ptr); // clean up after the read, and free any memory allocated png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); return image; }
image_t * fa_imageloader(const char *url, const struct image_meta *im, const char **vpaths, char *errbuf, size_t errlen, int *cache_control, cancellable_t *c) { uint8_t p[16]; int r; int width = -1, height = -1, orientation = 0; fa_handle_t *fh; image_t *img; image_coded_type_t fmt; #if ENABLE_LIBAV if(strchr(url, '#')) return fa_image_from_video(url, im, errbuf, errlen, cache_control, c); #endif if(!im->im_want_thumb) return fa_imageloader2(url, vpaths, errbuf, errlen, cache_control, c); fa_open_extra_t foe = { .foe_cancellable = c }; if((fh = fa_open_vpaths(url, vpaths, errbuf, errlen, FA_BUFFERED_SMALL, &foe)) == NULL) return NULL; if(ONLY_CACHED(cache_control)) { snprintf(errbuf, errlen, "Not cached"); return NULL; } if(fa_read(fh, p, sizeof(p)) != sizeof(p)) { snprintf(errbuf, errlen, "File too short"); fa_close(fh); return NULL; } /* Probe format */ if(p[0] == 0xff && p[1] == 0xd8 && p[2] == 0xff) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_reader, fh, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION | (im->im_want_thumb ? JPEG_INFO_THUMBNAIL : 0), p, sizeof(p), errbuf, errlen)) { fa_close(fh); return NULL; } if(im->im_want_thumb && ji.ji_thumbnail) { image_t *im = image_retain(ji.ji_thumbnail); fa_close(fh); jpeg_info_clear(&ji); im->im_flags |= IMAGE_ADAPTED; return im; } fmt = IMAGE_JPEG; width = ji.ji_width; height = ji.ji_height; orientation = ji.ji_orientation; jpeg_info_clear(&ji); } else if(!memcmp(pngsig, p, 8)) { fmt = IMAGE_PNG; } else if(!memcmp(gif87sig, p, sizeof(gif87sig)) || !memcmp(gif89sig, p, sizeof(gif89sig))) { fmt = IMAGE_GIF; } else if(p[0] == 'B' && p[1] == 'M') { fmt = IMAGE_BMP; } else if(!memcmp(svgsig1, p, sizeof(svgsig1)) || !memcmp(svgsig2, p, sizeof(svgsig2))) { fmt = IMAGE_SVG; } else { snprintf(errbuf, errlen, "Unknown format"); fa_close(fh); return NULL; } int64_t s = fa_fsize(fh); if(s < 0) { snprintf(errbuf, errlen, "Can't read from non-seekable file"); fa_close(fh); return NULL; } void *ptr; img = image_coded_alloc(&ptr, s, fmt); if(img == NULL) { snprintf(errbuf, errlen, "Out of memory"); fa_close(fh); return NULL; } img->im_width = width; img->im_height = height; img->im_orientation = orientation; fa_seek(fh, SEEK_SET, 0); r = fa_read(fh, ptr, s); fa_close(fh); if(r != s) { image_release(img); snprintf(errbuf, errlen, "Read error"); return NULL; } return img; }
// BMP 8/24 bits my_image *loadBMP(boost::filesystem::path & aPath, int nbytes, bool inverse) { if ( nbytes != 0 && nbytes != 1 && nbytes != 3 ) return NULL; FILE *fp; fopen_s(&fp, aPath.file_string().data(), "rb"); if (!fp) return NULL; BITMAPINFO *pbmi = (BITMAPINFO*)malloc(sizeof(BITMAPINFOHEADER) + 256*4); if (!pbmi) { fclose(fp); return NULL; } fseek(fp, sizeof(BITMAPFILEHEADER), SEEK_SET); fread(&pbmi->bmiHeader, 1, sizeof(BITMAPINFOHEADER), fp); // кол-во байтов на пиксель в открываемом изображении int samples = pbmi->bmiHeader.biBitCount / 8; if (nbytes == 0) nbytes = samples; // читаем только 8 и 24-битные изображения if (samples != 1 && samples != 3) { fclose(fp); if (pbmi) free(pbmi); return NULL; } if (samples == 1) fread(pbmi->bmiColors, 256 * 4, 1, fp); int width = pbmi->bmiHeader.biWidth; int height = pbmi->bmiHeader.biHeight; // создаём новое изображение my_image *image = image_create(width, height, nbytes); if (!image) { fclose(fp); if (pbmi) free(pbmi); return NULL; } // длина строки в открываемом и новом изображениях int buflen = ((width * samples + 3)/4)*4; int step = image->step; //int rowlen = width * nbytes; // флаг: прочитать файл за раз или читать построчно bool read_once = true; // TODO: можно добавить проверку наличия свободной памяти, // а пока так: смогли выделить сразу - хорошо, не смогли - читаем построчно // выделяем память под буфер UCHAR *buf; if (read_once) { buf = (UCHAR*)malloc(buflen * height); if (!buf) { // не получилось выделить память read_once = false; } else { // читаем весь файл fread(buf, buflen, height, fp); fclose(fp); } } // будем читать построчно if (!read_once) buf = (UCHAR*)malloc(buflen); // не получилось выделить память, выходим if ( !buf ) { fclose(fp); if (pbmi) free(pbmi); image_release(image); return NULL; } int i, j, gray, num; UCHAR *src = buf; UCHAR *dst = image->data; if (!inverse) { dst = image->data + (height - 1) * step; step = -step; } if (nbytes == 3) { if (read_once) { if (samples == 1) { for (j = 0; j < height; j++) { num = 0; for (i = 0; i < width; i++) { RGBQUAD *sp = pbmi->bmiColors + src[i]; RGBTRIPLE *t = (RGBTRIPLE*)(dst + num); t->rgbtRed = sp->rgbBlue; t->rgbtGreen = sp->rgbGreen; t->rgbtBlue = sp->rgbRed; num += 3; } dst += step; src += buflen; } } else if (samples == 3) { num = 3 * width; for (j = 0; j < height; j++) { for (i = 0; i < num; i += 3) { dst[i + 0] = src[i + 2]; dst[i + 1] = src[i + 1]; dst[i + 2] = src[i + 0]; } //memcpy(dst, buf, abs(rowlen)); dst += step; src += buflen; } } } else { if (samples == 1) { for (j = 0; j < height; j++) { num = 0; fread(buf, buflen, 1, fp); for (i = 0; i < width; i++) { RGBQUAD *sp = pbmi->bmiColors + buf[i]; RGBTRIPLE *t = (RGBTRIPLE*)(dst + num); t->rgbtRed = sp->rgbBlue; t->rgbtGreen = sp->rgbGreen; t->rgbtBlue = sp->rgbRed; num += 3; } dst += step; } } else if (samples == 3) { num = 3 * width; for (j = 0; j < height; j++) { fread(buf, buflen, 1, fp); for (i = 0; i < num; i += 3) { dst[i + 0] = buf[i + 2]; dst[i + 1] = buf[i + 1]; dst[i + 2] = buf[i + 0]; } //memcpy(dst, buf, abs(rowlen)); dst += step; } } } } if (nbytes == 1) { if (read_once) { if (samples == 1) { for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { RGBQUAD *quad = pbmi->bmiColors + src[i]; gray = 218 * quad->rgbRed + 732 * quad->rgbGreen + 74 * quad->rgbBlue; dst[i] = gray >> 10; } dst += step; src += buflen; } } else if (samples == 3) { for (j = 0; j < height; j++) { num = 0; for (i = 0; i < width; i++) { RGBTRIPLE *triple = (RGBTRIPLE*)(src + num); gray = 218 * triple->rgbtRed + 732 * triple->rgbtGreen + 74 * triple->rgbtBlue; dst[i] = gray >> 10; num += 3; } dst += step; src += buflen; } } } else { if (samples == 1) {
void image_atlas_release(atlas_t* atlas) { image_release(atlas->baked_image); free(atlas->coordinates); free(atlas); }