Pack.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. /*
  2. * The Python Imaging Library.
  3. * $Id$
  4. *
  5. * code to pack raw data
  6. *
  7. * history:
  8. * 1996-04-30 fl Created
  9. * 1996-05-12 fl Published a few RGB packers
  10. * 1996-11-01 fl More RGB packers (Tk booster stuff)
  11. * 1996-12-30 fl Added P;1, P;2 and P;4 packers
  12. * 1997-06-02 fl Added F (F;32NF) packer
  13. * 1997-08-28 fl Added 1 as L packer
  14. * 1998-02-08 fl Added I packer
  15. * 1998-03-09 fl Added mode field, RGBA/RGBX as RGB packers
  16. * 1998-07-01 fl Added YCbCr support
  17. * 1998-07-12 fl Added I 16 packer
  18. * 1999-02-03 fl Added BGR packers
  19. * 2003-09-26 fl Added LA/PA packers
  20. * 2006-06-22 fl Added CMYK;I packer
  21. *
  22. * Copyright (c) 1997-2006 by Secret Labs AB.
  23. * Copyright (c) 1996-1997 by Fredrik Lundh.
  24. *
  25. * See the README file for information on usage and redistribution.
  26. */
  27. #include "Imaging.h"
  28. #define R 0
  29. #define G 1
  30. #define B 2
  31. #define X 3
  32. #define A 3
  33. #define C 0
  34. #define M 1
  35. #define Y 2
  36. #define K 3
  37. /* byte swapping macros */
  38. #define C16N (out[0] = tmp[0], out[1] = tmp[1]);
  39. #define C16S (out[1] = tmp[0], out[0] = tmp[1]);
  40. #define C32N (out[0] = tmp[0], out[1] = tmp[1], out[2] = tmp[2], out[3] = tmp[3]);
  41. #define C32S (out[3] = tmp[0], out[2] = tmp[1], out[1] = tmp[2], out[0] = tmp[3]);
  42. #define C64N \
  43. (out[0] = tmp[0], \
  44. out[1] = tmp[1], \
  45. out[2] = tmp[2], \
  46. out[3] = tmp[3], \
  47. out[4] = tmp[4], \
  48. out[5] = tmp[5], \
  49. out[6] = tmp[6], \
  50. out[7] = tmp[7]);
  51. #define C64S \
  52. (out[7] = tmp[0], \
  53. out[6] = tmp[1], \
  54. out[5] = tmp[2], \
  55. out[4] = tmp[3], \
  56. out[3] = tmp[4], \
  57. out[2] = tmp[5], \
  58. out[1] = tmp[6], \
  59. out[0] = tmp[7]);
  60. #ifdef WORDS_BIGENDIAN
  61. #define C16B C16N
  62. #define C16L C16S
  63. #define C32B C32N
  64. #define C32L C32S
  65. #define C64B C64N
  66. #define C64L C64S
  67. #else
  68. #define C16B C16S
  69. #define C16L C16N
  70. #define C32B C32S
  71. #define C32L C32N
  72. #define C64B C64S
  73. #define C64L C64N
  74. #endif
  75. static void
  76. pack1(UINT8 *out, const UINT8 *in, int pixels) {
  77. int i, m, b;
  78. /* bilevel (black is 0) */
  79. b = 0;
  80. m = 128;
  81. for (i = 0; i < pixels; i++) {
  82. if (in[i] != 0) {
  83. b |= m;
  84. }
  85. m >>= 1;
  86. if (m == 0) {
  87. *out++ = b;
  88. b = 0;
  89. m = 128;
  90. }
  91. }
  92. if (m != 128) {
  93. *out++ = b;
  94. }
  95. }
  96. static void
  97. pack1I(UINT8 *out, const UINT8 *in, int pixels) {
  98. int i, m, b;
  99. /* bilevel (black is 1) */
  100. b = 0;
  101. m = 128;
  102. for (i = 0; i < pixels; i++) {
  103. if (in[i] == 0) {
  104. b |= m;
  105. }
  106. m >>= 1;
  107. if (m == 0) {
  108. *out++ = b;
  109. b = 0;
  110. m = 128;
  111. }
  112. }
  113. if (m != 128) {
  114. *out++ = b;
  115. }
  116. }
  117. static void
  118. pack1R(UINT8 *out, const UINT8 *in, int pixels) {
  119. int i, m, b;
  120. /* bilevel, lsb first (black is 0) */
  121. b = 0;
  122. m = 1;
  123. for (i = 0; i < pixels; i++) {
  124. if (in[i] != 0) {
  125. b |= m;
  126. }
  127. m <<= 1;
  128. if (m == 256) {
  129. *out++ = b;
  130. b = 0;
  131. m = 1;
  132. }
  133. }
  134. if (m != 1) {
  135. *out++ = b;
  136. }
  137. }
  138. static void
  139. pack1IR(UINT8 *out, const UINT8 *in, int pixels) {
  140. int i, m, b;
  141. /* bilevel, lsb first (black is 1) */
  142. b = 0;
  143. m = 1;
  144. for (i = 0; i < pixels; i++) {
  145. if (in[i] == 0) {
  146. b |= m;
  147. }
  148. m <<= 1;
  149. if (m == 256) {
  150. *out++ = b;
  151. b = 0;
  152. m = 1;
  153. }
  154. }
  155. if (m != 1) {
  156. *out++ = b;
  157. }
  158. }
  159. static void
  160. pack1L(UINT8 *out, const UINT8 *in, int pixels) {
  161. int i;
  162. /* bilevel, stored as bytes */
  163. for (i = 0; i < pixels; i++) {
  164. out[i] = (in[i] != 0) ? 255 : 0;
  165. }
  166. }
  167. static void
  168. packP4(UINT8 *out, const UINT8 *in, int pixels) {
  169. while (pixels >= 2) {
  170. *out++ = (in[0] << 4) | (in[1] & 15);
  171. in += 2;
  172. pixels -= 2;
  173. }
  174. if (pixels) {
  175. out[0] = (in[0] << 4);
  176. }
  177. }
  178. static void
  179. packP2(UINT8 *out, const UINT8 *in, int pixels) {
  180. while (pixels >= 4) {
  181. *out++ = (in[0] << 6) | ((in[1] & 3) << 4) | ((in[2] & 3) << 2) | (in[3] & 3);
  182. in += 4;
  183. pixels -= 4;
  184. }
  185. switch (pixels) {
  186. case 3:
  187. out[0] = (in[0] << 6) | ((in[1] & 3) << 4) | ((in[2] & 3) << 2);
  188. break;
  189. case 2:
  190. out[0] = (in[0] << 6) | ((in[1] & 3) << 4);
  191. break;
  192. case 1:
  193. out[0] = (in[0] << 6);
  194. }
  195. }
  196. static void
  197. packL16(UINT8 *out, const UINT8 *in, int pixels) {
  198. int i;
  199. /* L -> L;16, e.g: \xff77 -> \x00\xff\x00\x77 */
  200. for (i = 0; i < pixels; i++) {
  201. out[0] = 0;
  202. out[1] = in[i];
  203. out += 2;
  204. }
  205. }
  206. static void
  207. packL16B(UINT8 *out, const UINT8 *in, int pixels) {
  208. int i;
  209. /* L -> L;16B, e.g: \xff77 -> \xff\x00\x77\x00 */
  210. for (i = 0; i < pixels; i++) {
  211. out[0] = in[i];
  212. out[1] = 0;
  213. out += 2;
  214. }
  215. }
  216. static void
  217. packLA(UINT8 *out, const UINT8 *in, int pixels) {
  218. int i;
  219. /* LA, pixel interleaved */
  220. for (i = 0; i < pixels; i++) {
  221. out[0] = in[R];
  222. out[1] = in[A];
  223. out += 2;
  224. in += 4;
  225. }
  226. }
  227. static void
  228. packLAL(UINT8 *out, const UINT8 *in, int pixels) {
  229. int i;
  230. /* LA, line interleaved */
  231. for (i = 0; i < pixels; i++) {
  232. out[i] = in[R];
  233. out[i + pixels] = in[A];
  234. in += 4;
  235. }
  236. }
  237. void
  238. ImagingPackRGB(UINT8 *out, const UINT8 *in, int pixels) {
  239. int i = 0;
  240. /* RGB triplets */
  241. #ifdef __sparc
  242. /* SPARC CPUs cannot read integers from nonaligned addresses. */
  243. for (; i < pixels; i++) {
  244. out[0] = in[R];
  245. out[1] = in[G];
  246. out[2] = in[B];
  247. out += 3;
  248. in += 4;
  249. }
  250. #else
  251. for (; i < pixels - 1; i++) {
  252. memcpy(out, in + i * 4, 4);
  253. out += 3;
  254. }
  255. for (; i < pixels; i++) {
  256. out[0] = in[i * 4 + R];
  257. out[1] = in[i * 4 + G];
  258. out[2] = in[i * 4 + B];
  259. out += 3;
  260. }
  261. #endif
  262. }
  263. void
  264. ImagingPackXRGB(UINT8 *out, const UINT8 *in, int pixels) {
  265. int i;
  266. /* XRGB, triplets with left padding */
  267. for (i = 0; i < pixels; i++) {
  268. out[0] = 0;
  269. out[1] = in[R];
  270. out[2] = in[G];
  271. out[3] = in[B];
  272. out += 4;
  273. in += 4;
  274. }
  275. }
  276. void
  277. ImagingPackBGR(UINT8 *out, const UINT8 *in, int pixels) {
  278. int i;
  279. /* RGB, reversed bytes */
  280. for (i = 0; i < pixels; i++) {
  281. out[0] = in[B];
  282. out[1] = in[G];
  283. out[2] = in[R];
  284. out += 3;
  285. in += 4;
  286. }
  287. }
  288. void
  289. ImagingPackBGRX(UINT8 *out, const UINT8 *in, int pixels) {
  290. int i;
  291. /* BGRX, reversed bytes with right padding */
  292. for (i = 0; i < pixels; i++) {
  293. out[0] = in[B];
  294. out[1] = in[G];
  295. out[2] = in[R];
  296. out[3] = 0;
  297. out += 4;
  298. in += 4;
  299. }
  300. }
  301. void
  302. ImagingPackXBGR(UINT8 *out, const UINT8 *in, int pixels) {
  303. int i;
  304. /* XBGR, reversed bytes with left padding */
  305. for (i = 0; i < pixels; i++) {
  306. out[0] = 0;
  307. out[1] = in[B];
  308. out[2] = in[G];
  309. out[3] = in[R];
  310. out += 4;
  311. in += 4;
  312. }
  313. }
  314. void
  315. ImagingPackBGRA(UINT8 *out, const UINT8 *in, int pixels) {
  316. int i;
  317. /* BGRX, reversed bytes with right padding */
  318. for (i = 0; i < pixels; i++) {
  319. out[0] = in[B];
  320. out[1] = in[G];
  321. out[2] = in[R];
  322. out[3] = in[A];
  323. out += 4;
  324. in += 4;
  325. }
  326. }
  327. void
  328. ImagingPackABGR(UINT8 *out, const UINT8 *in, int pixels) {
  329. int i;
  330. /* XBGR, reversed bytes with left padding */
  331. for (i = 0; i < pixels; i++) {
  332. out[0] = in[A];
  333. out[1] = in[B];
  334. out[2] = in[G];
  335. out[3] = in[R];
  336. out += 4;
  337. in += 4;
  338. }
  339. }
  340. void
  341. ImagingPackBGRa(UINT8 *out, const UINT8 *in, int pixels) {
  342. int i;
  343. /* BGRa, reversed bytes with premultiplied alpha */
  344. for (i = 0; i < pixels; i++) {
  345. int alpha = out[3] = in[A];
  346. int tmp;
  347. out[0] = MULDIV255(in[B], alpha, tmp);
  348. out[1] = MULDIV255(in[G], alpha, tmp);
  349. out[2] = MULDIV255(in[R], alpha, tmp);
  350. out += 4;
  351. in += 4;
  352. }
  353. }
  354. static void
  355. packRGBL(UINT8 *out, const UINT8 *in, int pixels) {
  356. int i;
  357. /* RGB, line interleaved */
  358. for (i = 0; i < pixels; i++) {
  359. out[i] = in[R];
  360. out[i + pixels] = in[G];
  361. out[i + pixels + pixels] = in[B];
  362. in += 4;
  363. }
  364. }
  365. static void
  366. packRGBXL(UINT8 *out, const UINT8 *in, int pixels) {
  367. int i;
  368. /* RGBX, line interleaved */
  369. for (i = 0; i < pixels; i++) {
  370. out[i] = in[R];
  371. out[i + pixels] = in[G];
  372. out[i + pixels + pixels] = in[B];
  373. out[i + pixels + pixels + pixels] = in[X];
  374. in += 4;
  375. }
  376. }
  377. static void
  378. packI16B(UINT8 *out, const UINT8 *in_, int pixels) {
  379. int i;
  380. UINT16 tmp_;
  381. UINT8 *tmp = (UINT8 *)&tmp_;
  382. for (i = 0; i < pixels; i++) {
  383. INT32 in;
  384. memcpy(&in, in_, sizeof(in));
  385. if (in <= 0) {
  386. tmp_ = 0;
  387. } else if (in > 65535) {
  388. tmp_ = 65535;
  389. } else {
  390. tmp_ = in;
  391. }
  392. C16B;
  393. out += 2;
  394. in_ += sizeof(in);
  395. }
  396. }
  397. static void
  398. packI16N_I16B(UINT8 *out, const UINT8 *in, int pixels) {
  399. int i;
  400. UINT8 *tmp = (UINT8 *)in;
  401. for (i = 0; i < pixels; i++) {
  402. C16B;
  403. out += 2;
  404. tmp += 2;
  405. }
  406. }
  407. static void
  408. packI16N_I16(UINT8 *out, const UINT8 *in, int pixels) {
  409. int i;
  410. UINT8 *tmp = (UINT8 *)in;
  411. for (i = 0; i < pixels; i++) {
  412. C16L;
  413. out += 2;
  414. tmp += 2;
  415. }
  416. }
  417. static void
  418. packI32S(UINT8 *out, const UINT8 *in, int pixels) {
  419. int i;
  420. UINT8 *tmp = (UINT8 *)in;
  421. for (i = 0; i < pixels; i++) {
  422. C32L;
  423. out += 4;
  424. tmp += 4;
  425. }
  426. }
  427. void
  428. ImagingPackLAB(UINT8 *out, const UINT8 *in, int pixels) {
  429. int i;
  430. /* LAB triplets */
  431. for (i = 0; i < pixels; i++) {
  432. out[0] = in[0];
  433. out[1] = in[1] ^ 128; /* signed in outside world */
  434. out[2] = in[2] ^ 128;
  435. out += 3;
  436. in += 4;
  437. }
  438. }
  439. static void
  440. copy1(UINT8 *out, const UINT8 *in, int pixels) {
  441. /* L, P */
  442. memcpy(out, in, pixels);
  443. }
  444. static void
  445. copy2(UINT8 *out, const UINT8 *in, int pixels) {
  446. /* I;16, etc */
  447. memcpy(out, in, pixels * 2);
  448. }
  449. static void
  450. copy3(UINT8 *out, const UINT8 *in, int pixels) {
  451. /* BGR;24, etc */
  452. memcpy(out, in, pixels * 3);
  453. }
  454. static void
  455. copy4(UINT8 *out, const UINT8 *in, int pixels) {
  456. /* RGBA, CMYK quadruples */
  457. memcpy(out, in, 4 * pixels);
  458. }
  459. static void
  460. copy4I(UINT8 *out, const UINT8 *in, int pixels) {
  461. /* RGBA, CMYK quadruples, inverted */
  462. int i;
  463. for (i = 0; i < pixels * 4; i++) {
  464. out[i] = ~in[i];
  465. }
  466. }
  467. static void
  468. band0(UINT8 *out, const UINT8 *in, int pixels) {
  469. int i;
  470. for (i = 0; i < pixels; i++, in += 4) {
  471. out[i] = in[0];
  472. }
  473. }
  474. static void
  475. band1(UINT8 *out, const UINT8 *in, int pixels) {
  476. int i;
  477. for (i = 0; i < pixels; i++, in += 4) {
  478. out[i] = in[1];
  479. }
  480. }
  481. static void
  482. band2(UINT8 *out, const UINT8 *in, int pixels) {
  483. int i;
  484. for (i = 0; i < pixels; i++, in += 4) {
  485. out[i] = in[2];
  486. }
  487. }
  488. static void
  489. band3(UINT8 *out, const UINT8 *in, int pixels) {
  490. int i;
  491. for (i = 0; i < pixels; i++, in += 4) {
  492. out[i] = in[3];
  493. }
  494. }
  495. static struct {
  496. const char *mode;
  497. const char *rawmode;
  498. int bits;
  499. ImagingShuffler pack;
  500. } packers[] = {
  501. /* bilevel */
  502. {"1", "1", 1, pack1},
  503. {"1", "1;I", 1, pack1I},
  504. {"1", "1;R", 1, pack1R},
  505. {"1", "1;IR", 1, pack1IR},
  506. {"1", "L", 8, pack1L},
  507. /* grayscale */
  508. {"L", "L", 8, copy1},
  509. {"L", "L;16", 16, packL16},
  510. {"L", "L;16B", 16, packL16B},
  511. /* grayscale w. alpha */
  512. {"LA", "LA", 16, packLA},
  513. {"LA", "LA;L", 16, packLAL},
  514. /* grayscale w. alpha premultiplied */
  515. {"La", "La", 16, packLA},
  516. /* palette */
  517. {"P", "P;1", 1, pack1},
  518. {"P", "P;2", 2, packP2},
  519. {"P", "P;4", 4, packP4},
  520. {"P", "P", 8, copy1},
  521. /* palette w. alpha */
  522. {"PA", "PA", 16, packLA},
  523. {"PA", "PA;L", 16, packLAL},
  524. /* true colour */
  525. {"RGB", "RGB", 24, ImagingPackRGB},
  526. {"RGB", "RGBX", 32, copy4},
  527. {"RGB", "RGBA", 32, copy4},
  528. {"RGB", "XRGB", 32, ImagingPackXRGB},
  529. {"RGB", "BGR", 24, ImagingPackBGR},
  530. {"RGB", "BGRX", 32, ImagingPackBGRX},
  531. {"RGB", "XBGR", 32, ImagingPackXBGR},
  532. {"RGB", "RGB;L", 24, packRGBL},
  533. {"RGB", "R", 8, band0},
  534. {"RGB", "G", 8, band1},
  535. {"RGB", "B", 8, band2},
  536. /* true colour w. alpha */
  537. {"RGBA", "RGBA", 32, copy4},
  538. {"RGBA", "RGBA;L", 32, packRGBXL},
  539. {"RGBA", "RGB", 24, ImagingPackRGB},
  540. {"RGBA", "BGR", 24, ImagingPackBGR},
  541. {"RGBA", "BGRA", 32, ImagingPackBGRA},
  542. {"RGBA", "ABGR", 32, ImagingPackABGR},
  543. {"RGBA", "BGRa", 32, ImagingPackBGRa},
  544. {"RGBA", "R", 8, band0},
  545. {"RGBA", "G", 8, band1},
  546. {"RGBA", "B", 8, band2},
  547. {"RGBA", "A", 8, band3},
  548. /* true colour w. alpha premultiplied */
  549. {"RGBa", "RGBa", 32, copy4},
  550. {"RGBa", "BGRa", 32, ImagingPackBGRA},
  551. {"RGBa", "aBGR", 32, ImagingPackABGR},
  552. /* true colour w. padding */
  553. {"RGBX", "RGBX", 32, copy4},
  554. {"RGBX", "RGBX;L", 32, packRGBXL},
  555. {"RGBX", "RGB", 24, ImagingPackRGB},
  556. {"RGBX", "BGR", 24, ImagingPackBGR},
  557. {"RGBX", "BGRX", 32, ImagingPackBGRX},
  558. {"RGBX", "XBGR", 32, ImagingPackXBGR},
  559. {"RGBX", "R", 8, band0},
  560. {"RGBX", "G", 8, band1},
  561. {"RGBX", "B", 8, band2},
  562. {"RGBX", "X", 8, band3},
  563. /* colour separation */
  564. {"CMYK", "CMYK", 32, copy4},
  565. {"CMYK", "CMYK;I", 32, copy4I},
  566. {"CMYK", "CMYK;L", 32, packRGBXL},
  567. {"CMYK", "C", 8, band0},
  568. {"CMYK", "M", 8, band1},
  569. {"CMYK", "Y", 8, band2},
  570. {"CMYK", "K", 8, band3},
  571. /* video (YCbCr) */
  572. {"YCbCr", "YCbCr", 24, ImagingPackRGB},
  573. {"YCbCr", "YCbCr;L", 24, packRGBL},
  574. {"YCbCr", "YCbCrX", 32, copy4},
  575. {"YCbCr", "YCbCrK", 32, copy4},
  576. {"YCbCr", "Y", 8, band0},
  577. {"YCbCr", "Cb", 8, band1},
  578. {"YCbCr", "Cr", 8, band2},
  579. /* LAB Color */
  580. {"LAB", "LAB", 24, ImagingPackLAB},
  581. {"LAB", "L", 8, band0},
  582. {"LAB", "A", 8, band1},
  583. {"LAB", "B", 8, band2},
  584. /* HSV */
  585. {"HSV", "HSV", 24, ImagingPackRGB},
  586. {"HSV", "H", 8, band0},
  587. {"HSV", "S", 8, band1},
  588. {"HSV", "V", 8, band2},
  589. /* integer */
  590. {"I", "I", 32, copy4},
  591. {"I", "I;16B", 16, packI16B},
  592. {"I", "I;32S", 32, packI32S},
  593. {"I", "I;32NS", 32, copy4},
  594. /* floating point */
  595. {"F", "F", 32, copy4},
  596. {"F", "F;32F", 32, packI32S},
  597. {"F", "F;32NF", 32, copy4},
  598. /* storage modes */
  599. {"I;16", "I;16", 16, copy2},
  600. #ifdef WORDS_BIGENDIAN
  601. {"I;16", "I;16B", 16, packI16N_I16},
  602. #else
  603. {"I;16", "I;16B", 16, packI16N_I16B},
  604. #endif
  605. {"I;16B", "I;16B", 16, copy2},
  606. {"I;16L", "I;16L", 16, copy2},
  607. {"I;16N", "I;16N", 16, copy2},
  608. {"I;16", "I;16N", 16, packI16N_I16}, // LibTiff native->image endian.
  609. {"I;16L", "I;16N", 16, packI16N_I16},
  610. {"I;16B", "I;16N", 16, packI16N_I16B},
  611. {"BGR;15", "BGR;15", 16, copy2},
  612. {"BGR;16", "BGR;16", 16, copy2},
  613. {"BGR;24", "BGR;24", 24, copy3},
  614. {NULL} /* sentinel */
  615. };
  616. ImagingShuffler
  617. ImagingFindPacker(const char *mode, const char *rawmode, int *bits_out) {
  618. int i;
  619. /* find a suitable pixel packer */
  620. for (i = 0; packers[i].rawmode; i++) {
  621. if (strcmp(packers[i].mode, mode) == 0 &&
  622. strcmp(packers[i].rawmode, rawmode) == 0) {
  623. if (bits_out) {
  624. *bits_out = packers[i].bits;
  625. }
  626. return packers[i].pack;
  627. }
  628. }
  629. return NULL;
  630. }