static int grab_command(shell_t *shell, shell_argv_t *cmd_argv, char *tag) { int argc = cmd_argv->argc; char **argv = cmd_argv->argv; char *hdr = log_hdr_(tag); int ret = -1; /* Set error reporting tag */ error_default_tag(tag); /* The 'stop' qualifier */ if ( (argc > 1) && (strcmp(argv[1], "stop") == 0) ) { /* Check number of arguments */ if ( check_argc(shell, cmd_argv, tag, 2, 2) ) return -1; grab_end = 0; if ( grab_n > 0 ) { printf("%s%d frames recorded\n", hdr, grab_n); grab_n = 0; } else { printf("%sNo recording in progress\n", hdr); } ret = 0; } /* Unknown qualifier */ else { frame_t *frame = grab_display->root; char *window_str = NULL; frame_geometry_t window; char *fname = NULL; int grab_animation = 0; long grab_dt = 0; int n; /* Check number of arguments */ if ( check_argc(shell, cmd_argv, tag, 1, 4) ) return -1; for (n = 1; n < argc; n++) { char *str = argv[n]; char *eq = strchr(str, '='); if ( eq != NULL ) { *(eq++) = '\0'; if ( strcmp(str, "frame") == 0 ) { frame = frame_get_child_by_id(grab_display->root, eq); if ( frame == NULL ) { error(NULL, "Unknown frame '%s'", eq); return -1; } } else if ( strcmp(str, "window") == 0 ) { window_str = eq; } else if ( strcmp(str, "t") == 0 ) { grab_begin = (tstamp_get() / 1000); grab_end = 0; grab_n = 0; grab_dt = (atoi(eq) * 1000); if ( grab_dt < 0 ) grab_dt = 0; grab_end = grab_begin + grab_dt; grab_animation = 1; } else { error(tag, "Illegal qualifier '%s'", str); return -1; } } else { fname = str; } } /* Set source frame */ if ( window_str != NULL ) { if ( frame_rgb_parse_geometry(&(frame->hdr.fb->rgb), window_str, &window) ) { error(NULL, "Syntax error in window geometry"); return -1; } } else { window = frame->g; window.x = 0; window.y = 0; } /* Retrieve output format */ grab_ppm = (ppm_filename_suffix(fname) != NULL); /* Construct an image file name */ fname = grab_ppm ? ppm_filename(fname) : png_filename(fname); if ( fname == NULL ) { error(tag, "Failed to construct a valid image file name"); return -1; } if ( grab_animation ) { char *suffix_str; char *suffix; if ( grab_ppm ) { suffix_str = PPM_SUFFIX; suffix = ppm_filename_suffix(fname); } else { suffix_str = PNG_SUFFIX; suffix = png_filename_suffix(fname); } if ( suffix != NULL ) *suffix = '\0'; grab_fname_size = strlen(fname) + 16; if ( grab_fname_fmt != NULL ) free(grab_fname_fmt); grab_fname_fmt = (char *) malloc(grab_fname_size); snprintf(grab_fname_fmt, grab_fname_size, "%s.%%09lu%s", fname, suffix_str); grab_frame = frame; grab_window = window; ret = grab_save(0); if ( ret == 0 ) { printf("%sframe=%s window=%s t=%ld %s.*%s\n", hdr, frame->hdr.id, frame_geometry_str(&window), grab_dt / 1000, fname, suffix_str); } else { printf("%sFailed to write image file '%s'", hdr, grab_fname); grab_end = 0; } } else { if ( grab_ppm ) ret = ppm_save(&(frame->hdr.fb->rgb), &window, fname); else ret = png_save(&(frame->hdr.fb->rgb), &window, fname); if ( ret == 0 ) printf("%sframe=%s window=%s %s\n", hdr, frame->hdr.id, frame_geometry_str(&window), fname); else printf("%sFailed to write image file '%s'", hdr, fname); } free(fname); } return ret; }
int png_save_vidframe(const struct vidframe *vf, const char *path) { png_byte **png_row_pointers = NULL; png_byte *row; const png_byte *p; png_byte red, green, blue; png_structp png_ptr = NULL; png_infop info_ptr = NULL; FILE *fp = NULL; size_t x, y; unsigned int width = vf->size.w & ~1; unsigned int height = vf->size.h & ~1; unsigned int bytes_per_pixel = 3; /* RGB format */ time_t tnow; struct tm *tmx; char filename_buf[64]; struct vidframe *f2 = NULL; int err = 0; tnow = time(NULL); tmx = localtime(&tnow); if (vf->fmt != VID_FMT_RGB32) { err = vidframe_alloc(&f2, VID_FMT_RGB32, &vf->size); if (err) goto out; vidconv(f2, vf, NULL); vf = f2; } /* Initialize the write struct. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { err = ENOMEM; goto out; } /* Initialize the info struct. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { err = ENOMEM; goto out; } /* Set up error handling. */ if (setjmp(png_jmpbuf(png_ptr))) { err = ENOMEM; goto out; } /* Set image attributes. */ png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Initialize rows of PNG * bytes_per_row = width * bytes_per_pixel; */ png_row_pointers = png_malloc(png_ptr, height * sizeof(png_byte *)); for (y = 0; y < height; ++y) { png_row_pointers[y] = (png_byte *) png_malloc(png_ptr, width * sizeof(uint8_t) * bytes_per_pixel); } p = vf->data[0]; for (y = 0; y < height; ++y) { row = png_row_pointers[y]; for (x = 0; x < width; ++x) { red = *p++; green = *p++; blue = *p++; *row++ = blue; *row++ = green; *row++ = red; ++p; /* skip alpha */ } } /* Write the image data. */ fp = fopen(png_filename(tmx, path, filename_buf, sizeof(filename_buf)), "wb"); if (fp == NULL) { err = errno; goto out; } png_init_io(png_ptr, fp); png_set_rows(png_ptr, info_ptr, png_row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); info("png: wrote %s\n", filename_buf); out: /* Finish writing. */ mem_deref(f2); png_save_free(png_ptr, png_row_pointers, height); png_destroy_write_struct(&png_ptr, &info_ptr); if (fp) fclose(fp); return 0; }