00001
00014 #include "JpegTool.h"
00015
00016 #ifdef ENABLE_JPEGLIB
00017
00018
00019 using namespace jbxl;
00020
00021
00022
00028 void JPEGImage::init(void)
00029 {
00030 xs = 0;
00031 ys = 0;
00032 col = 0;
00033 state = 0;
00034 gp = NULL;
00035 image = NULL;
00036 return;
00037 }
00038
00039
00045 bool JPEGImage::isNull(void)
00046 {
00047 if (gp==NULL || image==NULL) return true;
00048 return false;
00049 }
00050
00051
00055 void JPEGImage::clear(void)
00056 {
00057 memset(gp, 0, sizeof(JSAMPLE)*xs*ys*col);
00058 return;
00059 }
00060
00061
00065 void JPEGImage::fill(JSAMPLE v)
00066 {
00067 int i;
00068 for (i=0; i<xs*ys*col; i++) gp[i] = v;
00069
00070 return;
00071 }
00072
00073
00079 void JPEGImage::free(void)
00080 {
00081 if (gp!=NULL) ::free(gp);
00082 if (image!=NULL) ::free(image);
00083 init();
00084
00085 return;
00086 }
00087
00088
00092 void JPEGImage::set(int x, int y, int c)
00093 {
00094 if (c!=1) c = 3;
00095
00096 getm(x, y, c);
00097 if (gp==NULL) return;
00098
00099 xs = x;
00100 ys = y;
00101 col = c;
00102 state = 0;
00103
00104 memset(gp, 0, sizeof(JSAMPLE)*c*x*y);
00105
00106 return;
00107 }
00108
00109
00113 void JPEGImage::getm(int x, int y, int c)
00114 {
00115 image = (JSAMPARRAY)malloc(sizeof(JSAMPROW)*y);
00116 if (image==NULL) {
00117 state = JBXL_GRAPH_MEMORY_ERROR;
00118 return;
00119 }
00120
00121 gp = (JSAMPLE*)malloc(sizeof(JSAMPLE)*c*x*y);
00122 if (gp==NULL) {
00123 freeNull(image);
00124 state = JBXL_GRAPH_MEMORY_ERROR;
00125 return;
00126 }
00127
00128 int j;
00129 for (j=0; j<y; j++) image[j] = (JSAMPROW)&gp[j*c*x];
00130
00131 return;
00132 }
00133
00134
00135
00137
00150 JPEGImage jbxl::readJPEGFile(const char* fname)
00151 {
00152 JPEGImage jp;
00153 FILE* fp;
00154
00155 fp = fopen(fname, "rb");
00156 if (fp==NULL) {
00157 jp.gp = NULL;
00158 jp.state = JBXL_GRAPH_OPFILE_ERROR;
00159 return jp;
00160 }
00161
00162 jp = readJPEGData(fp);
00163 fclose(fp);
00164
00165 return jp;
00166 }
00167
00168
00181 JPEGImage jbxl::readJPEGData(FILE* fp)
00182 {
00183 JPEGImage jp;
00184 int xs, ys, col;
00185 struct jpeg_decompress_struct jdat;
00186 struct jpeg_error_mgr jerr;
00187
00188 fseek(fp, 0, 0);
00189 jp.init();
00190 jdat.err = jpeg_std_error(&jerr);
00191 jpeg_create_decompress(&jdat);
00192
00193
00194
00195
00196
00197
00198 jpeg_stdio_src(&jdat, fp);
00199 jpeg_read_header(&jdat, TRUE);
00200 jpeg_start_decompress(&jdat);
00201
00202 xs = jdat.output_width;
00203 ys = jdat.output_height;
00204 col = jdat.output_components;
00205 if (xs<=0 || ys<=0 || col<=0) {
00206 jpeg_destroy_decompress(&jdat);
00207 fclose(fp);
00208 jp.state = JBXL_GRAPH_HEADER_ERROR;
00209 return jp;
00210 }
00211
00212 jp.set(xs, ys, col);
00213 if (jp.state) return jp;
00214
00215 int rmn = jdat.output_height;
00216 while(rmn>0) {
00217 jpeg_read_scanlines(&jdat, jp.image+jdat.output_scanline, rmn);
00218 rmn = jdat.output_height - jdat.output_scanline;
00219 }
00220 jpeg_finish_decompress (&jdat);
00221 jpeg_destroy_decompress(&jdat);
00222
00223 return jp;
00224 }
00225
00226
00243 int jbxl::writeJPEGFile(const char* fname, JPEGImage jp, int qulty)
00244 {
00245 FILE* fp;
00246 int ret;
00247
00248 if (fname==NULL) return JBXL_GRAPH_IVDARG_ERROR;
00249 if (jp.col!=1 && jp.col!=3) return JBXL_GRAPH_IVDARG_ERROR;
00250 if (jp.gp==NULL || jp.image==NULL) return JBXL_GRAPH_NODATA_ERROR;
00251
00252 fp = fopen(fname, "wb");
00253 if (fp==NULL) {
00254 return JBXL_GRAPH_OPFILE_ERROR;
00255 }
00256
00257 ret = writeJPEGData(fp, jp, qulty);
00258 fclose(fp);
00259
00260 return ret;
00261 }
00262
00263
00264
00281 int jbxl::writeJPEGData(FILE* fp, JPEGImage jp, int qulty)
00282 {
00283 struct jpeg_compress_struct jdat;
00284 struct jpeg_error_mgr jerr;
00285
00286 if (fp==NULL) return JBXL_GRAPH_OPFILE_ERROR;
00287 if (jp.col!=1 && jp.col!=3) return JBXL_GRAPH_IVDARG_ERROR;
00288 if (jp.gp==NULL || jp.image==NULL) return JBXL_GRAPH_NODATA_ERROR;
00289
00290 if (qulty>100) qulty = 100;
00291 else if (qulty<0) qulty = 0;
00292
00293 jdat.err = jpeg_std_error(&jerr);
00294 jpeg_create_compress(&jdat);
00295
00296
00297
00298
00299
00300
00301 fseek(fp, 0, 0);
00302 jpeg_stdio_dest(&jdat, fp);
00303
00304 jdat.image_width = jp.xs;
00305 jdat.image_height = jp.ys;
00306 jdat.input_components = jp.col;
00307 if (jp.col==1) jdat.in_color_space = JCS_GRAYSCALE;
00308 else jdat.in_color_space = JCS_RGB;
00309
00310 jpeg_set_quality (&jdat, qulty, TRUE);
00311 jpeg_set_defaults(&jdat);
00312
00313 jpeg_start_compress (&jdat, TRUE);
00314 jpeg_write_scanlines(&jdat, jp.image, jp.ys);
00315 jpeg_finish_compress(&jdat);
00316
00317 jpeg_destroy_compress(&jdat);
00318
00319 return 0;
00320 }
00321
00322
00323
00325
00337 CmnHead jbxl::JPEGImage2CmnHead(JPEGImage jp)
00338 {
00339 CmnHead hd;
00340 int i, j, k, yp, zp;
00341
00342 memset(&hd, 0, sizeof(CmnHead));
00343
00344 if (jp.isNull()) {
00345 hd.kind = HEADER_NONE;
00346 hd.xsize = JBXL_GRAPH_NODATA_ERROR;
00347 return hd;
00348 }
00349
00350
00351 if (jp.col==1) {
00352 hd.kind = JPEG_MONO_DATA;
00353 }
00354 else if (jp.col==3) {
00355 hd.kind = JPEG_RGB_DATA;
00356 }
00357 else {
00358 hd.kind = HEADER_NONE;
00359 hd.xsize = JBXL_GRAPH_IVDARG_ERROR;
00360 return hd;
00361 }
00362
00363 hd.xsize = jp.xs;
00364 hd.ysize = jp.ys;
00365 hd.zsize = jp.col;
00366 hd.depth = 8;
00367 hd.bsize = 0;
00368 hd.lsize = jp.xs*jp.ys*jp.col*((hd.depth+7)/8);
00369 hd.buf = NULL;
00370 hd.grptr = (uByte*)malloc(hd.lsize);
00371 if (hd.grptr==NULL) {
00372 hd.kind = HEADER_NONE;
00373 hd.xsize = JBXL_GRAPH_MEMORY_ERROR;
00374 return hd;
00375 }
00376
00377 for (k=0; k<jp.col; k++) {
00378 zp = k*jp.xs*jp.ys;
00379 for (j=0; j<jp.ys; j++) {
00380 yp = zp + j*jp.xs;
00381 for (i=0; i<jp.xs; i++) {
00382 hd.grptr[yp + i] = (uByte)jp.point(i, j, k);
00383 }
00384 }
00385 }
00386
00387 return hd;
00388 }
00389
00390
00403 JPEGImage jbxl::CmnHead2JPEGImage(CmnHead hd)
00404 {
00405 JPEGImage jp;
00406 int i, j, k, yp, zp, col;
00407 int kind = hd.kind & 0x00ff;
00408
00409 jp.init();
00410
00411 if (hd.grptr==NULL) {
00412 jp.state = JBXL_GRAPH_NODATA_ERROR;
00413 return jp;
00414 }
00415 if (hd.depth!=8 && hd.depth!=16) {
00416 jp.state = JBXL_GRAPH_IVDARG_ERROR;
00417 return jp;
00418 }
00419
00420
00421 if (kind==JPEG_MONO_DATA && hd.zsize==1) col = 1;
00422 else if (kind==JPEG_RGB_DATA && hd.zsize==3) col = 3;
00423 else if ((kind==JPEG_ARGB_DATA || kind==JPEG_RGBA_DATA) && hd.zsize==4) col = 3;
00424 else if ((kind==JPEG16_RGB_DATA || kind==JPEG16_ARGB_DATA || kind==JPEG16_RGBA_DATA) && hd.zsize==1 && hd.depth==16) col = 3;
00425 else {
00426 jp.state = JBXL_GRAPH_IVDARG_ERROR;
00427 return jp;
00428 }
00429
00430 jp.set(hd.xsize, hd.ysize, col);
00431 if (jp.isNull()) return jp;
00432
00433
00434 if (kind==JPEG16_RGB_DATA && hd.depth==16) {
00435 for (j=0; j<jp.ys; j++) {
00436 yp = j*jp.xs;
00437 for (i=0; i<jp.xs; i++) {
00438 uWord* ptr = (uWord*)&hd.grptr[(yp+i)*2];
00439 if (isLittleEndian) {
00440 jp.point(i, j, 0) = (JSAMPLE)(((int)(((*ptr)&0xf800)>>11)*255)/32);
00441 jp.point(i, j, 1) = (JSAMPLE)(((int)(((*ptr)&0x07e0)>>5) *255)/64);
00442 jp.point(i, j, 2) = (JSAMPLE)(((int)(((*ptr)&0x001f)) *255)/32);
00443 }
00444 else {
00445 jp.point(i, j, 0) = (JSAMPLE)(((int)(((*ptr)&0x001f)) *255)/32);
00446 jp.point(i, j, 1) = (JSAMPLE)(((int)(((*ptr)&0x07e0)>>5) *255)/64);
00447 jp.point(i, j, 2) = (JSAMPLE)(((int)(((*ptr)&0xf800)>>11)*255)/32);
00448 }
00449 }
00450 }
00451 }
00452
00453
00454 else if (kind==JPEG16_ARGB_DATA && hd.depth==16) {
00455 for (j=0; j<jp.ys; j++) {
00456 yp = j*jp.xs;
00457 for (i=0; i<jp.xs; i++) {
00458 uWord* ptr = (uWord*)&hd.grptr[(yp+i)*2];
00459 if (isLittleEndian) {
00460 jp.point(i, j, 0) = (JSAMPLE)(((int)(((*ptr)&0x0f00)>>8) *255)/16);
00461 jp.point(i, j, 1) = (JSAMPLE)(((int)(((*ptr)&0x00f0)>>4) *255)/16);
00462 jp.point(i, j, 2) = (JSAMPLE)(((int)(((*ptr)&0x000f)) *255)/16);
00463 }
00464 else {
00465 jp.point(i, j, 0) = (JSAMPLE)(((int)(((*ptr)&0x00f0)>>4) *255)/16);
00466 jp.point(i, j, 1) = (JSAMPLE)(((int)(((*ptr)&0x0f00)>>8) *255)/16);
00467 jp.point(i, j, 2) = (JSAMPLE)(((int)(((*ptr)&0xf000)>>12)*255)/16);
00468 }
00469 }
00470 }
00471 }
00472
00473
00474 else if (kind==JPEG16_RGBA_DATA && hd.depth==16) {
00475 for (j=0; j<jp.ys; j++) {
00476 yp = j*jp.xs;
00477 for (i=0; i<jp.xs; i++) {
00478 uWord* ptr = (uWord*)&hd.grptr[(yp+i)*2];
00479 if (isLittleEndian) {
00480 jp.point(i, j, 0) = (JSAMPLE)(((int)(((*ptr)&0xf000)>>12)*255)/16);
00481 jp.point(i, j, 1) = (JSAMPLE)(((int)(((*ptr)&0x0f00)>>8) *255)/16);
00482 jp.point(i, j, 2) = (JSAMPLE)(((int)(((*ptr)&0x00f0)>>4) *255)/16);
00483 }
00484 else {
00485 jp.point(i, j, 0) = (JSAMPLE)(((int)(((*ptr)&0x000f)) *255)/16);
00486 jp.point(i, j, 1) = (JSAMPLE)(((int)(((*ptr)&0x00f0)>>4) *255)/16);
00487 jp.point(i, j, 2) = (JSAMPLE)(((int)(((*ptr)&0x0f00)>>8) *255)/16);
00488 }
00489 }
00490 }
00491 }
00492
00493
00494 else if (kind==JPEG_ARGB_DATA) {
00495 if (hd.depth==8) {
00496 for (k=1; k<=3; k++) {
00497 zp = k*jp.xs*jp.ys;
00498 for (j=0; j<jp.ys; j++) {
00499 yp = zp + j*jp.xs;
00500 for (i=0; i<jp.xs; i++) {
00501 jp.point(i, j, k-1) = (JSAMPLE)hd.grptr[yp+i];
00502 }
00503 }
00504 }
00505 }
00506
00507
00508 else if (hd.depth==16) {
00509 int max = 0;
00510 uWord* ptr = (uWord*)hd.grptr;
00511 for (i=hd.xsize*hd.ysize; i<hd.xsize*hd.ysize*hd.zsize; i++) {
00512 if (max<ptr[i]) max = ptr[i];
00513 }
00514
00515 for (k=1; k<=3; k++) {
00516 zp = k*jp.xs*jp.ys;
00517 for (j=0; j<jp.ys; j++) {
00518 yp = zp + j*jp.xs;
00519 for (i=0; i<jp.xs; i++) {
00520 if (max<=255) {
00521 if (isLittleEndian) jp.point(i, j, k-1) = (JSAMPLE)hd.grptr[(yp+i)*2];
00522 else jp.point(i, j, k-1) = (JSAMPLE)hd.grptr[(yp+i)*2 + 1];
00523 }
00524 else {
00525 jp.point(i, j, k-1) = (JSAMPLE)((ptr[yp+i]*255)/max);
00526 }
00527 }
00528 }
00529 }
00530 }
00531 }
00532
00533
00534 else {
00535 if (hd.depth==8) {
00536 for (k=0; k<jp.col; k++) {
00537 zp = k*jp.xs*jp.ys;
00538 for (j=0; j<jp.ys; j++) {
00539 yp = zp + j*jp.xs;
00540 for (i=0; i<jp.xs; i++) {
00541 jp.point(i, j, k) = (JSAMPLE)hd.grptr[yp+i];
00542 }
00543 }
00544 }
00545 }
00546
00547
00548 else if (hd.depth==16) {
00549 int max = 0;
00550 uWord* ptr = (uWord*)hd.grptr;
00551 for (i=0; i<hd.xsize*hd.ysize*hd.zsize; i++) {
00552 if (max<ptr[i]) max = ptr[i];
00553 }
00554
00555 for (k=0; k<jp.col; k++) {
00556 zp = k*jp.xs*jp.ys;
00557 for (j=0; j<jp.ys; j++) {
00558 yp = zp + j*jp.xs;
00559 for (i=0; i<jp.xs; i++) {
00560 if (max<=255) {
00561 if (isLittleEndian) jp.point(i, j, k) = (JSAMPLE)hd.grptr[(yp+i)*2];
00562 else jp.point(i, j, k) = (JSAMPLE)hd.grptr[(yp+i)*2 + 1];
00563 }
00564 else {
00565 jp.point(i, j, k) = (JSAMPLE)((ptr[yp+i]*255)/max);
00566 }
00567 }
00568 }
00569 }
00570 }
00571 }
00572
00573 return jp;
00574 }
00575
00576
00577
00579
00586 int jbxl::isJPEGHeader(Buffer buf)
00587 {
00588 if (buf.vldsz<10) return FALSE;
00589
00590 unsigned char* head = buf.buf;
00591
00592 if (head[0]==0xff && head[1]==0xd8) {
00593 if (head[2]==0xff) return TRUE;
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 }
00609
00610 return FALSE;
00611 }
00612
00613
00614 #endif // ENABLE_JPEGLIB
00615