readyuv.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. enum {
  9. pixels = 720,
  10. r601pal = 576,
  11. r601ntsc = 486,
  12. Shift = 13
  13. };
  14. static int lsbtab[] = { 6, 4, 2, 0};
  15. int
  16. looksize(char *file, vlong size, int *pixels, int *lines, int *bits)
  17. {
  18. Biobuf *bp;
  19. uvlong l, p;
  20. char *s, *a[12];
  21. /*
  22. * This may not always work, there could be an alias between file
  23. * sizes of different standards stored in 8bits and 10 bits.
  24. */
  25. if ((bp = Bopen(file, OREAD)) == nil)
  26. return -1;
  27. while((s = Brdstr(bp, '\n', 1)) != nil){
  28. if (tokenize(s, a, nelem(a)) < 3)
  29. continue;
  30. if (a[0][0] == '#')
  31. continue;
  32. p = atoll(a[3]);
  33. l = atoll(a[5]);
  34. if (l*p*2 == size){
  35. *pixels = p;
  36. *lines = l;
  37. *bits = 8;
  38. break;
  39. }
  40. if ((l*p*20)/8 == size){
  41. *pixels = p;
  42. *lines = l;
  43. *bits = 10;
  44. break;
  45. }
  46. }
  47. Bterm(bp);
  48. if (s == nil)
  49. return -1;
  50. return 0;
  51. }
  52. static int
  53. clip(int x)
  54. {
  55. x >>= (Shift+2); // +2 as we assume all input images are 10 bit
  56. if (x > 255)
  57. return 0xff;
  58. if (x <= 0)
  59. return 0;
  60. return x;
  61. }
  62. Rawimage**
  63. Breadyuv(Biobuf *bp, int colourspace)
  64. {
  65. Dir *d;
  66. uvlong sz;
  67. Rawimage *a, **array;
  68. char *e, ebuf[128];
  69. ushort * mux, *end, *frm;
  70. uchar *buf, *r, *g, *b;
  71. int y1, y2, cb, cr, c, l, w, base;
  72. int bits, lines, pixels;
  73. int F1, F2, F3, F4;
  74. frm = nil;
  75. buf = nil;
  76. if (colourspace != CYCbCr) {
  77. errstr(ebuf, sizeof ebuf); /* throw it away */
  78. werrstr("ReadYUV: unknown colour space %d", colourspace);
  79. return nil;
  80. }
  81. if ((a = calloc(sizeof(Rawimage), 1)) == nil)
  82. sysfatal("no memory");
  83. if ((array = calloc(sizeof(Rawimage * ), 2)) == nil)
  84. sysfatal("no memory");
  85. array[0] = a;
  86. array[1] = nil;
  87. if ((d = dirfstat(Bfildes(bp))) != nil) {
  88. sz = d->length;
  89. free(d);
  90. } else {
  91. fprint(2, "cannot stat input, assuming pixelsx576x10bit\n");
  92. sz = pixels * r601pal * 2L + (pixels * r601pal / 2L);
  93. }
  94. if (looksize("/lib/video.specs", sz, &pixels, &lines, &bits) == -1){
  95. e = "file size not listed in /lib/video.specs";
  96. goto Error;
  97. }
  98. a->nchans = 3;
  99. a->chandesc = CRGB;
  100. a->chanlen = pixels * lines;
  101. a->r = Rect(0, 0, pixels, lines);
  102. e = "no memory";
  103. if ((frm = malloc(pixels*2*lines*sizeof(ushort))) == nil)
  104. goto Error;
  105. for (c = 0; c < 3; c++)
  106. if ((a->chans[c] = malloc(pixels*lines)) == nil)
  107. goto Error;
  108. if ((buf = malloc(pixels*2)) == nil)
  109. goto Error;
  110. e = "read file";
  111. for (l = 0; l < lines; l++) {
  112. if (Bread(bp, buf, pixels *2) == -1)
  113. goto Error;
  114. base = l*pixels*2;
  115. for (w = 0; w < pixels *2; w++)
  116. frm[base + w] = ((ushort)buf[w]) << 2;
  117. }
  118. if (bits == 10)
  119. for (l = 0; l < lines; l++) {
  120. if (Bread(bp, buf, pixels / 2) == -1)
  121. goto Error;
  122. base = l * pixels * 2;
  123. for (w = 0; w < pixels * 2; w++)
  124. frm[base + w] |= (buf[w / 4] >> lsbtab[w % 4]) & 3;
  125. }
  126. mux = frm;
  127. end = frm + pixels * lines * 2;
  128. r = a->chans[0];
  129. g = a->chans[1];
  130. b = a->chans[2];
  131. if(pixels * lines != 414720){ // 625
  132. F1 = floor(1.402 * (1 << Shift));
  133. F2 = floor(0.34414 * (1 << Shift));
  134. F3 = floor(0.71414 * (1 << Shift));
  135. F4 = floor(1.772 * (1 << Shift));
  136. }
  137. else{ // 525
  138. F1 = floor(1.5748 * (1 << Shift));
  139. F2 = floor(0.1874 * (1 << Shift));
  140. F3 = floor(0.4681 * (1 << Shift));
  141. F4 = floor(1.8560 * (1 << Shift));
  142. }
  143. /*
  144. * Fixme: fixed colourspace conversion at present
  145. */
  146. while (mux < end) {
  147. cb = *mux++ - 512;
  148. y1 = (int)*mux++ << Shift;
  149. cr = *mux++ - 512;
  150. y2 = (int)*mux++ << Shift;
  151. *r++ = clip(y1 + F1*cr);
  152. *g++ = clip(y1 - F2*cb - F3*cr);
  153. *b++ = clip((y1 + F4*cb));
  154. *r++ = clip(y2 + F1*cr);
  155. *g++ = clip(y2 - F2*cb - F3*cr);
  156. *b++ = clip((y2 + F4*cb));
  157. }
  158. free(frm);
  159. free(buf);
  160. return array;
  161. Error:
  162. errstr(ebuf, sizeof ebuf);
  163. // if (ebuf[0] == 0)
  164. strcpy(ebuf, e);
  165. errstr(ebuf, sizeof ebuf);
  166. for (c = 0; c < 3; c++)
  167. free(a->chans[c]);
  168. free(a->cmap);
  169. free(array[0]);
  170. free(array);
  171. free(frm);
  172. free(buf);
  173. return nil;
  174. }
  175. Rawimage**
  176. readyuv(int fd, int colorspace)
  177. {
  178. Rawimage * *a;
  179. Biobuf b;
  180. if (Binit(&b, fd, OREAD) < 0)
  181. return nil;
  182. a = Breadyuv(&b, colorspace);
  183. Bterm(&b);
  184. return a;
  185. }