00001 extern "C" {
00002 #include "avcodec.h"
00003 }
00004 #include "frame.h"
00005 #include "mythcontext.h"
00006 #include "pgm.h"
00007
00008
00009
00010
00011
00012
00013
00014 static enum PixelFormat
00015 pixelTypeOfVideoFrameType(VideoFrameType codec)
00016 {
00017
00018 switch (codec) {
00019 case FMT_YV12: return PIX_FMT_YUV420P;
00020 default: break;
00021 }
00022 return PIX_FMT_NONE;
00023 }
00024
00025 int
00026 pgm_fill(AVPicture *dst, const VideoFrame *frame)
00027 {
00028 enum PixelFormat srcfmt;
00029 AVPicture src;
00030
00031 if ((srcfmt = pixelTypeOfVideoFrameType(frame->codec)) == PIX_FMT_NONE)
00032 {
00033 VERBOSE(VB_COMMFLAG, QString("pgm_fill unknown codec: %1")
00034 .arg(frame->codec));
00035 return -1;
00036 }
00037
00038 if (avpicture_fill(&src, frame->buf, srcfmt, frame->width,
00039 frame->height) < 0)
00040 {
00041 VERBOSE(VB_COMMFLAG, "pgm_fill avpicture_fill failed");
00042 return -1;
00043 }
00044
00045 if (img_convert(dst, PIX_FMT_GRAY8, &src, srcfmt, frame->width,
00046 frame->height))
00047 {
00048 VERBOSE(VB_COMMFLAG, "pgm_fill img_convert failed");
00049 return -1;
00050 }
00051
00052 return 0;
00053 }
00054
00055 int
00056 pgm_read(unsigned char *buf, int width, int height, const char *filename)
00057 {
00058 FILE *fp;
00059 int nn, fwidth, fheight, maxgray, rr;
00060
00061 if (!(fp = fopen(filename, "r")))
00062 {
00063 VERBOSE(VB_COMMFLAG, QString("pgm_read fopen %1 failed: %2")
00064 .arg(filename).arg(strerror(errno)));
00065 return -1;
00066 }
00067
00068 if ((nn = fscanf(fp, "P5\n%d %d\n%d\n", &fwidth, &fheight, &maxgray)) != 3)
00069 {
00070 VERBOSE(VB_COMMFLAG, QString("pgm_read fscanf %1 failed: %2")
00071 .arg(filename).arg(strerror(errno)));
00072 goto error;
00073 }
00074
00075 if (fwidth != width || fheight != height || maxgray != UCHAR_MAX)
00076 {
00077 VERBOSE(VB_COMMFLAG, QString("pgm_read header (%1x%2,%3) != (%4x%5,%6)")
00078 .arg(fwidth).arg(fheight).arg(maxgray)
00079 .arg(width).arg(height).arg(UCHAR_MAX));
00080 goto error;
00081 }
00082
00083 for (rr = 0; rr < height; rr++)
00084 {
00085 if (fread(buf + rr * width, 1, width, fp) != (size_t)width)
00086 {
00087 VERBOSE(VB_COMMFLAG, QString("pgm_read fread %1 failed: %2")
00088 .arg(filename).arg(strerror(errno)));
00089 goto error;
00090 }
00091 }
00092
00093 (void)fclose(fp);
00094 return 0;
00095
00096 error:
00097 (void)fclose(fp);
00098 return -1;
00099 }
00100
00101 int
00102 pgm_write(const unsigned char *buf, int width, int height, const char *filename)
00103 {
00104
00105 FILE *fp;
00106 int rr;
00107
00108 if (!(fp = fopen(filename, "w")))
00109 {
00110 VERBOSE(VB_COMMFLAG, QString("pgm_write fopen %1 failed: %2")
00111 .arg(filename).arg(strerror(errno)));
00112 return -1;
00113 }
00114
00115 (void)fprintf(fp, "P5\n%d %d\n%d\n", width, height, UCHAR_MAX);
00116 for (rr = 0; rr < height; rr++)
00117 {
00118 if (fwrite(buf + rr * width, 1, width, fp) != (size_t)width)
00119 {
00120 VERBOSE(VB_COMMFLAG, QString("pgm_write fwrite %1 failed: %2")
00121 .arg(filename).arg(strerror(errno)));
00122 goto error;
00123 }
00124 }
00125
00126 (void)fclose(fp);
00127 return 0;
00128
00129 error:
00130 (void)fclose(fp);
00131 return -1;
00132 }
00133
00134 static int
00135 pgm_expand(AVPicture *dst, const AVPicture *src, int srcheight,
00136 int extratop, int extraright, int extrabottom, int extraleft)
00137 {
00138
00139 const int srcwidth = src->linesize[0];
00140 const int newwidth = srcwidth + extraleft + extraright;
00141 const int newheight = srcheight + extratop + extrabottom;
00142 const unsigned char *srcdata;
00143 int rr;
00144
00145
00146 for (rr = 0; rr < srcheight; rr++)
00147 memcpy(dst->data[0] + (rr + extratop) * newwidth + extraleft,
00148 src->data[0] + rr * srcwidth,
00149 srcwidth);
00150
00151
00152 srcdata = src->data[0];
00153 for (rr = 0; rr < extratop; rr++)
00154 memcpy(dst->data[0] + rr * newwidth + extraleft, srcdata, srcwidth);
00155
00156
00157 srcdata = src->data[0] + (srcheight - 1) * srcwidth;
00158 for (rr = extratop + srcheight; rr < newheight; rr++)
00159 memcpy(dst->data[0] + rr * newwidth + extraleft, srcdata, srcwidth);
00160
00161
00162 for (rr = 0; rr < newheight; rr++)
00163 memset(dst->data[0] + rr * newwidth,
00164 dst->data[0][rr * newwidth + extraleft],
00165 extraleft);
00166
00167
00168 for (rr = 0; rr < newheight; rr++)
00169 memset(dst->data[0] + rr * newwidth + extraleft + srcwidth,
00170 dst->data[0][rr * newwidth + extraleft + srcwidth - 1],
00171 extraright);
00172
00173 return 0;
00174 }
00175
00176 static int
00177 pgm_expand_uniform(AVPicture *dst, const AVPicture *src, int srcheight,
00178 int extramargin)
00179 {
00180 return pgm_expand(dst, src, srcheight,
00181 extramargin, extramargin, extramargin, extramargin);
00182 }
00183
00184 int
00185 pgm_crop(AVPicture *dst, const AVPicture *src, int srcheight,
00186 int srcrow, int srccol, int cropwidth, int cropheight)
00187 {
00188 const int srcwidth = src->linesize[0];
00189 int rr;
00190
00191 if (dst->linesize[0] != cropwidth)
00192 {
00193 VERBOSE(VB_COMMFLAG, QString("pgm_crop want width %1, have %2")
00194 .arg(cropwidth).arg(dst->linesize[0]));
00195 return -1;
00196 }
00197
00198 for (rr = 0; rr < cropheight; rr++)
00199 memcpy(dst->data[0] + rr * cropwidth,
00200 src->data[0] + (srcrow + rr) * srcwidth + srccol,
00201 cropwidth);
00202
00203 (void)srcheight;
00204 return 0;
00205 }
00206
00207 int
00208 pgm_overlay(AVPicture *dst, const AVPicture *s1, int s1height,
00209 int s1row, int s1col, const AVPicture *s2, int s2height)
00210 {
00211 const int dstwidth = dst->linesize[0];
00212 const int s1width = s1->linesize[0];
00213 const int s2width = s2->linesize[0];
00214 int rr;
00215
00216 if (dstwidth != s1width)
00217 {
00218 VERBOSE(VB_COMMFLAG, QString("pgm_overlay want width %1, have %2")
00219 .arg(s1width).arg(dst->linesize[0]));
00220 return -1;
00221 }
00222
00223 img_copy(dst, s1, PIX_FMT_GRAY8, s1width, s1height);
00224
00225
00226 for (rr = 0; rr < s2height; rr++)
00227 memcpy(dst->data[0] + (s1row + rr) * s1width + s1col,
00228 s2->data[0] + rr * s2width,
00229 s2width);
00230
00231 return 0;
00232 }
00233
00234 int
00235 pgm_convolve_radial(AVPicture *dst, AVPicture *s1, AVPicture *s2,
00236 const AVPicture *src, int srcheight,
00237 const double *mask, int mask_radius)
00238 {
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 const int srcwidth = src->linesize[0];
00253 const int newwidth = srcwidth + 2 * mask_radius;
00254 const int newheight = srcheight + 2 * mask_radius;
00255 int ii, rr, cc, rr2, cc2;
00256 double sum;
00257
00258
00259 if (pgm_expand_uniform(s1, src, srcheight, mask_radius))
00260 return -1;
00261
00262
00263 img_copy(s2, s1, PIX_FMT_GRAY8, newwidth, newheight);
00264 img_copy(dst, s1, PIX_FMT_GRAY8, newwidth, newheight);
00265
00266
00267 rr2 = mask_radius + srcheight;
00268 cc2 = mask_radius + srcwidth;
00269 for (rr = mask_radius; rr < rr2; rr++)
00270 {
00271 for (cc = mask_radius; cc < cc2; cc++)
00272 {
00273 sum = 0;
00274 for (ii = -mask_radius; ii <= mask_radius; ii++)
00275 {
00276 sum += mask[ii + mask_radius] *
00277 s1->data[0][(rr + ii) * newwidth + cc];
00278 }
00279 s2->data[0][rr * newwidth + cc] = (unsigned char)(sum + 0.5);
00280 }
00281 }
00282
00283
00284 for (rr = mask_radius; rr < rr2; rr++)
00285 {
00286 for (cc = mask_radius; cc < cc2; cc++)
00287 {
00288 sum = 0;
00289 for (ii = -mask_radius; ii <= mask_radius; ii++)
00290 {
00291 sum += mask[ii + mask_radius] *
00292 s2->data[0][rr * newwidth + cc + ii];
00293 }
00294 dst->data[0][rr * newwidth + cc] = (unsigned char)(sum + 0.5);
00295 }
00296 }
00297
00298 return 0;
00299 }
00300
00301