11#include "libavcodec/avcodec.h"
12#include "libavutil/imgutils.h"
23static enum PixelFormat pixelTypeOfVideoFrameType(
VideoFrameType codec)
27 case FMT_YV12:
return AV_PIX_FMT_YUV420P;
30 return AV_PIX_FMT_NONE;
39 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_read fopen %1 failed: %2")
44 auto close_fp = [](
FILE *fp2) { fclose(fp2); };
45 std::unique_ptr<
FILE,
decltype(close_fp)>
cleanup { fp, close_fp };
50 int nn = fscanf(fp,
"P5\n%20d %20d\n%20d\n", &fwidth, &fheight, &maxgray);
53 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_read fscanf %1 failed: %2")
58 if (fwidth != width || fheight != height || maxgray != UCHAR_MAX)
60 LOG(VB_COMMFLAG, LOG_ERR,
61 QString(
"pgm_read header (%1x%2,%3) != (%4x%5,%6)")
62 .arg(fwidth).arg(fheight).arg(maxgray)
63 .arg(width).arg(height).arg(UCHAR_MAX));
67 for (ptrdiff_t rr = 0; rr < height; rr++)
69 if (fread(buf + (rr * width), 1, width, fp) != (
size_t)width)
71 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_read fread %1 failed: %2")
79int pgm_write(
const unsigned char *buf,
int width,
int height,
87 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_write fopen %1 failed: %2")
92 auto close_fp = [](
FILE *fp2) { fclose(fp2); };
93 std::unique_ptr<
FILE,
decltype(close_fp)>
cleanup { fp, close_fp };
95 (void)fprintf(fp,
"P5\n%d %d\n%d\n", width, height, UCHAR_MAX);
96 for (ptrdiff_t rr = 0; rr < height; rr++)
98 if (fwrite(buf + (rr * width), 1, width, fp) != (
size_t)width)
100 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_write fwrite %1 failed: %2")
109 int extratop,
int extraright,
int extrabottom,
113 const int srcwidth = src->linesize[0];
114 const int newwidth = srcwidth + extraleft + extraright;
115 const int newheight = srcheight + extratop + extrabottom;
118 for (ptrdiff_t rr = 0; rr < srcheight; rr++)
120 memcpy(dst->data[0] + ((rr + extratop) * newwidth) + extraleft,
121 src->data[0] + (rr * srcwidth),
126 const uchar *srcdata = src->data[0];
127 for (ptrdiff_t rr = 0; rr < extratop; rr++)
128 memcpy(dst->data[0] + (rr * newwidth) + extraleft, srcdata, srcwidth);
131 srcdata = src->data[0] + (
static_cast<ptrdiff_t
>(srcheight - 1) * srcwidth);
132 for (ptrdiff_t rr = extratop + srcheight; rr < newheight; rr++)
133 memcpy(dst->data[0] + (rr * newwidth) + extraleft, srcdata, srcwidth);
136 for (ptrdiff_t rr = 0; rr < newheight; rr++)
138 memset(dst->data[0] + (rr * newwidth),
139 dst->data[0][(rr * newwidth) + extraleft],
144 for (ptrdiff_t rr = 0; rr < newheight; rr++)
146 memset(dst->data[0] + (rr * newwidth) + extraleft + srcwidth,
147 dst->data[0][(rr * newwidth) + extraleft + srcwidth - 1],
155 int srcheight,
int extramargin)
158 extramargin, extramargin, extramargin, extramargin);
162 [[maybe_unused]]
int srcheight,
163 int srcrow,
int srccol,
int cropwidth,
int cropheight)
165 const int srcwidth = src->linesize[0];
167 if (dst->linesize[0] != cropwidth)
169 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_crop want width %1, have %2")
170 .arg(cropwidth).arg(dst->linesize[0]));
174 for (ptrdiff_t rr = 0; rr < cropheight; rr++)
176 memcpy(dst->data[0] + (rr * cropwidth),
177 src->data[0] + ((srcrow + rr) * srcwidth) + srccol,
185 int s1row,
int s1col,
const AVFrame *s2,
int s2height)
187 const int dstwidth = dst->linesize[0];
188 const int s1width = s1->linesize[0];
189 const int s2width = s2->linesize[0];
191 if (dstwidth != s1width)
193 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_overlay want width %1, have %2")
194 .arg(s1width).arg(dst->linesize[0]));
200 std::array<const uint8_t*,4> src_data
201 {s1->data[0], s1->data[1], s1->data[2], s1->data[3]};
203 av_image_copy(dst->data, dst->linesize, src_data.data(), s1->linesize,
204 AV_PIX_FMT_GRAY8, s1width, s1height);
207 for (ptrdiff_t rr = 0; rr < s2height; rr++)
209 memcpy(dst->data[0] + ((s1row + rr) * s1width) + s1col,
210 s2->data[0] + (rr * s2width),
218 const AVFrame *src,
int srcheight,
219 const double *mask,
int mask_radius)
234 const int srcwidth = src->linesize[0];
235 const int newwidth = srcwidth + (2 * mask_radius);
236 const int newheight = srcheight + (2 * mask_radius);
246 std::array<const uint8_t*,4> src_data
247 {s1->data[0], s1->data[1], s1->data[2], s1->data[3]};
249 av_image_copy(s2->data, s2->linesize, src_data.data(), s1->linesize,
250 AV_PIX_FMT_GRAY8, newwidth, newheight);
251 av_image_copy(dst->data, dst->linesize, src_data.data(), s1->linesize,
252 AV_PIX_FMT_GRAY8, newwidth, newheight);
255 int rr2 = mask_radius + srcheight;
256 int cc2 = mask_radius + srcwidth;
257 for (
int rr = mask_radius; rr < rr2; rr++)
259 for (
int cc = mask_radius; cc < cc2; cc++)
262 for (
int ii = -mask_radius; ii <= mask_radius; ii++)
264 sum += mask[ii + mask_radius] *
265 s1->data[0][((rr + ii) * newwidth) + cc];
267 s2->data[0][(rr * newwidth) + cc] = lround(sum);
272 for (
int rr = mask_radius; rr < rr2; rr++)
274 for (
int cc = mask_radius; cc < cc2; cc++)
277 for (
int ii = -mask_radius; ii <= mask_radius; ii++)
279 sum += mask[ii + mask_radius] *
280 s2->data[0][(rr * newwidth) + cc + ii];
282 dst->data[0][(rr * newwidth) + cc] = lround(sum);
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
int pgm_convolve_radial(AVFrame *dst, AVFrame *s1, AVFrame *s2, const AVFrame *src, int srcheight, const double *mask, int mask_radius)
int pgm_write(const unsigned char *buf, int width, int height, const char *filename)
static int pgm_expand(AVFrame *dst, const AVFrame *src, int srcheight, int extratop, int extraright, int extrabottom, int extraleft)
int pgm_crop(AVFrame *dst, const AVFrame *src, int srcheight, int srcrow, int srccol, int cropwidth, int cropheight)
int pgm_read(unsigned char *buf, int width, int height, const char *filename)
static int pgm_expand_uniform(AVFrame *dst, const AVFrame *src, int srcheight, int extramargin)
int pgm_overlay(AVFrame *dst, const AVFrame *s1, int s1height, int s1row, int s1col, const AVFrame *s2, int s2height)
static QString cleanup(const QString &str)