📄 pnmtoy4m.c
字号:
uint8_t *A = buffers[3]; for (y = 0; y < height; y++) { pixels = rowbuffer; y4m_read(fd, pixels, width * 4); if (!bgra) { for (x = 0; x < width; x++) { *(R++) = *(pixels++); *(G++) = *(pixels++); *(B++) = *(pixels++); *(A++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(B++) = *(pixels++); *(G++) = *(pixels++); *(R++) = *(pixels++); *(A++) = *(pixels++); } } }}staticvoid read_ppm_raw(int fd, uint8_t *buffers[], uint8_t *rowbuffer, int width, int height, int bgr) { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; for (y = 0; y < height; y++) { pixels = rowbuffer; y4m_read(fd, pixels, width * 3); if (!bgr) { for (x = 0; x < width; x++) { *(R++) = *(pixels++); *(G++) = *(pixels++); *(B++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(B++) = *(pixels++); *(G++) = *(pixels++); *(R++) = *(pixels++); } } }}staticvoid read_pgm_raw(int fd, uint8_t *buffer, int width, int height) { mjpeg_debug("read PGM into one buffer, %dx%d", width, height); y4m_read(fd, buffer, width * height);}#define Y_BLACK 16#define Y_WHITE 219/* 000000000011111111112222222222 012345678901234567890123456789 76543210765432107654321076543210*/staticvoid read_pbm_raw(int fd, uint8_t *buffer, int width, int height) { int row_bytes = (width + 7) >> 3; int total_bytes = row_bytes * height; uint8_t *pbm = buffer + total_bytes - 1; uint8_t *luma = buffer + (width * height) - 1; int x, y; mjpeg_debug("read PBM into one buffer, %dx%d", width, height); y4m_read(fd, buffer, total_bytes); for (y = height - 1; y >= 0; y--) { for (x = width - 1; x >= 0; ) { int shift = 7 - (x % 8); uint8_t bits = *(pbm--) >> shift; while (shift < 8) { *(luma--) = (bits & 0x1) ? Y_BLACK : Y_WHITE; bits >>= 1; shift++; x--; } } }}staticvoid read_pnm_data(int fd, uint8_t *planes[], uint8_t *rowbuffer, pnm_info_t *pnm, int bgr){ switch (pnm->format) { case FMT_PPM_RAW: read_ppm_raw(fd, planes, rowbuffer, pnm->width, pnm->height, bgr); break; case FMT_PGM_RAW: read_pgm_raw(fd, planes[0], pnm->width, pnm->height); break; case FMT_PBM_RAW: read_pbm_raw(fd, planes[0], pnm->width, pnm->height); break; case FMT_PAM: switch (pnm->tupl) { case TUPL_RGB: read_ppm_raw(fd, planes, rowbuffer, pnm->width, pnm->height, bgr); break; case TUPL_GRAY: read_pgm_raw(fd, planes[0], pnm->width, pnm->height); break; case TUPL_RGB_ALPHA: read_rgba_raw(fd, planes, rowbuffer, pnm->width, pnm->height, bgr); break; case TUPL_GRAY_ALPHA: case TUPL_BW: case TUPL_BW_ALPHA: case TUPL_UNKNOWN: mjpeg_error_exit1("Unknown/unhandled PAM tuple/format."); break; } break; case FMT_PBM_PLAIN: case FMT_PGM_PLAIN: case FMT_PPM_PLAIN: case FMT_UNKNOWN: mjpeg_error_exit1("Unknown/unhandled PNM format."); break; }}/* * Read one whole frame. * * If non-interleaved fields, this requires reading two PNM images. * */staticint read_pnm_frame(int fd, pnm_info_t *pnm, uint8_t *buffers[], uint8_t *buffers2[], int de_leaved, int bgr){ static uint8_t *rowbuffer = NULL; pnm_info_t new_pnm; int err; err = read_pnm_header(fd, &new_pnm); //&format, &width, &height); if (err > 0) return 1; /* EOF */ if (err < 0) return -1; /* error */ mjpeg_debug("Got PNM header: [%s%s%s] %dx%d", magics[new_pnm.format], (new_pnm.format == FMT_PAM) ? " " : "", (new_pnm.format == FMT_PAM) ? tupls[new_pnm.tupl].tag : "", new_pnm.width, new_pnm.height); if (pnm->width == 0) { /* first time */ mjpeg_debug("Initializing PNM read_frame"); pnm_info_copy(pnm, &new_pnm); rowbuffer = malloc(new_pnm.width * new_pnm.depth * sizeof(rowbuffer[0])); } else { /* make sure everything matches */ if ( !pnm_info_equal(pnm, &new_pnm) ) mjpeg_error_exit1("One of these frames is not like the others!"); } if (buffers[0] == NULL) alloc_buffers(buffers, new_pnm.width, new_pnm.height, new_pnm.depth); if ((buffers2[0] == NULL) && (de_leaved)) alloc_buffers(buffers2, new_pnm.width, new_pnm.height, new_pnm.depth); /* Interleaved or not --> read image into first buffer... */ read_pnm_data(fd, buffers, rowbuffer, pnm, bgr); if (de_leaved) { /* Really Non-Interleaved: --> read second field into second buffer */ err = read_pnm_header(fd, &new_pnm); //&format, &width, &height); if (err > 0) return 1; /* EOF */ if (err < 0) return -1; /* error */ mjpeg_debug("Got second PNM header: [%s] %dx%d", magics[new_pnm.format], new_pnm.width, new_pnm.height); /* make sure everything matches */ if ( !pnm_info_equal(pnm, &new_pnm) ) mjpeg_error_exit1("One of these fields is not like the others!"); read_pnm_data(fd, buffers2, rowbuffer, pnm, bgr); } return 0;}staticvoid setup_output_stream(int fdout, cl_info_t *cl, y4m_stream_info_t *sinfo, pnm_info_t *pnm, int *field_height) { int err; int ss_mode = Y4M_UNKNOWN; if ( (cl->output_interlace != Y4M_ILACE_NONE) && (!cl->deinterleave) && ((pnm->height % 2) != 0) ) mjpeg_error_exit1("Frame height (%d) is not a multiple of 2!", pnm->height); y4m_si_set_width(sinfo, pnm->width); if (cl->deinterleave) y4m_si_set_height(sinfo, pnm->height * 2); else y4m_si_set_height(sinfo, pnm->height); y4m_si_set_sampleaspect(sinfo, cl->output_aspect); y4m_si_set_interlace(sinfo, cl->output_interlace); y4m_si_set_framerate(sinfo, cl->output_framerate); switch (pnm->format) { case FMT_PPM_RAW: case FMT_PPM_PLAIN: ss_mode = Y4M_CHROMA_444; break; case FMT_PGM_RAW: case FMT_PGM_PLAIN: case FMT_PBM_RAW: case FMT_PBM_PLAIN: ss_mode = Y4M_CHROMA_MONO; break; case FMT_PAM: switch (pnm->tupl) { case TUPL_RGB: ss_mode = Y4M_CHROMA_444; break; case TUPL_GRAY: ss_mode = Y4M_CHROMA_MONO; break; case TUPL_RGB_ALPHA: ss_mode = Y4M_CHROMA_444ALPHA; break; case TUPL_GRAY_ALPHA: case TUPL_BW: case TUPL_BW_ALPHA: case TUPL_UNKNOWN: assert(0); break; } break; case FMT_UNKNOWN: assert(0); break; } y4m_si_set_chroma(sinfo, ss_mode); if ((err = y4m_write_stream_header(fdout, sinfo)) != Y4M_OK) mjpeg_error_exit1("Write header failed: %s", y4m_strerr(err)); mjpeg_info("Output Stream parameters:"); y4m_log_stream_info(LOG_INFO, " ", sinfo);}int main(int argc, char **argv){ cl_info_t cl; y4m_stream_info_t sinfo; y4m_frame_info_t finfo; uint8_t *planes[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ uint8_t *planes2[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ pnm_info_t pnm; int field_height; int fdout = 1; /* stdout */ int err, i, count, repeating_last; y4m_accept_extensions(1); y4m_init_stream_info(&sinfo); y4m_init_frame_info(&finfo); parse_args(&cl, argc, argv); pnm.width = 0; pnm.height = 0; for (i = 0; i < Y4M_MAX_NUM_PLANES; i++) { planes[i] = NULL; planes2[i] = NULL; } /* Read first PPM frame/field-pair, to get dimensions/format. */ if (read_pnm_frame(cl.fdin, &pnm, planes, planes2, cl.deinterleave, cl.bgr)) mjpeg_error_exit1("Failed to read first frame."); /* Setup streaminfo and write output header */ setup_output_stream(fdout, &cl, &sinfo, &pnm, &field_height); /* Loop 'framecount' times, or possibly forever... */ for (count = 0, repeating_last = 0; (count < (cl.offset + cl.framecount)) || (cl.framecount == 0); count++) { if (repeating_last) goto WRITE_FRAME; /* Read PPM frame/field */ /* ...but skip reading very first frame, already read prior to loop */ if (count > 0) { err = read_pnm_frame(cl.fdin, &pnm, planes, planes2, cl.deinterleave, cl.bgr); if (err == 1) { /* clean input EOF */ if (cl.repeatlast) { repeating_last = 1; goto WRITE_FRAME; } else if (cl.framecount != 0) { mjpeg_error_exit1("Input frame shortfall (only %d converted).", count - cl.offset); } else { break; /* input is exhausted; we are done! time to go home! */ } } else if (err) mjpeg_error_exit1("Error reading pnm frame"); } /* ...skip transforms if we are just going to skip this frame anyway. BUT, if 'cl.repeatlast' is on, we must process/buffer every frame, because we don't know when we will see the last one. */ if ((count >= cl.offset) || (cl.repeatlast)) { /* Transform colorspace. */ switch (pnm.format) { case FMT_PPM_PLAIN: case FMT_PPM_RAW: convert_RGB_to_YCbCr(planes, pnm.width * pnm.height); if (cl.deinterleave) convert_RGB_to_YCbCr(planes2, pnm.width * pnm.height); break; case FMT_PGM_PLAIN: case FMT_PGM_RAW: convert_Y255_to_Y219(planes[0], pnm.width * pnm.height); if (cl.deinterleave) convert_Y255_to_Y219(planes2[0], pnm.width * pnm.height); break; case FMT_PBM_PLAIN: case FMT_PBM_RAW: /* all set. (converted at read time) */ break; case FMT_PAM: switch (pnm.tupl) { case TUPL_RGB: convert_RGB_to_YCbCr(planes, pnm.width * pnm.height); if (cl.deinterleave) convert_RGB_to_YCbCr(planes2, pnm.width * pnm.height); break; case TUPL_GRAY: convert_Y255_to_Y219(planes[0], pnm.width * pnm.height); if (cl.deinterleave) convert_Y255_to_Y219(planes2[0], pnm.width * pnm.height); break; case TUPL_RGB_ALPHA: convert_RGB_to_YCbCr(planes, pnm.width * pnm.height); convert_Y255_to_Y219(planes[3], pnm.width * pnm.height); if (cl.deinterleave) { convert_RGB_to_YCbCr(planes2, pnm.width * pnm.height); convert_Y255_to_Y219(planes2[3], pnm.width * pnm.height); } break; case TUPL_GRAY_ALPHA: case TUPL_BW: case TUPL_BW_ALPHA: case TUPL_UNKNOWN: assert(0); break; } break; case FMT_UNKNOWN: assert(0); break; } } WRITE_FRAME: /* Write converted frame to output */ if (count >= cl.offset) { if (cl.deinterleave) { switch (cl.input_interlace) { case Y4M_ILACE_TOP_FIRST: err = y4m_write_fields(fdout, &sinfo, &finfo, planes, planes2); break; case Y4M_ILACE_BOTTOM_FIRST: err = y4m_write_fields(fdout, &sinfo, &finfo, planes2, planes); break; case Y4M_ILACE_NONE: default: assert(0); break; } } else { err = y4m_write_frame(fdout, &sinfo, &finfo, planes); } if (err != Y4M_OK) mjpeg_error_exit1("Write frame/fields failed: %s", y4m_strerr(err)); } } for (i = 0; i < Y4M_MAX_NUM_PLANES; i++) { if (planes[i] != NULL) free(planes[i]); if (planes2[i] != NULL) free(planes2[i]); } y4m_fini_stream_info(&sinfo); y4m_fini_frame_info(&finfo); mjpeg_debug("Done."); return 0;}#if 0staticvoid read_two_ppm_raw(int fd, uint8_t *buffers[], uint8_t *buffers2[], uint8_t *rowbuffer, int width, int height, int bgr){ int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; uint8_t *R2 = buffers2[0]; uint8_t *G2 = buffers2[1]; uint8_t *B2 = buffers2[2]; mjpeg_debug("read into two buffers, %dx%d", width, height); height /= 2; for (y = 0; y < height; y++) { pixels = rowbuffer; if (y4m_read(fd, pixels, width * 3)) mjpeg_error_exit1("read error A y=%d", y); if (!bgr) { for (x = 0; x < width; x++) { *(R++) = *(pixels++); *(G++) = *(pixels++); *(B++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(B++) = *(pixels++); *(G++) = *(pixels++); *(R++) = *(pixels++); } } pixels = rowbuffer; if (y4m_read(fd, pixels, width * 3)) mjpeg_error_exit1("read error B y=%d", y); if (!bgr) { for (x = 0; x < width; x++) { *(R2++) = *(pixels++); *(G2++) = *(pixels++); *(B2++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(B2++) = *(pixels++); *(G2++) = *(pixels++); *(R2++) = *(pixels++); } } }}staticvoid read_two_pgm_raw(int fd, uint8_t *buffer, uint8_t *buffer2, int width, int height){ int y; mjpeg_debug("read PGM into two buffers, %dx%d", width, height); for (y = 0; y < height; y += 2) { if (y4m_read(fd, buffer, width)) mjpeg_error_exit1("read error A y=%d", y); buffer += width; if (y4m_read(fd, buffer2, width)) mjpeg_error_exit1("read error B y=%d", y); buffer2 += width; }}staticvoid read_pnm_into_two_buffers(int fd, uint8_t *planes[], uint8_t *planes2[], uint8_t *rowbuffer, pnm_info_t *pnm, int bgr){ switch (pnm->format) { case FMT_PPM_RAW: read_two_ppm_raw(fd, planes, planes2, rowbuffer, pnm->width, pnm->height, bgr); break; case FMT_PGM_RAW: read_two_pgm_raw(fd, planes[0], planes2[0], pnm->width, pnm->height); break; case FMT_PBM_RAW: // read_two_pbm_raw(fd, planes[0], planes2[0], pnm->width, pnm->height); break; case FMT_PBM_PLAIN: case FMT_PGM_PLAIN: case FMT_PPM_PLAIN: case FMT_UNKNOWN: assert(0); break; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -