17abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#include <stdio.h> 27abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#include <debug.h> 37abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#include <cmdline.h> 47abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#include <sys/types.h> 57abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#include <sys/stat.h> 67abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#include <sys/mman.h> 77abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#include <fcntl.h> 87abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#include <string.h> 97abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#include <errno.h> 107abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#include <unistd.h> 117abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 127abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#ifndef max 137abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#define max(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; }) 147abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#define min(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; }) 157abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#endif 167abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 177abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#define CONVERT_TYPE_PPM 0 187abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#define CONVERT_TYPE_RGB 1 197abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev#define CONVERT_TYPE_ARGB 2 207abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 217abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev/* 227abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved 237abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev U/V plane containing 8 bit 2x2 subsampled chroma samples. 247abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev except the interleave order of U and V is reversed. 257abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 267abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev H V 277abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev Y Sample Period 1 1 287abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev U (Cb) Sample Period 2 2 297abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev V (Cr) Sample Period 2 2 307abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev */ 317abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 327abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevtypedef struct rgb_context { 337abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char *buffer; 347abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int width; 357abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int height; 367abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int rotate; 377abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int i; 387abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int j; 397abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int size; /* for debugging */ 407abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev} rgb_context; 417abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 427abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevtypedef void (*rgb_cb)( 437abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char r, 447abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char g, 457abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char b, 467abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev rgb_context *ctx); 477abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 487abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevconst int bytes_per_pixel = 2; 497abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 507abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevstatic void color_convert_common( 517abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char *pY, unsigned char *pUV, 527abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int width, int height, 537abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char *buffer, 547abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int size, /* buffer size in bytes */ 557abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int gray, 567abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int rotate, 577abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev rgb_cb cb) 587abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev{ 597abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int i, j; 607abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int nR, nG, nB; 617abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int nY, nU, nV; 627abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev rgb_context ctx; 637abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 647abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx.buffer = buffer; 657abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx.size = size; /* debug */ 667abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx.width = width; 677abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx.height = height; 687abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx.rotate = rotate; 697abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 707abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev if (gray) { 717abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev for (i = 0; i < height; i++) { 727abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev for (j = 0; j < width; j++) { 737abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nB = *(pY + i * width + j); 747abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx.i = i; 757abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx.j = j; 767abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev cb(nB, nB, nB, &ctx); 777abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 787abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 797abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } else { 807abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev // YUV 4:2:0 817abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev for (i = 0; i < height; i++) { 827abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev for (j = 0; j < width; j++) { 837abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nY = *(pY + i * width + j); 847abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nV = *(pUV + (i/2) * width + bytes_per_pixel * (j/2)); 857abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nU = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1); 867abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 877abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev // Yuv Convert 887abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nY -= 16; 897abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nU -= 128; 907abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nV -= 128; 917abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 927abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev if (nY < 0) 937abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nY = 0; 947abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 957abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev // nR = (int)(1.164 * nY + 2.018 * nU); 967abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev // nG = (int)(1.164 * nY - 0.813 * nV - 0.391 * nU); 977abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev // nB = (int)(1.164 * nY + 1.596 * nV); 987abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 997abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nB = (int)(1192 * nY + 2066 * nU); 1007abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nG = (int)(1192 * nY - 833 * nV - 400 * nU); 1017abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nR = (int)(1192 * nY + 1634 * nV); 1027abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1037abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nR = min(262143, max(0, nR)); 1047abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nG = min(262143, max(0, nG)); 1057abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nB = min(262143, max(0, nB)); 1067abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1077abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nR >>= 10; nR &= 0xff; 1087abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nG >>= 10; nG &= 0xff; 1097abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev nB >>= 10; nB &= 0xff; 1107abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1117abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx.i = i; 1127abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx.j = j; 1137abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev cb(nR, nG, nB, &ctx); 1147abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 1157abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 1167abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 1177abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev} 1187abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1197abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevstatic void rgb16_cb( 1207abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char r, 1217abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char g, 1227abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char b, 1237abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev rgb_context *ctx) 1247abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev{ 1257abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned short *rgb16 = (unsigned short *)ctx->buffer; 1267abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev *(rgb16 + ctx->i * ctx->width + ctx->j) = b | (g << 5) | (r << 11); 1277abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev} 1287abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1297abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevstatic void common_rgb_cb( 1307abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char r, 1317abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char g, 1327abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char b, 1337abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev rgb_context *ctx, 1347abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int alpha) 1357abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev{ 1367abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char *out = ctx->buffer; 1377abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int offset = 0; 1387abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int bpp; 1397abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int i = 0; 1407abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev switch(ctx->rotate) { 1417abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev case 0: /* no rotation */ 1427abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev offset = ctx->i * ctx->width + ctx->j; 1437abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev break; 1447abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev case 1: /* 90 degrees */ 1457abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev offset = ctx->height * (ctx->j + 1) - ctx->i; 1467abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev break; 1477abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev case 2: /* 180 degrees */ 1487abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev offset = (ctx->height - 1 - ctx->i) * ctx->width + ctx->j; 1497abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev break; 1507abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev case 3: /* 270 degrees */ 1517abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev offset = (ctx->width - 1 - ctx->j) * ctx->height + ctx->i; 1527abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev break; 1537abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev default: 1547abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev FAILIF(1, "Unexpected roation value %d!\n", ctx->rotate); 1557abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 1567abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1577abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev bpp = 3 + !!alpha; 1587abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev offset *= bpp; 1597abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev FAILIF(offset < 0, "point (%d, %d) generates a negative offset.\n", ctx->i, ctx->j); 1607abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev FAILIF(offset + bpp > ctx->size, "point (%d, %d) at offset %d exceeds the size %d of the buffer.\n", 1617abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx->i, ctx->j, 1627abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev offset, 1637abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ctx->size); 1647abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1657abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev out += offset; 1667abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1677abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev if (alpha) out[i++] = 0xff; 1687abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev out[i++] = r; 1697abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev out[i++] = g; 1707abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev out[i] = b; 1717abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev} 1727abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1737abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevstatic void rgb24_cb( 1747abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char r, 1757abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char g, 1767abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char b, 1777abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev rgb_context *ctx) 1787abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev{ 1797abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev return common_rgb_cb(r,g,b,ctx,0); 1807abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev} 1817abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1827abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevstatic void argb_cb( 1837abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char r, 1847abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char g, 1857abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev unsigned char b, 1867abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev rgb_context *ctx) 1877abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev{ 1887abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev return common_rgb_cb(r,g,b,ctx,1); 1897abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev} 1907abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 1917abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevstatic void convert(const char *infile, 1927abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev const char *outfile, 1937abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int height, 1947abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int width, 1957abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int gray, 1967abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int type, 1977abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int rotate) 1987abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev{ 1997abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev void *in, *out; 2007abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int ifd, ofd, rc; 2017abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int psz = getpagesize(); 2027abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev static char header[1024]; 2037abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int header_size; 2047abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev size_t outsize; 2057abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2067abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int bpp = 3; 2077abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev switch (type) { 2087abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev case CONVERT_TYPE_PPM: 2097abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev PRINT("encoding PPM\n"); 2107abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev if (rotate & 1) 2117abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev header_size = snprintf(header, sizeof(header), "P6\n%d %d\n255\n", height, width); 2127abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev else 2137abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev header_size = snprintf(header, sizeof(header), "P6\n%d %d\n255\n", width, height); 2147abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev break; 2157abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev case CONVERT_TYPE_RGB: 2167abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev PRINT("encoding raw RGB24\n"); 2177abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev header_size = 0; 2187abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev break; 2197abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev case CONVERT_TYPE_ARGB: 2207abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev PRINT("encoding raw ARGB\n"); 2217abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev header_size = 0; 2227abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev bpp = 4; 2237abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev break; 2247abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 2257abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2267abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev outsize = header_size + width * height * bpp; 2277abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev outsize = (outsize + psz - 1) & ~(psz - 1); 2287abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2297abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("Opening input file %s\n", infile); 2307abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ifd = open(infile, O_RDONLY); 2317abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev FAILIF(ifd < 0, "open(%s) failed: %s (%d)\n", 2327abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev infile, strerror(errno), errno); 2337abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2347abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("Opening output file %s\n", outfile); 2357abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ofd = open(outfile, O_RDWR | O_CREAT, 0664); 2367abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev FAILIF(ofd < 0, "open(%s) failed: %s (%d)\n", 2377abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev outfile, strerror(errno), errno); 2387abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2397abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("Memory-mapping input file %s\n", infile); 2407abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev in = mmap(0, width * height * 3 / 2, PROT_READ, MAP_PRIVATE, ifd, 0); 2417abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev FAILIF(in == MAP_FAILED, "could not mmap input file: %s (%d)\n", 2427abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev strerror(errno), errno); 2437abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2447abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("Truncating output file %s to %d bytes\n", outfile, outsize); 2457abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev FAILIF(ftruncate(ofd, outsize) < 0, 2467abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev "Could not truncate output file to required size: %s (%d)\n", 2477abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev strerror(errno), errno); 2487abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2497abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("Memory mapping output file %s\n", outfile); 2507abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev out = mmap(0, outsize, PROT_WRITE, MAP_SHARED, ofd, 0); 2517abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev FAILIF(out == MAP_FAILED, "could not mmap output file: %s (%d)\n", 2527abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev strerror(errno), errno); 2537abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2547abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("PPM header (%d) bytes:\n%s\n", header_size, header); 2557abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev FAILIF(write(ofd, header, header_size) != header_size, 2567abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev "Error wrinting PPM header: %s (%d)\n", 2577abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev strerror(errno), errno); 2587abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2597abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("Converting %dx%d YUV 4:2:0 to RGB24...\n", width, height); 2607abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev color_convert_common(in, in + width * height, 2617abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev width, height, 2627abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev out + header_size, outsize - header_size, 2637abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev gray, rotate, 2647abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev type == CONVERT_TYPE_ARGB ? argb_cb : rgb24_cb); 2657abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev} 2667abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2677abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevint verbose_flag; 2687abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevint quiet_flag; 2697abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2707abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchevint main(int argc, char **argv) { 2717abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2727abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev char *infile, *outfile, *type; 2737abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int height, width, gray, rotate; 2747abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int cmdline_error = 0; 2757abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2767abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev /* Parse command-line arguments. */ 2777abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2787abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int first = get_options(argc, argv, 2797abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev &outfile, 2807abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev &height, 2817abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev &width, 2827abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev &gray, 2837abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev &type, 2847abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev &rotate, 2857abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev &verbose_flag); 2867abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 2877abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev if (first == argc) { 2887abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ERROR("You must specify an input file!\n"); 2897abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev cmdline_error++; 2907abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 2917abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev if (!outfile) { 2927abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ERROR("You must specify an output file!\n"); 2937abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev cmdline_error++; 2947abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 2957abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev if (height < 0 || width < 0) { 2967abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev ERROR("You must specify both image height and width!\n"); 2977abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev cmdline_error++; 2987abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 2997abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 3007abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev FAILIF(rotate % 90, "Rotation angle must be a multiple of 90 degrees!\n"); 3017abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 3027abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev rotate /= 90; 3037abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev rotate %= 4; 3047abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev if (rotate < 0) rotate += 4; 3057abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 3067abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev if (cmdline_error) { 3077abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev print_help(argv[0]); 3087abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev exit(1); 3097abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev } 3107abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 3117abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev infile = argv[first]; 3127abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 3137abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("input file: [%s]\n", infile); 3147abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("output file: [%s]\n", outfile); 3157abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("height: %d\n", height); 3167abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("width: %d\n", width); 3177abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("gray only: %d\n", gray); 3187abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("encode as: %s\n", type); 3197abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev INFO("rotation: %d\n", rotate); 3207abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 3217abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev /* Convert the image */ 3227abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 3237abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev int conv_type; 3247abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev if (!type || !strcmp(type, "ppm")) 3257abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev conv_type = CONVERT_TYPE_PPM; 3267abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev else if (!strcmp(type, "rgb")) 3277abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev conv_type = CONVERT_TYPE_RGB; 3287abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev else if (!strcmp(type, "argb")) 3297abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev conv_type = CONVERT_TYPE_ARGB; 3307abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev else FAILIF(1, "Unknown encoding type %s.\n", type); 3317abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 3327abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev convert(infile, outfile, 3337abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev height, width, gray, 3347abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev conv_type, 3357abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev rotate); 3367abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev 3377abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev free(outfile); 3387abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev return 0; 3397abfb48551224ac2b4a8d1820c023915e31ffb5fIliyan Malchev} 340