4#include "libmythbase/mythconfig.h"
12#include "libavcodec/avcodec.h"
13#include "libavutil/imgutils.h"
24static enum PixelFormat pixelTypeOfVideoFrameType(
VideoFrameType codec)
28 case FMT_YV12:
return AV_PIX_FMT_YUV420P;
31 return AV_PIX_FMT_NONE;
40 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_read fopen %1 failed: %2")
45 auto close_fp = [](
FILE *fp2) { fclose(fp2); };
46 std::unique_ptr<
FILE,
decltype(close_fp)>
cleanup { fp, close_fp };
51 int nn = fscanf(fp,
"P5\n%20d %20d\n%20d\n", &fwidth, &fheight, &maxgray);
54 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_read fscanf %1 failed: %2")
59 if (fwidth != width || fheight != height || maxgray != UCHAR_MAX)
61 LOG(VB_COMMFLAG, LOG_ERR,
62 QString(
"pgm_read header (%1x%2,%3) != (%4x%5,%6)")
63 .arg(fwidth).arg(fheight).arg(maxgray)
64 .arg(width).arg(height).arg(UCHAR_MAX));
68 for (ptrdiff_t rr = 0; rr < height; rr++)
70 if (fread(buf + (rr * width), 1, width, fp) != (
size_t)width)
72 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_read fread %1 failed: %2")
80int pgm_write(
const unsigned char *buf,
int width,
int height,
88 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_write fopen %1 failed: %2")
93 auto close_fp = [](
FILE *fp2) { fclose(fp2); };
94 std::unique_ptr<
FILE,
decltype(close_fp)>
cleanup { fp, close_fp };
96 (void)fprintf(fp,
"P5\n%d %d\n%d\n", width, height, UCHAR_MAX);
97 for (ptrdiff_t rr = 0; rr < height; rr++)
99 if (fwrite(buf + (rr * width), 1, width, fp) != (
size_t)width)
101 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_write fwrite %1 failed: %2")
110 int extratop,
int extraright,
int extrabottom,
114 const int srcwidth = src->linesize[0];
115 const int newwidth = srcwidth + extraleft + extraright;
116 const int newheight = srcheight + extratop + extrabottom;
119 for (ptrdiff_t rr = 0; rr < srcheight; rr++)
121 memcpy(dst->data[0] + ((rr + extratop) * newwidth) + extraleft,
122 src->data[0] + (rr * srcwidth),
127 const uchar *srcdata = src->data[0];
128 for (ptrdiff_t rr = 0; rr < extratop; rr++)
129 memcpy(dst->data[0] + (rr * newwidth) + extraleft, srcdata, srcwidth);
132 srcdata = src->data[0] + (
static_cast<ptrdiff_t
>(srcheight - 1) * srcwidth);
133 for (ptrdiff_t rr = extratop + srcheight; rr < newheight; rr++)
134 memcpy(dst->data[0] + (rr * newwidth) + extraleft, srcdata, srcwidth);
137 for (ptrdiff_t rr = 0; rr < newheight; rr++)
139 memset(dst->data[0] + (rr * newwidth),
140 dst->data[0][(rr * newwidth) + extraleft],
145 for (ptrdiff_t rr = 0; rr < newheight; rr++)
147 memset(dst->data[0] + (rr * newwidth) + extraleft + srcwidth,
148 dst->data[0][(rr * newwidth) + extraleft + srcwidth - 1],
156 int srcheight,
int extramargin)
159 extramargin, extramargin, extramargin, extramargin);
163 [[maybe_unused]]
int srcheight,
164 int srcrow,
int srccol,
int cropwidth,
int cropheight)
166 const int srcwidth = src->linesize[0];
168 if (dst->linesize[0] != cropwidth)
170 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_crop want width %1, have %2")
171 .arg(cropwidth).arg(dst->linesize[0]));
175 for (ptrdiff_t rr = 0; rr < cropheight; rr++)
177 memcpy(dst->data[0] + (rr * cropwidth),
178 src->data[0] + ((srcrow + rr) * srcwidth) + srccol,
186 int s1row,
int s1col,
const AVFrame *s2,
int s2height)
188 const int dstwidth = dst->linesize[0];
189 const int s1width = s1->linesize[0];
190 const int s2width = s2->linesize[0];
192 if (dstwidth != s1width)
194 LOG(VB_COMMFLAG, LOG_ERR, QString(
"pgm_overlay want width %1, have %2")
195 .arg(s1width).arg(dst->linesize[0]));
201 std::array<const uint8_t*,4> src_data
202 {s1->data[0], s1->data[1], s1->data[2], s1->data[3]};
204 av_image_copy(dst->data, dst->linesize, src_data.data(), s1->linesize,
205 AV_PIX_FMT_GRAY8, s1width, s1height);
208 for (ptrdiff_t rr = 0; rr < s2height; rr++)
210 memcpy(dst->data[0] + ((s1row + rr) * s1width) + s1col,
211 s2->data[0] + (rr * s2width),
219 const AVFrame *src,
int srcheight,
220 const double *mask,
int mask_radius)
235 const int srcwidth = src->linesize[0];
236 const int newwidth = srcwidth + (2 * mask_radius);
237 const int newheight = srcheight + (2 * mask_radius);
247 std::array<const uint8_t*,4> src_data
248 {s1->data[0], s1->data[1], s1->data[2], s1->data[3]};
250 av_image_copy(s2->data, s2->linesize, src_data.data(), s1->linesize,
251 AV_PIX_FMT_GRAY8, newwidth, newheight);
252 av_image_copy(dst->data, dst->linesize, src_data.data(), s1->linesize,
253 AV_PIX_FMT_GRAY8, newwidth, newheight);
256 int rr2 = mask_radius + srcheight;
257 int cc2 = mask_radius + srcwidth;
258 for (
int rr = mask_radius; rr < rr2; rr++)
260 for (
int cc = mask_radius; cc < cc2; cc++)
263 for (
int ii = -mask_radius; ii <= mask_radius; ii++)
265 sum += mask[ii + mask_radius] *
266 s1->data[0][((rr + ii) * newwidth) + cc];
268 s2->data[0][(rr * newwidth) + cc] = lround(sum);
273 for (
int rr = mask_radius; rr < rr2; rr++)
275 for (
int cc = mask_radius; cc < cc2; cc++)
278 for (
int ii = -mask_radius; ii <= mask_radius; ii++)
280 sum += mask[ii + mask_radius] *
281 s2->data[0][(rr * newwidth) + cc + ii];
283 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)