Jpegfile.cpp
上传用户:gzboli
上传日期:2013-04-10
资源大小:471k
文件大小:20k
源码类别:

图片显示

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////
  2. // JpegFile - A C++ class to allow reading and writing of
  3. // RGB and Grayscale JPEG images.
  4. // It is based on the IJG V.6 code.
  5. //
  6. // This class Copyright 1997, Chris Losinger
  7. // This is free to use and modify provided my name is 
  8. // included.
  9. //
  10. // See jpegfile.h for usage.
  11. //
  12. ////////////////////////////////////////////////////////////
  13. #include "stdafx.h"
  14. #include "JpegFile.h"
  15. #include <stdio.h>
  16. #ifdef __cplusplus
  17. extern "C" {
  18. #endif // __cplusplus
  19. #define HAVE_BOOLEAN 
  20. #include "jpeglib.h"
  21. #ifdef __cplusplus
  22. }
  23. #endif // __cplusplus
  24. //
  25. //
  26. //
  27. /*
  28.  * <setjmp.h> is used for the optional error recovery mechanism shown in
  29.  * the second part of the example.
  30.  */
  31. #include <setjmp.h>
  32. // error handler, to avoid those pesky exit(0)'s
  33. struct my_error_mgr {
  34.   struct jpeg_error_mgr pub; /* "public" fields */
  35.   jmp_buf setjmp_buffer; /* for return to caller */
  36. };
  37. typedef struct my_error_mgr * my_error_ptr;
  38. //
  39. //
  40. //
  41. METHODDEF(void) my_error_exit (j_common_ptr cinfo);
  42. //
  43. // to handle fatal errors.
  44. // the original JPEG code will just exit(0). can't really
  45. // do that in Windows....
  46. //
  47. METHODDEF(void) my_error_exit (j_common_ptr cinfo)
  48. {
  49. /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
  50. my_error_ptr myerr = (my_error_ptr) cinfo->err;
  51. char buffer[JMSG_LENGTH_MAX];
  52. /* Create the message */
  53. (*cinfo->err->format_message) (cinfo, buffer);
  54. /* Always display the message. */
  55. MessageBox(NULL,buffer,"JPEG Fatal Error",MB_ICONSTOP);
  56. /* Return control to the setjmp point */
  57. longjmp(myerr->setjmp_buffer, 1);
  58. }
  59. // store a scanline to our data buffer
  60. void j_putRGBScanline(BYTE *jpegline, 
  61.  int widthPix,
  62.  BYTE *outBuf,
  63.  int row);
  64. void j_putGrayScanlineToRGB(BYTE *jpegline, 
  65.  int widthPix,
  66.  BYTE *outBuf,
  67.  int row);
  68. //
  69. // constructor doesn't do much - there's no real class here...
  70. //
  71. JpegFile::JpegFile()
  72. {
  73. }
  74. //
  75. //
  76. //
  77. JpegFile::~JpegFile()
  78. {
  79. }
  80. //
  81. // read a JPEG file
  82. //
  83. BYTE * JpegFile::JpegFileToRGB(CString fileName,
  84.    UINT *width,
  85.    UINT *height)
  86. {
  87. // basic code from IJG Jpeg Code v6 example.c
  88. *width=0;
  89. *height=0;
  90. /* This struct contains the JPEG decompression parameters and pointers to
  91. * working space (which is allocated as needed by the JPEG library).
  92. */
  93. struct jpeg_decompress_struct cinfo;
  94. /* We use our private extension JPEG error handler.
  95. * Note that this struct must live as long as the main JPEG parameter
  96. * struct, to avoid dangling-pointer problems.
  97. */
  98. struct my_error_mgr jerr;
  99. /* More stuff */
  100. FILE * infile=NULL; /* source file */
  101. JSAMPARRAY buffer; /* Output row buffer */
  102. int row_stride; /* physical row width in output buffer */
  103. char buf[250];
  104. /* In this example we want to open the input file before doing anything else,
  105. * so that the setjmp() error recovery below can assume the file is open.
  106. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
  107. * requires it in order to read binary files.
  108. */
  109. if ((infile = fopen(fileName, "rb")) == NULL) {
  110. sprintf(buf, "JPEG :nCan't open %sn", fileName);
  111. AfxMessageBox(buf);
  112. return NULL;
  113. }
  114. /* Step 1: allocate and initialize JPEG decompression object */
  115. /* We set up the normal JPEG error routines, then override error_exit. */
  116. cinfo.err = jpeg_std_error(&jerr.pub);
  117. jerr.pub.error_exit = my_error_exit;
  118. /* Establish the setjmp return context for my_error_exit to use. */
  119. if (setjmp(jerr.setjmp_buffer)) {
  120. /* If we get here, the JPEG code has signaled an error.
  121.  * We need to clean up the JPEG object, close the input file, and return.
  122.  */
  123. jpeg_destroy_decompress(&cinfo);
  124. if (infile!=NULL)
  125. fclose(infile);
  126. return NULL;
  127. }
  128. /* Now we can initialize the JPEG decompression object. */
  129. jpeg_create_decompress(&cinfo);
  130. /* Step 2: specify data source (eg, a file) */
  131. jpeg_stdio_src(&cinfo, infile);
  132. /* Step 3: read file parameters with jpeg_read_header() */
  133. (void) jpeg_read_header(&cinfo, TRUE);
  134. /* We can ignore the return value from jpeg_read_header since
  135. *   (a) suspension is not possible with the stdio data source, and
  136. *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
  137. * See libjpeg.doc for more info.
  138. */
  139. /* Step 4: set parameters for decompression */
  140. /* In this example, we don't need to change any of the defaults set by
  141. * jpeg_read_header(), so we do nothing here.
  142. */
  143. /* Step 5: Start decompressor */
  144. (void) jpeg_start_decompress(&cinfo);
  145. /* We can ignore the return value since suspension is not possible
  146. * with the stdio data source.
  147. */
  148. /* We may need to do some setup of our own at this point before reading
  149. * the data.  After jpeg_start_decompress() we have the correct scaled
  150. * output image dimensions available, as well as the output colormap
  151. * if we asked for color quantization.
  152. * In this example, we need to make an output work buffer of the right size.
  153. */ 
  154. // get our buffer set to hold data
  155. BYTE *dataBuf;
  156. ////////////////////////////////////////////////////////////
  157. // alloc and open our new buffer
  158. dataBuf=(BYTE *)new BYTE[cinfo.output_width * 3 * cinfo.output_height];
  159. if (dataBuf==NULL) {
  160. AfxMessageBox("JpegFile :nOut of memory",MB_ICONSTOP);
  161. jpeg_destroy_decompress(&cinfo);
  162. fclose(infile);
  163. return NULL;
  164. }
  165. // how big is this thing gonna be?
  166. *width = cinfo.output_width;
  167. *height = cinfo.output_height;
  168. /* JSAMPLEs per row in output buffer */
  169. row_stride = cinfo.output_width * cinfo.output_components;
  170. /* Make a one-row-high sample array that will go away when done with image */
  171. buffer = (*cinfo.mem->alloc_sarray)
  172. ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
  173. /* Step 6: while (scan lines remain to be read) */
  174. /*           jpeg_read_scanlines(...); */
  175. /* Here we use the library's state variable cinfo.output_scanline as the
  176. * loop counter, so that we don't have to keep track ourselves.
  177. */
  178. while (cinfo.output_scanline < cinfo.output_height) {
  179. /* jpeg_read_scanlines expects an array of pointers to scanlines.
  180.  * Here the array is only one element long, but you could ask for
  181.  * more than one scanline at a time if that's more convenient.
  182.  */
  183. (void) jpeg_read_scanlines(&cinfo, buffer, 1);
  184. /* Assume put_scanline_someplace wants a pointer and sample count. */
  185. // asuumer all 3-components are RGBs
  186. if (cinfo.out_color_components==3) {
  187. j_putRGBScanline(buffer[0], 
  188. *width,
  189. dataBuf,
  190. cinfo.output_scanline-1);
  191. } else if (cinfo.out_color_components==1) {
  192. // assume all single component images are grayscale
  193. j_putGrayScanlineToRGB(buffer[0], 
  194. *width,
  195. dataBuf,
  196. cinfo.output_scanline-1);
  197. }
  198. }
  199. /* Step 7: Finish decompression */
  200. (void) jpeg_finish_decompress(&cinfo);
  201. /* We can ignore the return value since suspension is not possible
  202. * with the stdio data source.
  203. */
  204. /* Step 8: Release JPEG decompression object */
  205. /* This is an important step since it will release a good deal of memory. */
  206. jpeg_destroy_decompress(&cinfo);
  207. /* After finish_decompress, we can close the input file.
  208. * Here we postpone it until after no more JPEG errors are possible,
  209. * so as to simplify the setjmp error logic above.  (Actually, I don't
  210. * think that jpeg_destroy can do an error exit, but why assume anything...)
  211. */
  212. fclose(infile);
  213. /* At this point you may want to check to see whether any corrupt-data
  214. * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
  215. */
  216. return dataBuf;
  217. }
  218. BOOL JpegFile::GetJPGDimensions(CString fileName,
  219. UINT *width,
  220. UINT *height)
  221. {
  222. // basic code from IJG Jpeg Code v6 example.c
  223. /* This struct contains the JPEG decompression parameters and pointers to
  224. * working space (which is allocated as needed by the JPEG library).
  225. */
  226. struct jpeg_decompress_struct cinfo;
  227. /* We use our private extension JPEG error handler.
  228. * Note that this struct must live as long as the main JPEG parameter
  229. * struct, to avoid dangling-pointer problems.
  230. */
  231. struct my_error_mgr jerr;
  232. /* More stuff */
  233. FILE * infile=NULL; /* source file */
  234. char buf[250];
  235. /* In this example we want to open the input file before doing anything else,
  236. * so that the setjmp() error recovery below can assume the file is open.
  237. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
  238. * requires it in order to read binary files.
  239. */
  240. if ((infile = fopen(fileName, "rb")) == NULL) {
  241. sprintf(buf, "JPEG :nCan't open %sn", fileName);
  242. AfxMessageBox(buf);
  243. return FALSE;
  244. }
  245. /* Step 1: allocate and initialize JPEG decompression object */
  246. /* We set up the normal JPEG error routines, then override error_exit. */
  247. cinfo.err = jpeg_std_error(&jerr.pub);
  248. jerr.pub.error_exit = my_error_exit;
  249. /* Establish the setjmp return context for my_error_exit to use. */
  250. if (setjmp(jerr.setjmp_buffer)) {
  251. /* If we get here, the JPEG code has signaled an error.
  252.  * We need to clean up the JPEG object, close the input file, and return.
  253.  */
  254. jpeg_destroy_decompress(&cinfo);
  255. if (infile!=NULL)
  256. fclose(infile);
  257. return FALSE;
  258. }
  259. /* Now we can initialize the JPEG decompression object. */
  260. jpeg_create_decompress(&cinfo);
  261. /* Step 2: specify data source (eg, a file) */
  262. jpeg_stdio_src(&cinfo, infile);
  263. /* Step 3: read file parameters with jpeg_read_header() */
  264. (void) jpeg_read_header(&cinfo, TRUE);
  265. /* We can ignore the return value from jpeg_read_header since
  266. *   (a) suspension is not possible with the stdio data source, and
  267. *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
  268. * See libjpeg.doc for more info.
  269. */
  270. // how big is this thing ?
  271. *width = cinfo.image_width;
  272. *height = cinfo.image_height;
  273. /* Step 8: Release JPEG decompression object */
  274. /* This is an important step since it will release a good deal of memory. */
  275. jpeg_destroy_decompress(&cinfo);
  276. /* After finish_decompress, we can close the input file.
  277. * Here we postpone it until after no more JPEG errors are possible,
  278. * so as to simplify the setjmp error logic above.  (Actually, I don't
  279. * think that jpeg_destroy can do an error exit, but why assume anything...)
  280. */
  281. fclose(infile);
  282. /* At this point you may want to check to see whether any corrupt-data
  283. * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
  284. */
  285. return TRUE;
  286. }
  287. //
  288. //
  289. //
  290. BYTE *JpegFile::RGBFromDWORDAligned(BYTE *inBuf,
  291. UINT widthPix, 
  292. UINT widthBytes,
  293. UINT height)
  294. {
  295. if (inBuf==NULL)
  296. return NULL;
  297. BYTE *tmp;
  298. tmp=(BYTE *)new BYTE[height * widthPix * 3];
  299. if (tmp==NULL)
  300. return NULL;
  301. UINT row;
  302. for (row=0;row<height;row++) {
  303. memcpy((tmp+row * widthPix * 3), 
  304. (inBuf + row * widthBytes), 
  305. widthPix * 3);
  306. }
  307. return tmp;
  308. }
  309. //
  310. //
  311. //
  312. BOOL JpegFile::RGBToJpegFile(CString fileName, 
  313. BYTE *dataBuf,
  314. UINT widthPix,
  315. UINT height,
  316. BOOL color, 
  317. int quality)
  318. {
  319. if (dataBuf==NULL)
  320. return FALSE;
  321. if (widthPix==0)
  322. return FALSE;
  323. if (height==0)
  324. return FALSE;
  325. LPBYTE tmp;
  326. if (!color) {
  327. tmp = (BYTE*)new BYTE[widthPix*height];
  328. if (tmp==NULL) {
  329. AfxMessageBox("Memory error");
  330. return FALSE;
  331. }
  332. UINT row,col;
  333. for (row=0;row<height;row++) {
  334. for (col=0;col<widthPix;col++) {
  335. LPBYTE pRed, pGrn, pBlu;
  336. pRed = dataBuf + row * widthPix * 3 + col * 3;
  337. pGrn = dataBuf + row * widthPix * 3 + col * 3 + 1;
  338. pBlu = dataBuf + row * widthPix * 3 + col * 3 + 2;
  339. // luminance
  340. int lum = (int)(.299 * (double)(*pRed) + .587 * (double)(*pGrn) + .114 * (double)(*pBlu));
  341. LPBYTE pGray;
  342. pGray = tmp + row * widthPix + col;
  343. *pGray = (BYTE)lum;
  344. }
  345. }
  346. }
  347. struct jpeg_compress_struct cinfo;
  348. /* More stuff */
  349. FILE * outfile=NULL; /* target file */
  350. int row_stride; /* physical row widthPix in image buffer */
  351. struct my_error_mgr jerr;
  352. /* Step 1: allocate and initialize JPEG compression object */
  353. cinfo.err = jpeg_std_error(&jerr.pub);
  354. jerr.pub.error_exit = my_error_exit;
  355. /* Establish the setjmp return context for my_error_exit to use. */
  356. if (setjmp(jerr.setjmp_buffer)) {
  357. /* If we get here, the JPEG code has signaled an error.
  358.  * We need to clean up the JPEG object, close the input file, and return.
  359.  */
  360. jpeg_destroy_compress(&cinfo);
  361. if (outfile!=NULL)
  362. fclose(outfile);
  363. if (!color) {
  364. delete [] tmp;
  365. }
  366. return FALSE;
  367. }
  368. /* Now we can initialize the JPEG compression object. */
  369. jpeg_create_compress(&cinfo);
  370. /* Step 2: specify data destination (eg, a file) */
  371. /* Note: steps 2 and 3 can be done in either order. */
  372. if ((outfile = fopen(fileName, "wb")) == NULL) {
  373. char buf[250];
  374. sprintf(buf, "JpegFile :nCan't open %sn", fileName);
  375. AfxMessageBox(buf);
  376. return FALSE;
  377. }
  378. jpeg_stdio_dest(&cinfo, outfile);
  379. /* Step 3: set parameters for compression */
  380.     
  381. /* First we supply a description of the input image.
  382. * Four fields of the cinfo struct must be filled in:
  383. */
  384. cinfo.image_width = widthPix;  /* image widthPix and height, in pixels */
  385. cinfo.image_height = height;
  386. if (color) {
  387. cinfo.input_components = 3; /* # of color components per pixel */
  388. cinfo.in_color_space = JCS_RGB;  /* colorspace of input image */
  389. } else {
  390. cinfo.input_components = 1; /* # of color components per pixel */
  391. cinfo.in_color_space = JCS_GRAYSCALE;  /* colorspace of input image */
  392. }
  393.  
  394. /* Now use the library's routine to set default compression parameters.
  395.    * (You must set at least cinfo.in_color_space before calling this,
  396.    * since the defaults depend on the source color space.)
  397.    */
  398.   jpeg_set_defaults(&cinfo);
  399.   /* Now you can set any non-default parameters you wish to.
  400.    * Here we just illustrate the use of quality (quantization table) scaling:
  401.    */
  402.   jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
  403.   /* Step 4: Start compressor */
  404.   /* TRUE ensures that we will write a complete interchange-JPEG file.
  405.    * Pass TRUE unless you are very sure of what you're doing.
  406.    */
  407.   jpeg_start_compress(&cinfo, TRUE);
  408.   /* Step 5: while (scan lines remain to be written) */
  409.   /*           jpeg_write_scanlines(...); */
  410.   /* Here we use the library's state variable cinfo.next_scanline as the
  411.    * loop counter, so that we don't have to keep track ourselves.
  412.    * To keep things simple, we pass one scanline per call; you can pass
  413.    * more if you wish, though.
  414.    */
  415.   row_stride = widthPix * 3; /* JSAMPLEs per row in image_buffer */
  416.   while (cinfo.next_scanline < cinfo.image_height) {
  417.     /* jpeg_write_scanlines expects an array of pointers to scanlines.
  418.      * Here the array is only one element long, but you could pass
  419.      * more than one scanline at a time if that's more convenient.
  420.      */
  421. LPBYTE outRow;
  422. if (color) {
  423. outRow = dataBuf + (cinfo.next_scanline * widthPix * 3);
  424. } else {
  425. outRow = tmp + (cinfo.next_scanline * widthPix);
  426. }
  427.     (void) jpeg_write_scanlines(&cinfo, &outRow, 1);
  428.   }
  429.   /* Step 6: Finish compression */
  430.   jpeg_finish_compress(&cinfo);
  431.   /* After finish_compress, we can close the output file. */
  432.   fclose(outfile);
  433.   /* Step 7: release JPEG compression object */
  434.   /* This is an important step since it will release a good deal of memory. */
  435.   jpeg_destroy_compress(&cinfo);
  436.   if (!color)
  437.   delete [] tmp;
  438.   /* And we're done! */
  439.   return TRUE;
  440. }
  441. //
  442. // stash a scanline
  443. //
  444. void j_putRGBScanline(BYTE *jpegline, 
  445.  int widthPix,
  446.  BYTE *outBuf,
  447.  int row)
  448. {
  449. int offset = row * widthPix * 3;
  450. int count;
  451. for (count=0;count<widthPix;count++) {
  452. BYTE iRed, iBlu, iGrn;
  453. LPBYTE oRed, oBlu, oGrn;
  454. iRed = *(jpegline + count * 3 + 0);
  455. iGrn = *(jpegline + count * 3 + 1);
  456. iBlu = *(jpegline + count * 3 + 2);
  457. oRed = outBuf + offset + count * 3 + 0;
  458. oGrn = outBuf + offset + count * 3 + 1;
  459. oBlu = outBuf + offset + count * 3 + 2;
  460. *oRed = iRed;
  461. *oGrn = iGrn;
  462. *oBlu = iBlu;
  463. }
  464. }
  465. //
  466. // stash a gray scanline
  467. //
  468. void j_putGrayScanlineToRGB(BYTE *jpegline, 
  469.  int widthPix,
  470.  BYTE *outBuf,
  471.  int row)
  472. {
  473. int offset = row * widthPix * 3;
  474. int count;
  475. for (count=0;count<widthPix;count++) {
  476. BYTE iGray;
  477. LPBYTE oRed, oBlu, oGrn;
  478. // get our grayscale value
  479. iGray = *(jpegline + count);
  480. oRed = outBuf + offset + count * 3;
  481. oGrn = outBuf + offset + count * 3 + 1;
  482. oBlu = outBuf + offset + count * 3 + 2;
  483. *oRed = iGray;
  484. *oGrn = iGray;
  485. *oBlu = iGray;
  486. }
  487. }
  488. //
  489. // copies BYTE buffer into DWORD-aligned BYTE buffer
  490. // return addr of new buffer
  491. //
  492. BYTE * JpegFile::MakeDwordAlignedBuf(BYTE *dataBuf,
  493.  UINT widthPix, // pixels!!
  494.  UINT height,
  495.  UINT *uiOutWidthBytes) // bytes!!!
  496. {
  497. ////////////////////////////////////////////////////////////
  498. // what's going on here? this certainly means trouble 
  499. if (dataBuf==NULL)
  500. return NULL;
  501. ////////////////////////////////////////////////////////////
  502. // how big is the smallest DWORD-aligned buffer that we can use?
  503. UINT uiWidthBytes;
  504. uiWidthBytes = WIDTHBYTES(widthPix * 24);
  505. DWORD dwNewsize=(DWORD)((DWORD)uiWidthBytes * 
  506. (DWORD)height);
  507. BYTE *pNew;
  508. ////////////////////////////////////////////////////////////
  509. // alloc and open our new buffer
  510. pNew=(BYTE *)new BYTE[dwNewsize];
  511. if (pNew==NULL) {
  512. return NULL;
  513. }
  514. ////////////////////////////////////////////////////////////
  515. // copy row-by-row
  516. UINT uiInWidthBytes = widthPix * 3;
  517. UINT uiCount;
  518. for (uiCount=0;uiCount < height;uiCount++) {
  519. BYTE * bpInAdd;
  520. BYTE * bpOutAdd;
  521. ULONG lInOff;
  522. ULONG lOutOff;
  523. lInOff=uiInWidthBytes * uiCount;
  524. lOutOff=uiWidthBytes * uiCount;
  525. bpInAdd= dataBuf + lInOff;
  526. bpOutAdd= pNew + lOutOff;
  527. memcpy(bpOutAdd,bpInAdd,uiInWidthBytes);
  528. }
  529. *uiOutWidthBytes=uiWidthBytes;
  530. return pNew;
  531. }
  532. //
  533. // vertically flip a buffer 
  534. // note, this operates on a buffer of widthBytes bytes, not pixels!!!
  535. //
  536. BOOL JpegFile::VertFlipBuf(BYTE  * inbuf, 
  537.    UINT widthBytes, 
  538.    UINT height)
  539. {   
  540. BYTE  *tb1;
  541. BYTE  *tb2;
  542. if (inbuf==NULL)
  543. return FALSE;
  544. UINT bufsize;
  545. bufsize=widthBytes;
  546. tb1= (BYTE *)new BYTE[bufsize];
  547. if (tb1==NULL) {
  548. return FALSE;
  549. }
  550. tb2= (BYTE *)new BYTE [bufsize];
  551. if (tb2==NULL) {
  552. delete [] tb1;
  553. return FALSE;
  554. }
  555. UINT row_cnt;     
  556. ULONG off1=0;
  557. ULONG off2=0;
  558. for (row_cnt=0;row_cnt<(height+1)/2;row_cnt++) {
  559. off1=row_cnt*bufsize;
  560. off2=((height-1)-row_cnt)*bufsize;   
  561. memcpy(tb1,inbuf+off1,bufsize);
  562. memcpy(tb2,inbuf+off2,bufsize);
  563. memcpy(inbuf+off1,tb2,bufsize);
  564. memcpy(inbuf+off2,tb1,bufsize);
  565. }
  566. delete [] tb1;
  567. delete [] tb2;
  568. return TRUE;
  569. }        
  570. //
  571. // swap Rs and Bs
  572. //
  573. // Note! this does its stuff on buffers with a whole number of pixels
  574. // per data row!!
  575. //
  576. BOOL JpegFile::BGRFromRGB(BYTE *buf, UINT widthPix, UINT height)
  577. {
  578. if (buf==NULL)
  579. return FALSE;
  580. UINT col, row;
  581. for (row=0;row<height;row++) {
  582. for (col=0;col<widthPix;col++) {
  583. LPBYTE pRed, pGrn, pBlu;
  584. pRed = buf + row * widthPix * 3 + col * 3;
  585. pGrn = buf + row * widthPix * 3 + col * 3 + 1;
  586. pBlu = buf + row * widthPix * 3 + col * 3 + 2;
  587. // swap red and blue
  588. BYTE tmp;
  589. tmp = *pRed;
  590. *pRed = *pBlu;
  591. *pBlu = tmp;
  592. }
  593. }
  594. return TRUE;
  595. }
  596. //
  597. // Note! this does its stuff on buffers with a whole number of pixels
  598. // per data row!!
  599. //
  600. BOOL JpegFile::MakeGrayScale(BYTE *buf, UINT widthPix, UINT height)
  601. {
  602. if (buf==NULL)
  603. return FALSE;
  604. UINT row,col;
  605. for (row=0;row<height;row++) {
  606. for (col=0;col<widthPix;col++) {
  607. LPBYTE pRed, pGrn, pBlu;
  608. pRed = buf + row * widthPix * 3 + col * 3;
  609. pGrn = buf + row * widthPix * 3 + col * 3 + 1;
  610. pBlu = buf + row * widthPix * 3 + col * 3 + 2;
  611. // luminance
  612. int lum = (int)(.299 * (double)(*pRed) + .587 * (double)(*pGrn) + .114 * (double)(*pBlu));
  613. *pRed = (BYTE)lum;
  614. *pGrn = (BYTE)lum;
  615. *pBlu = (BYTE)lum;
  616. }
  617. }
  618. return TRUE;
  619. }