bool CoImageTIF::Encode(FILE* pFile, bool bAppend) { if (EncodeSafeCheck(pFile)) return false; XFileDisk hFile(pFile); try { if (&hFile==NULL) throw CVLIB_IMG_ERR_NOFILE; // if (GetPalette() == NULL) throw CVLIB_IMG_ERR_NOIMAGE; // <RJ> replaced "w+b" with "a", to append an image directly on an existing file if (m_tif2==NULL) m_tif2 =(void*)_TIFFOpenEx(&hFile, "a"); if (m_tif2==NULL) throw "initialization fail"; if (bAppend || m_pages) m_multipage=true; m_pages++; if (!EncodeBody(m_tif2,m_multipage,m_pages,m_pages)) throw "Error saving TIFF file"; if (bAppend) { if (!TIFFWriteDirectory((TIFF*)m_tif2)) throw "Error saving TIFF directory"; } } catch (char *message) { strncpy(m_Info.szLastError,message,255); if (m_tif2) { TIFFClose((TIFF*)m_tif2); m_tif2=NULL; m_multipage=false; m_pages=0; } return false; } if (!bAppend) { TIFFClose((TIFF*)m_tif2); m_tif2=NULL; m_multipage=false; m_pages=0; } return true; }
bool CxImageSKA::Encode(CxFile * hFile) { if (EncodeSafeCheck(hFile)) return false; if(head.biBitCount > 8) { strcpy(info.szLastError,"SKA Images must be 8 bit or less"); return false; } SKAHEADER ska_header; ska_header.Width = (unsigned short)GetWidth(); ska_header.Height = (unsigned short)GetHeight(); ska_header.BppExp = 3; ska_header.dwUnknown = 0x01000000; ska_header.Width = ntohs(ska_header.Width); ska_header.Height = ntohs(ska_header.Height); ska_header.dwUnknown = ntohl(ska_header.dwUnknown); hFile->Write(&ska_header,sizeof(SKAHEADER),1); ska_header.Width = ntohs(ska_header.Width); ska_header.Height = ntohs(ska_header.Height); ska_header.dwUnknown = ntohl(ska_header.dwUnknown); if (head.biBitCount<8) IncreaseBpp(8); rgb_color pal[256]; for(int idx=0; idx<256; idx++){ GetPaletteColor(idx,&(pal[idx].r),&(pal[idx].g),&(pal[idx].b)); } hFile->Write(pal,256*sizeof(rgb_color),1); BYTE* src = GetBits(ska_header.Height-1); for(int y=0;y<ska_header.Height;y++){ hFile->Write(src,ska_header.Width,1); src -= GetEffWidth(); } return true; }
bool CxImageBMP::Encode(CxFile * hFile) { if (EncodeSafeCheck(hFile)) return false; BITMAPFILEHEADER hdr; hdr.bfType = 0x4d42; // 'BM' WINDOWS_BITMAP_SIGNATURE hdr.bfSize = GetSize() + 14 /*sizeof(BITMAPFILEHEADER)*/; hdr.bfReserved1 = hdr.bfReserved2 = 0; hdr.bfOffBits = 14 /*sizeof(BITMAPFILEHEADER)*/ + head.biSize + GetPaletteSize(); //copy attributes memcpy(pDib,&head,sizeof(BITMAPINFOHEADER)); // Write the file header hFile->Write(&hdr,min(14,sizeof(BITMAPFILEHEADER)),1); // Write the DIB header and the pixels hFile->Write(pDib,GetSize(),1); return true; }
bool CxImageJPG::Encode(CxFile * hFile) { if (EncodeSafeCheck(hFile)) return false; if (head.biClrUsed!=0 && !IsGrayScale()){ strcpy(info.szLastError,"JPEG can save only RGB or GreyScale images"); return false; } /* This struct contains the JPEG compression parameters and pointers to * working space (which is allocated as needed by the JPEG library). * It is possible to have several such structures, representing multiple * compression/decompression processes, in existence at once. We refer * to any one struct (and its associated working data) as a "JPEG object". */ struct jpeg_compress_struct cinfo; /* This struct represents a JPEG error handler. It is declared separately * because applications often want to supply a specialized error handler * (see the second half of this file for an example). But here we just * take the easy way out and use the standard error handler, which will * print a message on stderr and call exit() if compression fails. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ //struct jpeg_error_mgr jerr; /* We use our private extension JPEG error handler. <CSC> */ struct ima_error_mgr jerr; jerr.buffer=info.szLastError; /* More stuff */ int row_stride; /* physical row width in image buffer */ JSAMPARRAY buffer; /* Output row buffer */ /* Step 1: allocate and initialize JPEG compression object */ /* We have to set up the error handler first, in case the initialization * step fails. (Unlikely, but it could happen if you are out of memory.) * This routine fills in the contents of struct jerr, and returns jerr's * address which we place into the link field in cinfo. */ //cinfo.err = jpeg_std_error(&jerr); <CSC> /* We set up the normal JPEG error routines, then override error_exit. */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = ima_jpeg_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ strcpy(info.szLastError, jerr.buffer); //<CSC> jpeg_destroy_compress(&cinfo); return 0; } /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); /* Step 2: specify data destination (eg, a file) */ /* Note: steps 2 and 3 can be done in either order. */ /* Here we use the library-supplied code to send compressed data to a * stdio stream. You can also write your own code to do something else. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to write binary files. */ //jpeg_stdio_dest(&cinfo, outfile); CxFileJpg dest(hFile); cinfo.dest = &dest; /* Step 3: set parameters for compression */ /* First we supply a description of the input image. * Four fields of the cinfo struct must be filled in: */ cinfo.image_width = GetWidth(); // image width and height, in pixels cinfo.image_height = GetHeight(); if (IsGrayScale()){ cinfo.input_components = 1; // # of color components per pixel cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */ } else { cinfo.input_components = 3; // # of color components per pixel cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ } /* Now use the library's routine to set default compression parameters. * (You must set at least cinfo.in_color_space before calling this, * since the defaults depend on the source color space.) */ jpeg_set_defaults(&cinfo); /* Now you can set any non-default parameters you wish to. * Here we just illustrate the use of quality (quantization table) scaling: */ //jpeg_set_quality(&cinfo, info.nQuality, TRUE /* limit to baseline-JPEG values */); #ifdef C_ARITH_CODING_SUPPORTED if ((GetCodecOption() & ENCODE_ARITHMETIC) != 0) cinfo.arith_code = TRUE; #endif #ifdef ENTRPY_OPT_SUPPORTED if ((GetCodecOption() & ENCODE_OPTIMIZE) != 0) cinfo.optimize_coding = TRUE; #endif if ((GetCodecOption() & ENCODE_GRAYSCALE) != 0) jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE); if ((GetCodecOption() & ENCODE_SMOOTHING) != 0) cinfo.smoothing_factor = m_nSmoothing; jpeg_set_quality(&cinfo, GetJpegQuality(), (GetCodecOption() & ENCODE_BASELINE) != 0); #ifdef C_PROGRESSIVE_SUPPORTED if ((GetCodecOption() & ENCODE_PROGRESSIVE) != 0) jpeg_simple_progression(&cinfo); #endif #ifdef C_LOSSLES_SUPPORTED if ((GetCodecOption() & ENCODE_LOSSLESS) != 0) jpeg_simple_lossless(&cinfo, m_nPredictor, m_nPointTransform); #endif cinfo.density_unit=1; cinfo.X_density=(unsigned short)GetXDPI(); cinfo.Y_density=(unsigned short)GetYDPI(); /* Step 4: Start compressor */ /* TRUE ensures that we will write a complete interchange-JPEG file. * Pass TRUE unless you are very sure of what you're doing. */ jpeg_start_compress(&cinfo, TRUE); /* Step 5: while (scan lines remain to be written) */ /* jpeg_write_scanlines(...); */ /* Here we use the library's state variable cinfo.next_scanline as the * loop counter, so that we don't have to keep track ourselves. * To keep things simple, we pass one scanline per call; you can pass * more if you wish, though. */ row_stride = info.dwEffWidth; /* JSAMPLEs per row in image_buffer */ //<DP> "8+row_stride" fix heap deallocation problem during debug??? buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, 8+row_stride, 1); CImageIterator iter(this); iter.Upset(); while (cinfo.next_scanline < cinfo.image_height) { // info.nProgress = (long)(100*cinfo.next_scanline/cinfo.image_height); iter.GetRow(buffer[0], row_stride); // not necessary if swapped red and blue definition in jmorecfg.h;ln322 <W. Morrison> if (head.biClrUsed==0){ // swap R & B for RGB images RGBtoBGR(buffer[0], row_stride); // Lance : 1998/09/01 : Bug ID: EXP-2.1.1-9 } iter.PrevRow(); (void) jpeg_write_scanlines(&cinfo, buffer, 1); } /* Step 6: Finish compression */ jpeg_finish_compress(&cinfo); /* Step 7: release JPEG compression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_compress(&cinfo); /* And we're done! */ return true; }
bool CxImageJ2K::Encode(CxFile * hFile) { if (EncodeSafeCheck(hFile)) return false; if (head.biClrUsed!=0 && !IsGrayScale()){ strcpy(info.szLastError,"J2K can save only RGB or GrayScale images"); return false; } int i,x,y; j2k_image_t *img; j2k_cp_t *cp; j2k_tcp_t *tcp; j2k_tccp_t *tccp; img = (j2k_image_t *)calloc(sizeof(j2k_image_t),1); cp = (j2k_cp_t *)calloc(sizeof(j2k_cp_t),1); cp->tx0=0; cp->ty0=0; cp->tw=1; cp->th=1; cp->tcps=(j2k_tcp_t*)calloc(sizeof(j2k_tcp_t),1); tcp=&cp->tcps[0]; long w=head.biWidth; long h=head.biHeight; tcp->numlayers=1; for (i=0;i<tcp->numlayers;i++) tcp->rates[i]=(w*h*GetJpegQuality())/600; if (IsGrayScale()) { img->x0=0; img->y0=0; img->x1=w; img->y1=h; img->numcomps=1; img->comps=(j2k_comp_t*)calloc(sizeof(j2k_comp_t),1); img->comps[0].data=(int*)calloc(w*h*sizeof(int),1); img->comps[0].prec=8; img->comps[0].sgnd=0; img->comps[0].dx=1; img->comps[0].dy=1; for (i=0,y=0; y<h; y++) { for (x=0; x<w; x++,i++){ img->comps[0].data[i]=GetPixelIndex(x,h-1-y); } } } else if (!IsIndexed()) { img->x0=0; img->y0=0; img->x1=w; img->y1=h; img->numcomps=3; img->comps=(j2k_comp_t*)calloc(img->numcomps*sizeof(j2k_comp_t),1); for (i=0; i<img->numcomps; i++) { img->comps[i].data=(int*)calloc(w*h*sizeof(int),1); img->comps[i].prec=8; img->comps[i].sgnd=0; img->comps[i].dx=1; img->comps[i].dy=1; } RGBQUAD c; for (i=0,y=0; y<h; y++) { for (x=0; x<w; x++,i++){ c=GetPixelColor(x,h-1-y); img->comps[0].data[i]=c.rgbRed; img->comps[1].data[i]=c.rgbGreen; img->comps[2].data[i]=c.rgbBlue; } } } else { return 0; } cp->tdx=img->x1-img->x0; cp->tdy=img->y1-img->y0; tcp->csty=0; tcp->prg=0; tcp->mct=img->numcomps==3?1:0; tcp->tccps=(j2k_tccp_t*)calloc(img->numcomps*sizeof(j2k_tccp_t),1); int ir=0; /* or 1 ???*/ for (i=0; i<img->numcomps; i++) { tccp=&tcp->tccps[i]; tccp->csty=0; tccp->numresolutions=6; tccp->cblkw=6; tccp->cblkh=6; tccp->cblksty=0; tccp->qmfbid=ir?0:1; tccp->qntsty=ir?J2K_CCP_QNTSTY_SEQNT:J2K_CCP_QNTSTY_NOQNT; tccp->numgbits=2; tccp->roishift=0; j2k_calc_explicit_stepsizes(tccp, img->comps[i].prec); } BYTE* dest=(BYTE*)calloc(tcp->rates[tcp->numlayers-1]+2,1); long len = j2k_encode(img, cp, dest, tcp->rates[tcp->numlayers-1]+2); if (len==0) { strcpy(info.szLastError,"J2K failed to encode image"); } else { hFile->Write(dest, len, 1); } free(dest); j2k_destroy(&img,&cp); return (len!=0); }
bool CxImagePCX::Encode(CxFile * hFile) { if (EncodeSafeCheck(hFile)) return false; try { PCXHEADER pcxHeader; memset(&pcxHeader,0,sizeof(pcxHeader)); pcxHeader.Manufacturer = PCX_MAGIC; pcxHeader.Version = 5; pcxHeader.Encoding = 1; pcxHeader.Xmin = 0; pcxHeader.Ymin = 0; pcxHeader.Xmax = (WORD)head.biWidth-1; pcxHeader.Ymax = (WORD)head.biHeight-1; pcxHeader.Hres = (WORD)info.xDPI; pcxHeader.Vres = (WORD)info.yDPI; pcxHeader.Reserved = 0; pcxHeader.PaletteType = head.biClrUsed==0; switch(head.biBitCount){ case 24: case 8: { pcxHeader.BitsPerPixel = 8; pcxHeader.ColorPlanes = head.biClrUsed==0 ? 3 : 1; #if CXIMAGE_SUPPORT_ALPHA if (AlphaIsValid() && head.biClrUsed==0) pcxHeader.ColorPlanes =4; #endif //CXIMAGE_SUPPORT_ALPHA pcxHeader.BytesPerLine = (WORD)head.biWidth; break; } default: //(4 1) pcxHeader.BitsPerPixel = 1; pcxHeader.ColorPlanes = head.biClrUsed==16 ? 4 : 1; pcxHeader.BytesPerLine = (WORD)((head.biWidth * pcxHeader.BitsPerPixel + 7)>>3); } if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){ pcxHeader.ColorMap[0][0] = pcxHeader.ColorMap[0][1] = pcxHeader.ColorMap[0][2] = 0; pcxHeader.ColorMap[1][0] = pcxHeader.ColorMap[1][1] = pcxHeader.ColorMap[1][2] = 255; } if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 4){ RGBQUAD c; for (int i = 0; i < 16; i++){ c=GetPaletteColor(i); pcxHeader.ColorMap[i][0] = c.rgbRed; pcxHeader.ColorMap[i][1] = c.rgbGreen; pcxHeader.ColorMap[i][2] = c.rgbBlue; } } pcxHeader.BytesPerLine = (pcxHeader.BytesPerLine + 1)&(~1); if (hFile->Write(&pcxHeader, sizeof(pcxHeader), 1) == 0 ) throw "cannot write PCX header"; CxMemFile buffer; buffer.Open(); BYTE c,n; long x,y; if (head.biClrUsed==0){ for (y = head.biHeight-1; y >=0 ; y--){ for (int p=0; p<pcxHeader.ColorPlanes; p++){ c=n=0; for (x = 0; x<head.biWidth; x++){ if (p==0) PCX_PackPixels(GetPixelColor(x,y).rgbRed,c,n,buffer); else if (p==1) PCX_PackPixels(GetPixelColor(x,y).rgbGreen,c,n,buffer); else if (p==2) PCX_PackPixels(GetPixelColor(x,y).rgbBlue,c,n,buffer); #if CXIMAGE_SUPPORT_ALPHA else if (p==3) PCX_PackPixels(AlphaGet(x,y),c,n,buffer); #endif //CXIMAGE_SUPPORT_ALPHA } PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer); } } hFile->Write(buffer.GetBuffer(false),buffer.Size(),1); } else if (head.biBitCount==8) { for (y = head.biHeight-1; y >=0 ; y--){ c=n=0; for (x = 0; x<head.biWidth; x++){ PCX_PackPixels(GetPixelIndex(x,y),c,n,buffer); } PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer); } hFile->Write(buffer.GetBuffer(false),buffer.Size(),1); if (head.biBitCount == 8){ hFile->PutC(0x0C); BYTE* pal = (BYTE*)malloc(768); RGBQUAD c; for (int i=0;i<256;i++){ c=GetPaletteColor(i); pal[3*i+0] = c.rgbRed; pal[3*i+1] = c.rgbGreen; pal[3*i+2] = c.rgbBlue; } hFile->Write(pal,768,1); free(pal); } } else { //(head.biBitCount==4) || (head.biBitCount==1) RGBQUAD *rgb = GetPalette(); bool binvert = false; if (CompareColors(&rgb[0],&rgb[1])>0) binvert=(head.biBitCount==1); BYTE* plane = (BYTE*)malloc(pcxHeader.BytesPerLine); BYTE* raw = (BYTE*)malloc(head.biWidth); for(y = head.biHeight-1; y >=0 ; y--) { for( x = 0; x < head.biWidth; x++) raw[x] = (BYTE)GetPixelIndex(x,y); if (binvert) for( x = 0; x < head.biWidth; x++) raw[x] = 1-raw[x]; for( x = 0; x < pcxHeader.ColorPlanes; x++ ) { PCX_PixelsToPlanes(raw, head.biWidth, plane, x); PCX_PackPlanes(plane, pcxHeader.BytesPerLine, buffer); } } free(plane); free(raw); hFile->Write(buffer.GetBuffer(false),buffer.Size(),1); } } catch (char *message) { strncpy(info.szLastError,message,255); return false; } return true; }
bool CxImageGIF::Encode(CxFile * fp) { if (EncodeSafeCheck(fp)) return false; GifFileType *GifFile = NULL; ColorMapObject *OutputColorMap = NULL; int i, ColorMapSize; if(head.biBitCount != 8) { if(head.biBitCount < 8)IncreaseBpp(8); else DecreaseBpp(8, true); } try { GifFile = EGifOpen(fp, writeCxFile); ColorMapSize = head.biClrUsed; OutputColorMap = MakeMapObject(ColorMapSize, NULL); RGBQUAD* pPal = GetPalette(); for(i=0; i<ColorMapSize; ++i) { OutputColorMap->Colors[i].Red = pPal[i].rgbRed; OutputColorMap->Colors[i].Green = pPal[i].rgbGreen; OutputColorMap->Colors[i].Blue = pPal[i].rgbBlue; } EGifPutScreenDesc(GifFile, head.biWidth, head.biHeight, OutputColorMap->ColorCount, info.nBkgndIndex== -1 ? 0 : info.nBkgndIndex, OutputColorMap); FreeMapObject(OutputColorMap); OutputColorMap = NULL; if(info.nBkgndIndex != -1) { unsigned char ExtStr[4] = { 1, 0, 0, info.nBkgndIndex }; EGifPutExtension(GifFile, GRAPHICS_EXT_FUNC_CODE, 4, ExtStr); } EGifPutImageDesc(GifFile, 0, 0, head.biWidth, head.biHeight, FALSE, NULL); for (i = 0; i < head.biHeight; i++) EGifPutLine(GifFile, GetBits(head.biHeight - i - 1), head.biWidth); EGifCloseFile(GifFile); GifFile = NULL; } catch (int errid) { strncpy(info.szLastError,GifGetErrorMessage(errid),255); if(OutputColorMap) { FreeMapObject(OutputColorMap); OutputColorMap = NULL; } if(GifFile) { EGifCloseFile(GifFile); GifFile = NULL; } return false; } catch (char *message) { strncpy(info.szLastError,message,255); if(OutputColorMap) { FreeMapObject(OutputColorMap); OutputColorMap = NULL; } if(GifFile) { EGifCloseFile(GifFile); GifFile = NULL; } return false; } return true; }