onechan.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. #include <memdraw.h>
  13. #include <bio.h>
  14. #include "imagefile.h"
  15. /* Convert image to a single channel, one byte per pixel */
  16. static
  17. int
  18. notrans(uint32_t chan)
  19. {
  20. switch(chan){
  21. case GREY1:
  22. case GREY2:
  23. case GREY4:
  24. case CMAP8:
  25. case GREY8:
  26. return 1;
  27. }
  28. return 0;
  29. }
  30. static
  31. int
  32. easycase(uint32_t chan)
  33. {
  34. switch(chan){
  35. case RGB16:
  36. case RGB24:
  37. case RGBA32:
  38. case ARGB32:
  39. return 1;
  40. }
  41. return 0;
  42. }
  43. /*
  44. * Convert to one byte per pixel, RGBV or grey, depending
  45. */
  46. static
  47. uint8_t*
  48. load(Image *image, Memimage *memimage)
  49. {
  50. uint8_t *data, *p, *q0, *q1, *q2;
  51. uint8_t *rgbv;
  52. int depth, ndata, dx, dy, i, v;
  53. uint32_t chan, pixel;
  54. Rectangle r;
  55. Rawimage ri, *nri;
  56. if(memimage == nil){
  57. r = image->r;
  58. depth = image->depth;
  59. chan = image->chan;
  60. }else{
  61. r = memimage->r;
  62. depth = memimage->depth;
  63. chan = memimage->chan;
  64. }
  65. dx = Dx(r);
  66. dy = Dy(r);
  67. /*
  68. * Read image data into memory
  69. * potentially one extra byte on each end of each scan line.
  70. */
  71. ndata = dy*(2+bytesperline(r, depth));
  72. data = malloc(ndata);
  73. if(data == nil)
  74. return nil;
  75. if(memimage != nil)
  76. ndata = unloadmemimage(memimage, r, data, ndata);
  77. else
  78. ndata = unloadimage(image, r, data, ndata);
  79. if(ndata < 0){
  80. werrstr("onechan: %r");
  81. free(data);
  82. return nil;
  83. }
  84. /*
  85. * Repack
  86. */
  87. memset(&ri, 0, sizeof(ri));
  88. ri.r = r;
  89. ri.cmap = nil;
  90. ri.cmaplen = 0;
  91. ri.nchans = 3;
  92. ri.chanlen = dx*dy;
  93. ri.chans[0] = malloc(ri.chanlen);
  94. ri.chans[1] = malloc(ri.chanlen);
  95. ri.chans[2] = malloc(ri.chanlen);
  96. if(ri.chans[0]==nil || ri.chans[1]==nil || ri.chans[2]==nil){
  97. Err:
  98. free(ri.chans[0]);
  99. free(ri.chans[1]);
  100. free(ri.chans[2]);
  101. free(data);
  102. return nil;
  103. }
  104. ri.chandesc = CRGB;
  105. p = data;
  106. q0 = ri.chans[0];
  107. q1 = ri.chans[1];
  108. q2 = ri.chans[2];
  109. switch(chan){
  110. default:
  111. werrstr("can't handle image type 0x%lx", chan);
  112. goto Err;
  113. case RGB16:
  114. for(i=0; i<ri.chanlen; i++, p+=2){
  115. pixel = (p[1]<<8)|p[0]; /* rrrrrggg gggbbbbb */
  116. v = (pixel & 0xF800) >> 8;
  117. *q0++ = v | (v>>5);
  118. v = (pixel & 0x07E0) >> 3;
  119. *q1++ = v | (v>>6);
  120. v = (pixel & 0x001F) << 3;
  121. *q2++ = v | (v>>5);
  122. }
  123. break;
  124. case RGB24:
  125. for(i=0; i<ri.chanlen; i++){
  126. *q2++ = *p++;
  127. *q1++ = *p++;
  128. *q0++ = *p++;
  129. }
  130. break;
  131. case RGBA32:
  132. for(i=0; i<ri.chanlen; i++){
  133. *q2++ = *p++;
  134. *q1++ = *p++;
  135. *q0++ = *p++;
  136. p++;
  137. }
  138. break;
  139. case ARGB32:
  140. for(i=0; i<ri.chanlen; i++){
  141. p++;
  142. *q2++ = *p++;
  143. *q1++ = *p++;
  144. *q0++ = *p++;
  145. }
  146. break;
  147. }
  148. rgbv = nil;
  149. nri = torgbv(&ri, 1);
  150. if(nri != nil){
  151. rgbv = nri->chans[0];
  152. free(nri);
  153. }
  154. free(ri.chans[0]);
  155. free(ri.chans[1]);
  156. free(ri.chans[2]);
  157. free(data);
  158. return rgbv;
  159. }
  160. Image*
  161. onechan(Image *i)
  162. {
  163. uint8_t *data;
  164. Image *ni;
  165. if(notrans(i->chan))
  166. return i;
  167. if(easycase(i->chan))
  168. data = load(i, nil);
  169. else{
  170. ni = allocimage(display, i->r, RGB24, 0, DNofill);
  171. if(ni == nil)
  172. return ni;
  173. draw(ni, ni->r, i, nil, i->r.min);
  174. data = load(ni, nil);
  175. freeimage(ni);
  176. }
  177. if(data == nil)
  178. return nil;
  179. ni = allocimage(display, i->r, CMAP8, 0, DNofill);
  180. if(ni != nil)
  181. if(loadimage(ni, ni->r, data, Dx(ni->r)*Dy(ni->r)) < 0){
  182. freeimage(ni);
  183. ni = nil;
  184. }
  185. free(data);
  186. return ni;
  187. }
  188. Memimage*
  189. memonechan(Memimage *i)
  190. {
  191. uint8_t *data;
  192. Memimage *ni;
  193. if(notrans(i->chan))
  194. return i;
  195. if(easycase(i->chan))
  196. data = load(nil, i);
  197. else{
  198. ni = allocmemimage(i->r, RGB24);
  199. if(ni == nil)
  200. return ni;
  201. memimagedraw(ni, ni->r, i, i->r.min, nil, ZP, S);
  202. data = load(nil, ni);
  203. freememimage(ni);
  204. }
  205. if(data == nil)
  206. return nil;
  207. ni = allocmemimage(i->r, CMAP8);
  208. if(ni != nil)
  209. if(loadmemimage(ni, ni->r, data, Dx(ni->r)*Dy(ni->r)) < 0){
  210. freememimage(ni);
  211. ni = nil;
  212. }
  213. free(data);
  214. return ni;
  215. }