readyuv.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /* readyuv.c - read an Abekas A66 style image file. Steve Simon, 2003 */
  2. #include <u.h>
  3. #include <libc.h>
  4. #include <bio.h>
  5. #include <draw.h>
  6. #include <ctype.h>
  7. #include "imagefile.h"
  8. /*
  9. * ITU/CCIR Rec601 states:
  10. *
  11. * R = y + 1.402 * Cr
  12. * B = Y + 1.77305 * Cb
  13. * G = Y - 0.72414 * Cr - 0.34414 * Cb
  14. *
  15. * using 8 bit traffic
  16. * Y = 16 + 219 * Y
  17. * Cr = 128 + 224 * Cr
  18. * Cb = 128 + 224 * Cb
  19. * or, if 10bit is used
  20. * Y = 64 + 876 * Y
  21. * Cr = 512 + 896 * Cr
  22. * Cb = 512 + 896 * Cb
  23. */
  24. enum {
  25. PAL = 576, NTSC = 486 };
  26. static int lsbtab[] = { 6, 4, 2, 0};
  27. static int
  28. clip(int x)
  29. {
  30. x >>= 18;
  31. if (x > 255)
  32. return 0xff;
  33. if (x <= 0)
  34. return 0;
  35. return x;
  36. }
  37. Rawimage**
  38. Breadyuv(Biobuf *bp, int colourspace)
  39. {
  40. Dir * d;
  41. Rawimage * a, **array;
  42. char *e, ebuf[128];
  43. ushort * mux, *end, *frm;
  44. uchar buf[720 * 2], *r, *g, *b;
  45. int y1, y2, cb, cr, sz, c, l, w, base, bits, lines;
  46. frm = 0;
  47. if (colourspace != CYCbCr) {
  48. errstr(ebuf, sizeof ebuf); /* throw it away */
  49. werrstr("ReadYUV: unknown colour space %d", colourspace);
  50. return nil;
  51. }
  52. if ((a = calloc(sizeof(Rawimage), 1)) == nil)
  53. sysfatal("no memory");
  54. if ((array = calloc(sizeof(Rawimage * ), 2)) == nil)
  55. sysfatal("no memory");
  56. array[0] = a;
  57. array[1] = nil;
  58. if ((d = dirfstat(Bfildes(bp))) != nil) {
  59. sz = d->length;
  60. free(d);
  61. } else {
  62. fprint(2, "cannot stat input, assuming 720x576x10bit\n");
  63. sz = 720 * PAL * 2L + (720 * PAL / 2L);
  64. }
  65. switch (sz) {
  66. case 720 * PAL * 2: // 625 x 8bit
  67. bits = 8;
  68. lines = PAL;
  69. break;
  70. case 720 * NTSC * 2: // 525 x 8bit
  71. bits = 8;
  72. lines = NTSC;
  73. break;
  74. case 720 * PAL * 2 + (720 * PAL / 2) : // 625 x 10bit
  75. bits = 10;
  76. lines = PAL;
  77. break;
  78. case 720 * NTSC * 2 + (720 * NTSC / 2) : // 525 x 10bit
  79. bits = 10;
  80. lines = NTSC;
  81. break;
  82. default:
  83. e = "unknown file size";
  84. goto Error;
  85. }
  86. // print("bits=%d pixels=%d lines=%d\n", bits, 720, lines);
  87. //
  88. a->nchans = 3;
  89. a->chandesc = CRGB;
  90. a->chanlen = 720 * lines;
  91. a->r = Rect(0, 0, 720, lines);
  92. e = "no memory";
  93. if ((frm = malloc(720 * 2 * lines * sizeof(ushort))) == nil)
  94. goto Error;
  95. for (c = 0; c < 3; c++)
  96. if ((a->chans[c] = malloc(720 * lines)) == nil)
  97. goto Error;
  98. e = "read file";
  99. for (l = 0; l < lines; l++) {
  100. if (Bread(bp, buf, 720 * 2) == -1)
  101. goto Error;
  102. base = l * 720 * 2;
  103. for (w = 0; w < 720 * 2; w++)
  104. frm[base + w] = ((ushort)buf[w]) << 2;
  105. }
  106. if (bits == 10)
  107. for (l = 0; l < lines; l++) {
  108. if (Bread(bp, buf, 720 / 2) == -1)
  109. goto Error;
  110. base = l * 720 * 2;
  111. for (w = 0; w < 720 * 2; w++)
  112. frm[base + w] |= buf[w / 4] >> lsbtab[w % 4];
  113. }
  114. mux = frm;
  115. end = frm + 720 * lines * 2;
  116. r = a->chans[0];
  117. g = a->chans[1];
  118. b = a->chans[2];
  119. while (mux < end) {
  120. cb = *mux++ - 512;
  121. y1 = (*mux++ - 64) * 76310;
  122. cr = *mux++ - 512;
  123. y2 = (*mux++ - 64) * 76310;
  124. *r++ = clip((104635 * cr) + y1);
  125. *g++ = clip((-25690 * cb + -53294 * cr) + y1);
  126. *b++ = clip((132278 * cb) + y1);
  127. *r++ = clip((104635 * cr) + y2);
  128. *g++ = clip((-25690 * cb + -53294 * cr) + y2);
  129. *b++ = clip((132278 * cb) + y2);
  130. }
  131. free(frm);
  132. return array;
  133. Error:
  134. errstr(ebuf, sizeof ebuf);
  135. if (ebuf[0] == 0)
  136. strcpy(ebuf, e);
  137. errstr(ebuf, sizeof ebuf);
  138. for (c = 0; c < 3; c++)
  139. free(a->chans[c]);
  140. free(a->cmap);
  141. free(array[0]);
  142. free(array);
  143. free(frm);
  144. return nil;
  145. }
  146. Rawimage**
  147. readyuv(int fd, int colorspace)
  148. {
  149. Rawimage * *a;
  150. Biobuf b;
  151. if (Binit(&b, fd, OREAD) < 0)
  152. return nil;
  153. a = Breadyuv(&b, colorspace);
  154. Bterm(&b);
  155. return a;
  156. }