64 switch (info->subsampling) {
65 case Y4M_SUBS_MONO: ret = (size_t) info->width * info->height;
break;
66 case Y4M_SUBS_420: ret = (size_t) info->width * info->height + (
size_t) 2 * ((info->width + 1) / 2) * ((info->height + 1) / 2);
break;
67 case Y4M_SUBS_422: ret = (size_t) info->width * info->height + (
size_t) 2 * ((info->width + 1) / 2) * info->height;
break;
68 case Y4M_SUBS_444: ret = (size_t) info->width * info->height * 3;
break;
69 case Y4M_SUBS_YUVA: ret = (size_t) info->width * info->height * 4;
break;
71 fprintf(stderr,
"Unsupported subsampling '%d'\n", info->subsampling);
74 return ret * (info->bitdepth > 8 ? 2 : 1);
77size_t y4m_read(
const char *filename,
struct y4m_metadata *info,
unsigned char **data,
void *(*allocator)(
size_t)) {
78 FILE *file = fopen(filename,
"rb");
80 fprintf(stderr,
"Failed to open %s: %s\n", filename, strerror(errno));
84 if (fscanf(file,
"%128s",
item) != 1 || strcmp(
item,
"YUV4MPEG2") != 0) {
85 fprintf(stderr,
"File '%s' doesn't seem to be valid Y4M.\n", filename);
89 memset(info, 0,
sizeof *info);
90 info->width = info->height = info->bitdepth = info->subsampling = 0;
91 while (fscanf(file,
" %128s",
item) == 1 && strcmp(
item,
"FRAME") != 0) {
93 case 'W': info->width = atoi(
item + 1);
break;
94 case 'H': info->height = atoi(
item + 1);
break;
102 if (strcmp(
item,
"XCOLORRANGE=LIMITED") == 0) {
103 info->limited =
true;
108 if (getc(file) !=
'\n') {
113 if (data == NULL || allocator == NULL) {
117 *data = (
unsigned char *) allocator(datalen);
119 fprintf(stderr,
"Unspecified depth header field!\n");
124 size_t bytes_read = fread((
char *) *data, 1, datalen, file);
125 if (bytes_read != datalen) {
126 fprintf(stderr,
"Unable to load %zd data bytes from Y4M file, read %zd bytes: %s\n",
127 datalen, bytes_read, feof(file) ?
"EOF" : strerror(errno));
137 FILE *file = fopen(filename,
"wb");
139 fprintf(stderr,
"Failed to open %s for writing: %s\n", filename, strerror(errno));
142 char chroma_type[42];
144 snprintf(chroma_type,
sizeof chroma_type,
"mono");
146 if (info->bitdepth != 8) {
147 fprintf(stderr,
"Only 8-bit 444alpha is supported for Y4M!\n");
151 snprintf(chroma_type,
sizeof chroma_type,
"444alpha");
153 snprintf(chroma_type,
sizeof chroma_type,
"%d", info->subsampling);
160 if (info->bitdepth > 8) {
161 snprintf(chroma_type + strlen(chroma_type),
sizeof chroma_type - strlen(chroma_type),
"%s%d",
162 info->subsampling !=
Y4M_SUBS_MONO ?
"p" :
"", info->bitdepth);
165 fprintf(file,
"YUV4MPEG2 W%d H%d F25:1 Ip A0:0 C%s XCOLORRANGE=%s\nFRAME\n",
166 info->width, info->height, chroma_type, info->limited ?
"LIMITED" :
"FULL");
168 size_t bytes_written = fwrite((
const char *) data, 1,
len, file);
169 if (bytes_written !=
len) {
170 fprintf(stderr,
"Unable to write Y4M data - length %zd, written %zd: %s\n",
171 len, bytes_written, strerror(errno));
174 return bytes_written ==
len;