Solved
convert .bmp to .jpeg and write to file
Posted on 2000-04-12
I have the jpeglib that circulates in the shareware world, and I have been using it to "read a JPEG file and create a bitmap internally". Now I want to be able to use the same library to "write a bitmap in JPEG format to a file". I know the library has this output-JPEG function, but it seems non-trivial to call it. For example, the code below is the constructor I use to create a bitmap from a JPEG file. So I need another function perhaps similar to the one below, but that creates a JPEG file to disk from a bitmap. I don't seem to have such a function nor is there any doc in what I have to explain what to call.
Can someone send me the code for this function??
Thanks...
EqBitmap::EqBitmap(CDC *cdc, const char *filename)
{
struct jpeg_decompress_struct cinfo;
struct vw_error_mgr jerr;
JSAMPROW rowptr[1];
FILE *fp;
char *data = (char *) 0,
*tmp,
*tmp2,
sv;
int bperpix,
bperline,
wide,
high,
i;
CDC *hdc1,
*hdc2;
CBitmap *svb;
BITMAPINFO bi;
HBITMAP bm,
hsv;
if(!filename || !strlen(filename))
return;
if(!(fp = fopen(filename, "rb")))
return;
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = vw_error_handler;
jerr.pub.output_message = vw_error_handler;
if(setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
fclose(fp);
if(data)
free(data);
return;
}
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, fp);
(void) jpeg_read_header(&cinfo, 1);
jpeg_calc_output_dimensions(&cinfo);
wide = cinfo.output_width;
high = cinfo.output_height;
if((bperpix = cinfo.output_components) != 1 && bperpix != 3) {
jpeg_destroy_decompress(&cinfo);
fclose(fp);
return;
}
bperline = (((wide * 3) + 3) / 4) * 4;
if(!(data = (char *) malloc(high * bperline))) {
jpeg_destroy_decompress(&cinfo);
fclose(fp);
return;
}
jpeg_start_decompress(&cinfo);
while(cinfo.output_scanline < cinfo.output_height) {
tmp = &(data[cinfo.output_scanline * bperline]);
rowptr[0] = (JSAMPROW) tmp;
(void) jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1);
if(bperpix == 1) {
tmp2 = tmp + wide - 1;
tmp += wide * 3 - 1;
while(tmp != tmp2) {
*tmp-- = *tmp2;
*tmp-- = *tmp2;
*tmp-- = *tmp2--;
}
} else {
for(i = 0; i < wide; i++, tmp += 3) {
sv = tmp[0];
tmp[0] = tmp[2];
tmp[2] = sv;
}
}
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(fp);
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = wide;
bi.bmiHeader.biHeight = -high;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 24;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = wide * high * 3;
bi.bmiHeader.biXPelsPerMeter = 3273;
bi.bmiHeader.biYPelsPerMeter = 3273;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
bm = ::CreateDIBitmap((HDC) cdc->m_hDC, &(bi.bmiHeader), CBM_INIT, (void *) data, &bi, 0);
hdc1 = new CDC;
hdc1->CreateCompatibleDC(cdc);
CreateCompatibleBitmap(cdc, wide, high);
svb = hdc1->SelectObject(this);
hdc2 = new CDC;
hdc2->CreateCompatibleDC(cdc);
hsv = (HBITMAP) ::SelectObject((HDC) hdc2->m_hDC, (HGDIOBJ) bm);
::BitBlt((HDC) hdc1->m_hDC, 0, 0, wide, high, (HDC) hdc2->m_hDC, 0, 0, SRCCOPY);
::SelectObject((HDC) hdc2->m_hDC, (HGDIOBJ) hsv);
hdc1->SelectObject(svb);
delete hdc1;
delete hdc2;
::DeleteObject((HGDIOBJ) bm);
width = wide;
height = high;
free(data);
return;
}