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