3 * Copyright (c) 2017 Paras Chadha
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include "avio_internal.h"
31 typedef struct FITSContext
{
35 static int fits_write_header(AVFormatContext
*s
)
37 FITSContext
*fitsctx
= s
->priv_data
;
38 fitsctx
->first_image
= 1;
43 * Write one header line comprising of keyword and value(int)
44 * @param s AVFormat Context
45 * @param keyword pointer to the char array in which keyword is stored
46 * @param value the value corresponding to the keyword
47 * @param lines_written to keep track of lines written so far
50 static int write_keyword_value(AVFormatContext
*s
, const char *fmt
,
51 const char *keyword
, void *value
, int *lines_written
)
56 len
= strlen(keyword
);
57 memset(header
, ' ', sizeof(header
));
58 memcpy(header
, keyword
, len
);
63 if (!strcmp(fmt
, "%d")) {
64 ret
= snprintf(header
+ 10, 70, fmt
, *(int *)value
);
66 ret
= snprintf(header
+ 10, 70, fmt
, *(float *)value
);
69 memset(&header
[ret
+ 10], ' ', sizeof(header
) - (ret
+ 10));
71 avio_write(s
->pb
, header
, sizeof(header
));
76 static int write_image_header(AVFormatContext
*s
)
78 AVStream
*st
= s
->streams
[0];
79 AVCodecParameters
*encctx
= st
->codecpar
;
80 FITSContext
*fitsctx
= s
->priv_data
;
82 int bitpix
, naxis
, naxis3
= 1, bzero
= 0, rgb
= 0, lines_written
= 0, lines_left
;
83 int pcount
= 0, gcount
= 1;
84 float datamax
, datamin
;
86 switch (encctx
->format
) {
87 case AV_PIX_FMT_GRAY8
:
93 case AV_PIX_FMT_GRAY16BE
:
100 case AV_PIX_FMT_GBRP
:
101 case AV_PIX_FMT_GBRAP
:
105 if (encctx
->format
== AV_PIX_FMT_GBRP
) {
113 case AV_PIX_FMT_GBRP16BE
:
114 case AV_PIX_FMT_GBRAP16BE
:
118 if (encctx
->format
== AV_PIX_FMT_GBRP16BE
) {
128 return AVERROR(EINVAL
);
131 if (fitsctx
->first_image
) {
132 memcpy(buffer
, "SIMPLE = ", 10);
133 memset(buffer
+ 10, ' ', 70);
135 avio_write(s
->pb
, buffer
, sizeof(buffer
));
137 memcpy(buffer
, "XTENSION= 'IMAGE '", 20);
138 memset(buffer
+ 20, ' ', 60);
139 avio_write(s
->pb
, buffer
, sizeof(buffer
));
143 write_keyword_value(s
, "%d", "BITPIX", &bitpix
, &lines_written
); // no of bits per pixel
144 write_keyword_value(s
, "%d", "NAXIS", &naxis
, &lines_written
); // no of dimensions of image
145 write_keyword_value(s
, "%d", "NAXIS1", &encctx
->width
, &lines_written
); // first dimension i.e. width
146 write_keyword_value(s
, "%d", "NAXIS2", &encctx
->height
, &lines_written
); // second dimension i.e. height
149 write_keyword_value(s
, "%d", "NAXIS3", &naxis3
, &lines_written
); // third dimension to store RGBA planes
151 if (!fitsctx
->first_image
) {
152 write_keyword_value(s
, "%d", "PCOUNT", &pcount
, &lines_written
);
153 write_keyword_value(s
, "%d", "GCOUNT", &gcount
, &lines_written
);
155 fitsctx
->first_image
= 0;
158 write_keyword_value(s
, "%g", "DATAMIN", &datamin
, &lines_written
);
159 write_keyword_value(s
, "%g", "DATAMAX", &datamax
, &lines_written
);
162 * Since FITS does not support unsigned 16 bit integers,
163 * BZERO = 32768 is used to store unsigned 16 bit integers as
164 * signed integers so that it can be read properly.
167 write_keyword_value(s
, "%d", "BZERO", &bzero
, &lines_written
);
170 memcpy(buffer
, "CTYPE3 = 'RGB '", 20);
171 memset(buffer
+ 20, ' ', 60);
172 avio_write(s
->pb
, buffer
, sizeof(buffer
));
176 memcpy(buffer
, "END", 3);
177 memset(buffer
+ 3, ' ', 77);
178 avio_write(s
->pb
, buffer
, sizeof(buffer
));
181 lines_left
= ((lines_written
+ 35) / 36) * 36 - lines_written
;
182 ffio_fill(s
->pb
, ' ', sizeof(buffer
) * lines_left
);
186 static int fits_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
188 int ret
= write_image_header(s
);
191 avio_write(s
->pb
, pkt
->data
, pkt
->size
);
195 const FFOutputFormat ff_fits_muxer
= {
197 .p
.long_name
= NULL_IF_CONFIG_SMALL("Flexible Image Transport System"),
198 .p
.extensions
= "fits",
199 .p
.audio_codec
= AV_CODEC_ID_NONE
,
200 .p
.video_codec
= AV_CODEC_ID_FITS
,
201 .p
.subtitle_codec
= AV_CODEC_ID_NONE
,
202 .flags_internal
= FF_OFMT_FLAG_MAX_ONE_OF_EACH
|
203 FF_OFMT_FLAG_ONLY_DEFAULT_CODECS
,
204 .priv_data_size
= sizeof(FITSContext
),
205 .write_header
= fits_write_header
,
206 .write_packet
= fits_write_packet
,
207 .p
.flags
= AVFMT_NOTIMESTAMPS
,