Update of /cvsroot/vba/VisualBoyAdvance/win32/dependencies/cximage In directory sc8-pr-cvs9.sourceforge.net:/tmp/cvs-serv12280/win32/dependencies/cximage Added Files: cximage.vcproj license.txt tif_xfile.cpp xfile.h ximabmp.cpp ximabmp.h ximacfg.h ximadef.h ximadsp.cpp ximaenc.cpp ximaexif.cpp ximage.cpp ximage.h ximagif.cpp ximagif.h ximahist.cpp ximaico.cpp ximaico.h ximainfo.cpp ximaint.cpp ximaiter.h ximaj2k.cpp ximaj2k.h ximajas.cpp ximajas.h ximajbg.cpp ximajbg.h ximajpg.cpp ximajpg.h ximalpha.cpp ximalyr.cpp ximamng.cpp ximamng.h ximapal.cpp ximapcx.cpp ximapcx.h ximapng.cpp ximapng.h ximasel.cpp ximatga.cpp ximatga.h ximath.cpp ximath.h ximatif.cpp ximatif.h ximatran.cpp ximawbmp.cpp ximawbmp.h ximawmf.cpp ximawmf.h ximawnd.cpp xiofile.h xmemfile.cpp xmemfile.h Log Message: added CxImage source code and added a VC2005 project file for a static build --- NEW FILE: ximath.h --- #if !defined(__ximath_h) #define __ximath_h #include "ximadef.h" //***bd*** simple floating point point class DLL_EXP CxPoint2 { public: CxPoint2(); CxPoint2(float const x_, float const y_); CxPoint2(CxPoint2 const &p); float Distance(CxPoint2 const p2); float Distance(float const x_, float const y_); float x,y; }; //and simple rectangle class DLL_EXP CxRect2 { public: CxRect2(); CxRect2(float const x1_, float const y1_, float const x2_, float const y2_); CxRect2(CxPoint2 const &bl, CxPoint2 const &tr); CxRect2(CxRect2 const &p); float Surface() const; CxRect2 CrossSection(CxRect2 const &r2) const; CxPoint2 Center() const; float Width() const; float Height() const; CxPoint2 botLeft; CxPoint2 topRight; }; #endif --- NEW FILE: ximapcx.cpp --- /* * File: ximapcx.cpp * Purpose: Platform Independent PCX Image Class Loader and Writer * 05/Jan/2002 Davide Pizzolato - www.xdp.it * CxImage version 5.99c 17/Oct/2004 * * based on ppmtopcx.c - convert a portable pixmap to PCX * Copyright (C) 1994 by Ingo Wilken (Ing...@in...) * based on ppmtopcx.c by Michael Davidson */ #include "ximapcx.h" #if CXIMAGE_SUPPORT_PCX #include "xmemfile.h" #define PCX_MAGIC 0X0A // PCX magic number #define PCX_256_COLORS 0X0C // magic number for 256 colors #define PCX_HDR_SIZE 128 // size of PCX header #define PCX_MAXCOLORS 256 #define PCX_MAXPLANES 4 #define PCX_MAXVAL 255 //////////////////////////////////////////////////////////////////////////////// bool CxImagePCX::Decode(CxFile *hFile) { if (hFile == NULL) return false; PCXHEADER pcxHeader; int i, x, y, y2, nbytes, count, Height, Width; BYTE c, ColorMap[PCX_MAXCOLORS][3]; BYTE *pcximage = NULL, *lpHead1 = NULL, *lpHead2 = NULL; BYTE *pcxplanes, *pcxpixels; try { if (hFile->Read(&pcxHeader,sizeof(PCXHEADER),1)==0) throw "Can't read PCX image"; if (pcxHeader.Manufacturer != PCX_MAGIC) throw "Error: Not a PCX file"; // Check for PCX run length encoding if (pcxHeader.Encoding != 1) throw "PCX file has unknown encoding scheme"; Width = (pcxHeader.Xmax - pcxHeader.Xmin) + 1; Height = (pcxHeader.Ymax - pcxHeader.Ymin) + 1; info.xDPI = pcxHeader.Hres; info.yDPI = pcxHeader.Vres; // Check that we can handle this image format if (pcxHeader.ColorPlanes > 4) throw "Can't handle image with more than 4 planes"; // Create the image if (pcxHeader.ColorPlanes >= 3 && pcxHeader.BitsPerPixel == 8){ Create (Width, Height, 24, CXIMAGE_FORMAT_PCX); #if CXIMAGE_SUPPORT_ALPHA if (pcxHeader.ColorPlanes==4) AlphaCreate(); #endif //CXIMAGE_SUPPORT_ALPHA } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 1) Create (Width, Height, 4, CXIMAGE_FORMAT_PCX); else Create (Width, Height, pcxHeader.BitsPerPixel, CXIMAGE_FORMAT_PCX); if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding //Read the image and check if it's ok nbytes = pcxHeader.BytesPerLine * pcxHeader.ColorPlanes * Height; lpHead1 = pcximage = (BYTE*)malloc(nbytes); while (nbytes > 0){ if (hFile == NULL || hFile->Eof()) throw "corrupted PCX"; hFile->Read(&c,1,1); if ((c & 0XC0) != 0XC0){ // Repeated group *pcximage++ = c; --nbytes; continue; } count = c & 0X3F; // extract count hFile->Read(&c,1,1); if (count > nbytes) throw "repeat count spans end of image"; nbytes -= count; while (--count >=0) *pcximage++ = c; } pcximage = lpHead1; //store the palette for (i = 0; i < 16; i++){ ColorMap[i][0] = pcxHeader.ColorMap[i][0]; ColorMap[i][1] = pcxHeader.ColorMap[i][1]; ColorMap[i][2] = pcxHeader.ColorMap[i][2]; } if (pcxHeader.BitsPerPixel == 8 && pcxHeader.ColorPlanes == 1){ hFile->Read(&c,1,1); if (c != PCX_256_COLORS) throw "bad color map signature"; for (i = 0; i < PCX_MAXCOLORS; i++){ hFile->Read(&ColorMap[i][0],1,1); hFile->Read(&ColorMap[i][1],1,1); hFile->Read(&ColorMap[i][2],1,1); } } if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){ ColorMap[0][0] = ColorMap[0][1] = ColorMap[0][2] = 0; ColorMap[1][0] = ColorMap[1][1] = ColorMap[1][2] = 255; } for (DWORD idx=0; idx<head.biClrUsed; idx++) SetPaletteColor((BYTE)idx,ColorMap[idx][0],ColorMap[idx][1],ColorMap[idx][2]); lpHead2 = pcxpixels = (BYTE *)malloc(Width + pcxHeader.BytesPerLine * 8); // Convert the image for (y = 0; y < Height; y++){ if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding y2=Height-1-y; pcxpixels = lpHead2; pcxplanes = pcximage + (y * pcxHeader.BytesPerLine * pcxHeader.ColorPlanes); if (pcxHeader.ColorPlanes == 3 && pcxHeader.BitsPerPixel == 8){ // Deal with 24 bit color image for (x = 0; x < Width; x++){ SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x])); } continue; #if CXIMAGE_SUPPORT_ALPHA } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 8){ for (x = 0; x < Width; x++){ SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x])); AlphaSet(x,y2,pcxplanes[3*pcxHeader.BytesPerLine + x]); } continue; #endif //CXIMAGE_SUPPORT_ALPHA } else if (pcxHeader.ColorPlanes == 1) { PCX_UnpackPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel); } else { PCX_PlanesToPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel); } for (x = 0; x < Width; x++) SetPixelIndex(x,y2,pcxpixels[x]); } } catch (char *message) { strncpy(info.szLastError,message,255); if (lpHead1){ free(lpHead1); lpHead1 = NULL; } if (lpHead2){ free(lpHead2); lpHead2 = NULL; } return false; } if (lpHead1){ free(lpHead1); lpHead1 = NULL; } if (lpHead2){ free(lpHead2); lpHead2 = NULL; } return true; } //////////////////////////////////////////////////////////////////////////////// #if CXIMAGE_SUPPORT_ENCODE //////////////////////////////////////////////////////////////////////////////// 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; } //////////////////////////////////////////////////////////////////////////////// #endif // CXIMAGE_SUPPORT_ENCODE //////////////////////////////////////////////////////////////////////////////// // Convert multi-plane format into 1 pixel per byte // from unpacked file data bitplanes[] into pixel row pixels[] // image Height rows, with each row having planes image planes each // bytesperline bytes void CxImagePCX::PCX_PlanesToPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel) { int i, j, npixels; BYTE * p; if (planes > 4) throw "Can't handle more than 4 planes"; if (bitsperpixel != 1) throw "Can't handle more than 1 bit per pixel"; // Clear the pixel buffer npixels = (bytesperline * 8) / bitsperpixel; p = pixels; while (--npixels >= 0) *p++ = 0; // Do the format conversion for (i = 0; i < planes; i++){ int pixbit, bits, mask; p = pixels; pixbit = (1 << i); // pixel bit for this plane for (j = 0; j < bytesperline; j++){ bits = *bitplanes++; for (mask = 0X80; mask != 0; mask >>= 1, p++) if (bits & mask) *p |= pixbit; } } } //////////////////////////////////////////////////////////////////////////////// // convert packed pixel format into 1 pixel per byte // from unpacked file data bitplanes[] into pixel row pixels[] // image Height rows, with each row having planes image planes each // bytesperline bytes void CxImagePCX::PCX_UnpackPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel) { register int bits; if (planes != 1) throw "Can't handle packed pixels with more than 1 plane."; if (bitsperpixel == 8){ // 8 bits/pixels, no unpacking needed while (bytesperline-- > 0) *pixels++ = *bitplanes++; } else if (bitsperpixel == 4){ // 4 bits/pixel, two pixels per byte while (bytesperline-- > 0){ bits = *bitplanes++; *pixels++ = (BYTE)((bits >> 4) & 0X0F); *pixels++ = (BYTE)((bits) & 0X0F); } } else if (bitsperpixel == 2){ // 2 bits/pixel, four pixels per byte while (bytesperline-- > 0){ bits = *bitplanes++; *pixels++ = (BYTE)((bits >> 6) & 0X03); *pixels++ = (BYTE)((bits >> 4) & 0X03); *pixels++ = (BYTE)((bits >> 2) & 0X03); *pixels++ = (BYTE)((bits) & 0X03); } } else if (bitsperpixel == 1){ // 1 bits/pixel, 8 pixels per byte while (bytesperline-- > 0){ bits = *bitplanes++; *pixels++ = ((bits & 0X80) != 0); *pixels++ = ((bits & 0X40) != 0); *pixels++ = ((bits & 0X20) != 0); *pixels++ = ((bits & 0X10) != 0); *pixels++ = ((bits & 0X08) != 0); *pixels++ = ((bits & 0X04) != 0); *pixels++ = ((bits & 0X02) != 0); *pixels++ = ((bits & 0X01) != 0); } } } //////////////////////////////////////////////////////////////////////////////// /* PCX_PackPixels(const long p,BYTE &c, BYTE &n, long &l, CxFile &f) * p = current pixel (-1 ends the line -2 ends odd line) * c = previous pixel * n = number of consecutive pixels */ void CxImagePCX::PCX_PackPixels(const long p,BYTE &c, BYTE &n, CxFile &f) { if (p!=c && n){ if (n==1 && c<0xC0){ f.PutC(c); } else { f.PutC(0xC0|n); f.PutC(c); } n=0; } if (n==0x3F) { f.PutC(0xFF); f.PutC(c); n=0; } if (p==-2) f.PutC(0); c=(BYTE)p; n++; } //////////////////////////////////////////////////////////////////////////////// void CxImagePCX::PCX_PackPlanes(BYTE* buff, const long size, CxFile &f) { BYTE *start,*end; BYTE c, previous, count; start = buff; end = buff + size; previous = *start++; count = 1; while (start < end) { c = *start++; if (c == previous && count < 63) { ++count; continue; } if (count > 1 || (previous & 0xc0) == 0xc0) { f.PutC( count | 0xc0 ); } f.PutC(previous); previous = c; count = 1; } if (count > 1 || (previous & 0xc0) == 0xc0) { count |= 0xc0; f.PutC(count); } f.PutC(previous); } //////////////////////////////////////////////////////////////////////////////// void CxImagePCX::PCX_PixelsToPlanes(BYTE* raw, long width, BYTE* buf, long plane) { int cbit, x, mask; unsigned char *cp = buf-1; mask = 1 << plane; cbit = -1; for( x = 0; x < width; x++ ) { if( cbit < 0 ) { cbit = 7; *++cp = 0; } if( raw[x] & mask ) *cp |= (1<<cbit); --cbit; } } //////////////////////////////////////////////////////////////////////////////// #endif // CXIMAGE_SUPPORT_PCX --- NEW FILE: ximawbmp.h --- /* * File: ximawbmp.h * Purpose: WBMP Image Class Loader and Writer */ /* ========================================================== * CxImageWBMP (c) 12/Jul/2002 Davide Pizzolato - www.xdp.it * For conditions of distribution and use, see copyright notice in ximage.h * ========================================================== */ #if !defined(__ximaWBMP_h) #define __ximaWBMP_h #include "ximage.h" #if CXIMAGE_SUPPORT_WBMP class CxImageWBMP: public CxImage { #pragma pack(1) typedef struct tagWbmpHeader { BYTE Type; // 0 BYTE FixHeader; // 0 BYTE ImageWidth; // Image Width BYTE ImageHeight; // Image Height } WBMPHEADER; #pragma pack() public: CxImageWBMP(): CxImage(CXIMAGE_FORMAT_WBMP) {} // bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_WBMP);} // bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_WBMP);} bool Decode(CxFile * hFile); bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } #if CXIMAGE_SUPPORT_ENCODE bool Encode(CxFile * hFile); bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); } #endif // CXIMAGE_SUPPORT_ENCODE }; #endif #endif --- NEW FILE: cximage.vcproj --- <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject ProjectType="Visual C++" Version="8,00" Name="cximage" ProjectGUID="{DB5C12E9-BCD3-4517-8708-475C0D1D88CE}" RootNamespace="cximage" Keyword="Win32Proj" > <Platforms> <Platform Name="Win32" /> </Platforms> <ToolFiles> </ToolFiles> <Configurations> <Configuration Name="Debug|Win32" OutputDirectory="$(SolutionDir)$(ConfigurationName)" IntermediateDirectory="$(ConfigurationName)" ConfigurationType="4" CharacterSet="0" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" /> <Tool Name="VCXMLDataGeneratorTool" /> <Tool Name="VCWebServiceProxyGeneratorTool" /> <Tool Name="VCMIDLTool" /> <Tool Name="VCCLCompilerTool" Optimization="0" PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS;JAS_WIN_MSVC_BUILD" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" WarningLevel="3" Detect64BitPortabilityProblems="false" DebugInformationFormat="4" /> <Tool Name="VCManagedResourceCompilerTool" /> <Tool Name="VCResourceCompilerTool" /> <Tool Name="VCPreLinkEventTool" /> <Tool Name="VCLibrarianTool" /> <Tool Name="VCALinkTool" /> <Tool Name="VCXDCMakeTool" /> <Tool Name="VCBscMakeTool" /> <Tool Name="VCFxCopTool" /> <Tool Name="VCPostBuildEventTool" /> </Configuration> <Configuration Name="Release|Win32" OutputDirectory="$(SolutionDir)$(ConfigurationName)" IntermediateDirectory="$(ConfigurationName)" ConfigurationType="4" CharacterSet="0" WholeProgramOptimization="1" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" /> <Tool Name="VCXMLDataGeneratorTool" /> <Tool Name="VCWebServiceProxyGeneratorTool" /> <Tool Name="VCMIDLTool" /> <Tool Name="VCCLCompilerTool" PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS;JAS_WIN_MSVC_BUILD" RuntimeLibrary="0" UsePrecompiledHeader="0" WarningLevel="3" Detect64BitPortabilityProblems="false" DebugInformationFormat="3" /> <Tool Name="VCManagedResourceCompilerTool" /> <Tool Name="VCResourceCompilerTool" /> <Tool Name="VCPreLinkEventTool" /> <Tool Name="VCLibrarianTool" /> <Tool Name="VCALinkTool" /> <Tool Name="VCXDCMakeTool" /> <Tool Name="VCBscMakeTool" /> <Tool Name="VCFxCopTool" /> <Tool Name="VCPostBuildEventTool" /> </Configuration> </Configurations> <References> </References> <Files> <Filter Name="Source Files" Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > <File RelativePath=".\tif_xfile.cpp" > </File> <File RelativePath=".\ximabmp.cpp" > </File> <File RelativePath=".\ximadsp.cpp" > </File> <File RelativePath=".\ximaenc.cpp" > </File> <File RelativePath=".\ximaexif.cpp" > </File> <File RelativePath=".\ximage.cpp" > </File> <File RelativePath=".\ximagif.cpp" > </File> <File RelativePath=".\ximahist.cpp" > </File> <File RelativePath=".\ximaico.cpp" > </File> <File RelativePath=".\ximainfo.cpp" > </File> <File RelativePath=".\ximaint.cpp" > </File> <File RelativePath=".\ximaj2k.cpp" > </File> <File RelativePath=".\ximajas.cpp" > </File> <File RelativePath=".\ximajbg.cpp" > </File> <File RelativePath=".\ximajpg.cpp" > </File> <File RelativePath=".\ximalpha.cpp" > </File> <File RelativePath=".\ximalyr.cpp" > </File> <File RelativePath=".\ximamng.cpp" > </File> <File RelativePath=".\ximapal.cpp" > </File> <File RelativePath=".\ximapcx.cpp" > </File> <File RelativePath=".\ximapng.cpp" > </File> <File RelativePath=".\ximasel.cpp" > </File> <File RelativePath=".\ximatga.cpp" > </File> <File RelativePath=".\ximath.cpp" > </File> <File RelativePath=".\ximatif.cpp" > </File> <File RelativePath=".\ximatran.cpp" > </File> <File RelativePath=".\ximawbmp.cpp" > </File> <File RelativePath=".\ximawmf.cpp" > </File> <File RelativePath=".\ximawnd.cpp" > </File> <File RelativePath=".\xmemfile.cpp" > </File> </Filter> <Filter Name="Header Files" Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > <File RelativePath=".\xfile.h" > </File> <File RelativePath=".\ximabmp.h" > </File> <File RelativePath=".\ximacfg.h" > </File> <File RelativePath=".\ximadef.h" > </File> <File RelativePath=".\ximage.h" > </File> <File RelativePath=".\ximagif.h" > </File> <File RelativePath=".\ximaico.h" > </File> <File RelativePath=".\ximaiter.h" > </File> <File RelativePath=".\ximaj2k.h" > </File> <File RelativePath=".\ximajas.h" > </File> <File RelativePath=".\ximajbg.h" > </File> <File RelativePath=".\ximajpg.h" > </File> <File RelativePath=".\ximamng.h" > </File> <File RelativePath=".\ximapcx.h" > </File> <File RelativePath=".\ximapng.h" > </File> <File RelativePath=".\ximatga.h" > </File> <File RelativePath=".\ximath.h" > </File> <File RelativePath=".\ximatif.h" > </File> <File RelativePath=".\ximawbmp.h" > </File> <File RelativePath=".\ximawmf.h" > </File> <File RelativePath=".\xiofile.h" > </File> <File RelativePath=".\xmemfile.h" > </File> </Filter> </Files> <Globals> </Globals> </VisualStudioProject> --- NEW FILE: ximatif.cpp --- /* * File: ximatif.cpp * Purpose: Platform Independent TIFF Image Class Loader and Writer * 07/Aug/2001 Davide Pizzolato - www.xdp.it * CxImage version 5.99c 17/Oct/2004 */ #include "ximatif.h" #if CXIMAGE_SUPPORT_TIF #include "../tiff/tiffio.h" #define CVT(x) (((x) * 255L) / ((1L<<16)-1)) #define SCALE(x) (((x)*((1L<<16)-1))/255) #define CalculateLine(width,bitdepth) (((width * bitdepth) + 7) / 8) #define CalculatePitch(line) (line + 3 & ~3) extern "C" TIFF* _TIFFOpenEx(CxFile* stream, const char* mode); //////////////////////////////////////////////////////////////////////////////// CxImageTIF::~CxImageTIF() { if (m_tif2) TIFFClose(m_tif2); } //////////////////////////////////////////////////////////////////////////////// bool CxImageTIF::Decode(CxFile * hFile) { //Comment this line if you need more information on errors // TIFFSetErrorHandler(NULL); //<Patrick Hoffmann> //Open file and fill the TIFF structure // m_tif = TIFFOpen(imageFileName,"rb"); TIFF* m_tif = _TIFFOpenEx(hFile, "rb"); uint32 height=0; uint32 width=0; uint16 bitspersample=1; uint16 samplesperpixel=1; uint32 rowsperstrip=(DWORD)-1; uint16 photometric=0; uint16 compression=1; uint16 orientation=ORIENTATION_TOPLEFT; //<vho> uint16 res_unit; //<Trifon> uint32 x, y; float resolution, offset; BOOL isRGB; BYTE *bits; //pointer to source data BYTE *bits2; //pointer to destination data try{ //check if it's a tiff file if (!m_tif) throw "Error encountered while opening TIFF file"; // <Robert Abram> - 12/2002 : get NumFrames directly, instead of looping // info.nNumFrames=0; // while(TIFFSetDirectory(m_tif,(uint16)info.nNumFrames)) info.nNumFrames++; info.nNumFrames = TIFFNumberOfDirectories(m_tif); if (!TIFFSetDirectory(m_tif, (uint16)info.nFrame)) throw "Error: page not present in TIFF file"; //get image info TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height); TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &photometric); TIFFGetField(m_tif, TIFFTAG_ORIENTATION, &orientation); if (info.nEscape == -1) { // Return output dimensions only head.biWidth = width; head.biHeight = height; throw "output dimensions returned"; } TIFFGetFieldDefaulted(m_tif, TIFFTAG_RESOLUTIONUNIT, &res_unit); if (TIFFGetField(m_tif, TIFFTAG_XRESOLUTION, &resolution)) { if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f); SetXDPI((long)resolution); } if (TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &resolution)) { if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f); SetYDPI((long)resolution); } if (TIFFGetField(m_tif, TIFFTAG_XPOSITION, &offset)) info.xOffset = (long)offset; if (TIFFGetField(m_tif, TIFFTAG_YPOSITION, &offset)) info.yOffset = (long)offset; head.biClrUsed=0; info.nBkgndIndex =-1; if (rowsperstrip>height){ rowsperstrip=height; TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); } isRGB = (bitspersample >= 8) && (photometric == PHOTOMETRIC_RGB) || (photometric == PHOTOMETRIC_YCBCR) || (photometric == PHOTOMETRIC_SEPARATED) || (photometric == PHOTOMETRIC_LOGL) || (photometric == PHOTOMETRIC_LOGLUV); if (isRGB){ head.biBitCount=24; }else{ if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE)){ if (bitspersample == 1){ head.biBitCount=1; //B&W image head.biClrUsed =2; } else if (bitspersample == 4) { head.biBitCount=4; //16 colors gray scale head.biClrUsed =16; } else { head.biBitCount=8; //gray scale head.biClrUsed =256; } } else if (bitspersample == 4) { head.biBitCount=4; // 16 colors head.biClrUsed=16; } else { head.biBitCount=8; //256 colors head.biClrUsed=256; } } if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding Create(width,height,head.biBitCount,CXIMAGE_FORMAT_TIF); //image creation if (!pDib) throw "CxImageTIF can't create image"; #if CXIMAGE_SUPPORT_ALPHA if (samplesperpixel==4) AlphaCreate(); //add alpha support for 32bpp tiffs if (samplesperpixel==2 && bitspersample==8) AlphaCreate(); //add alpha support for 8bpp + alpha #endif //CXIMAGE_SUPPORT_ALPHA TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression); SetCodecOption(compression); // <DPR> save original compression type if (isRGB) { // Read the whole image into one big RGBA buffer using // the traditional TIFFReadRGBAImage() API that we trust. uint32* raster; // retrieve RGBA image uint32 *row; raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32)); if (raster == NULL) throw "No space for raster buffer"; // Read the image in one chunk into an RGBA array if(!TIFFReadRGBAImage(m_tif, width, height, raster, 1)) { _TIFFfree(raster); throw "Corrupted TIFF file!"; } // read the raster lines and save them in the DIB // with RGB mode, we have to change the order of the 3 samples RGB row = &raster[0]; bits2 = info.pImage; for (y = 0; y < height; y++) { if (info.nEscape){ // <vho> - cancel decoding _TIFFfree(raster); throw "Cancelled"; } bits = bits2; for (x = 0; x < width; x++) { *bits++ = (BYTE)TIFFGetB(row[x]); *bits++ = (BYTE)TIFFGetG(row[x]); *bits++ = (BYTE)TIFFGetR(row[x]); #if CXIMAGE_SUPPORT_ALPHA if (samplesperpixel==4) AlphaSet(x,y,(BYTE)TIFFGetA(row[x])); #endif //CXIMAGE_SUPPORT_ALPHA } row += width; bits2 += info.dwEffWidth; } _TIFFfree(raster); } else { RGBQUAD *pal; pal=(RGBQUAD*)calloc(256,sizeof(RGBQUAD)); if (pal==NULL) throw "Unable to allocate TIFF palette"; // set up the colormap based on photometric switch(photometric) { case PHOTOMETRIC_MINISBLACK: // bitmap and greyscale image types case PHOTOMETRIC_MINISWHITE: if (bitspersample == 1) { // Monochrome image if (photometric == PHOTOMETRIC_MINISBLACK) { pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; } else { pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255; } } else { // need to build the scale for greyscale images if (photometric == PHOTOMETRIC_MINISBLACK) { for (DWORD i=0; i<head.biClrUsed; i++){ pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(i*(255/(head.biClrUsed-1))); } } else { for (DWORD i=0; i<head.biClrUsed; i++){ pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(255-i*(255/(head.biClrUsed-1))); } } } break; case PHOTOMETRIC_PALETTE: // color map indexed uint16 *red; uint16 *green; uint16 *blue; TIFFGetField(m_tif, TIFFTAG_COLORMAP, &red, &green, &blue); // Is the palette 16 or 8 bits ? BOOL Palette16Bits = FALSE; int n=1<<bitspersample; while (n-- > 0) { if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256) { Palette16Bits=TRUE; break; } } // load the palette in the DIB for (int i = (1 << bitspersample) - 1; i >= 0; i--) { if (Palette16Bits) { pal[i].rgbRed =(BYTE) CVT(red[i]); pal[i].rgbGreen = (BYTE) CVT(green[i]); pal[i].rgbBlue = (BYTE) CVT(blue[i]); } else { pal[i].rgbRed = (BYTE) red[i]; pal[i].rgbGreen = (BYTE) green[i]; pal[i].rgbBlue = (BYTE) blue[i]; } } break; } SetPalette(pal,head.biClrUsed); //palette assign free(pal); // read the tiff lines and save them in the DIB uint32 nrow; uint32 ys; int line = CalculateLine(width, bitspersample * samplesperpixel); long bitsize= TIFFStripSize(m_tif); //verify bitsize: could be wrong if StripByteCounts is missing. if (bitsize>(long)(head.biSizeImage*samplesperpixel)) bitsize=head.biSizeImage*samplesperpixel; int tiled_image = TIFFIsTiled(m_tif); uint32 tw, tl; BYTE* tilebuf; if (tiled_image){ TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &tw); TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &tl); rowsperstrip = tl; bitsize = TIFFTileSize(m_tif) * (int)(1+width/tw); tilebuf = (BYTE*)malloc(TIFFTileSize(m_tif)); } bits = (BYTE*)malloc(bitsize); if (bits==NULL){ throw "CxImageTIF can't allocate memory"; } for (ys = 0; ys < height; ys += rowsperstrip) { if (info.nEscape){ // <vho> - cancel decoding free(bits); throw "Cancelled"; } nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip); if (tiled_image){ uint32 imagew = TIFFScanlineSize(m_tif); uint32 tilew = TIFFTileRowSize(m_tif); int iskew = imagew - tilew; uint8* bufp = (uint8*) bits; uint32 colb = 0; for (uint32 col = 0; col < width; col += tw) { if (TIFFReadTile(m_tif, tilebuf, col, ys, 0, 0) < 0){ free(tilebuf); free(bits); throw "Corrupted tiled TIFF file!"; } if (colb + tw > imagew) { uint32 owidth = imagew - colb; uint32 oskew = tilew - owidth; TileToStrip(bufp + colb, tilebuf, nrow, owidth, oskew + iskew, oskew ); } else { TileToStrip(bufp + colb, tilebuf, nrow, tilew, iskew, 0); } colb += tilew; } } else { if (TIFFReadEncodedStrip(m_tif, TIFFComputeStrip(m_tif, ys, 0), bits, nrow * line) == -1) { free(bits); throw "Corrupted TIFF file!"; } } for (y = 0; y < nrow; y++) { long offset=(nrow-y-1)*line; if (bitspersample==16) for (DWORD xi=0;xi<width;xi++) bits[xi+offset]=bits[xi*2+offset+1]; if (samplesperpixel==1) { //simple 8bpp image memcpy(info.pImage+info.dwEffWidth*(height-ys-nrow+y),bits+offset,info.dwEffWidth); } else if (samplesperpixel==2) { //8bpp image with alpha layer int xi=0; int ii=0; int yi=height-ys-nrow+y; while (ii<line){ SetPixelIndex(xi,yi,bits[ii+offset]); #if CXIMAGE_SUPPORT_ALPHA AlphaSet(xi,yi,bits[ii+offset+1]); #endif //CXIMAGE_SUPPORT_ALPHA ii+=2; xi++; if (xi>=(int)width){ yi--; xi=0; } } } else { //photometric==PHOTOMETRIC_CIELAB if (head.biBitCount!=24){ //fix image Create(width,height,24,CXIMAGE_FORMAT_TIF); #if CXIMAGE_SUPPORT_ALPHA if (samplesperpixel==4) AlphaCreate(); #endif //CXIMAGE_SUPPORT_ALPHA } int xi=0; int ii=0; int yi=height-ys-nrow+y; RGBQUAD c; int l,a,b,bitsoffset; double p,cx,cy,cz,cr,cg,cb; while (ii<line){ bitsoffset = ii*samplesperpixel+offset; l=bits[bitsoffset]; a=bits[bitsoffset+1]; b=bits[bitsoffset+2]; if (a>127) a-=256; if (b>127) b-=256; // lab to xyz p = (l/2.55 + 16) / 116.0; cx = pow( p + a * 0.002, 3); cy = pow( p, 3); cz = pow( p - b * 0.005, 3); // white point cx*=0.95047; //cy*=1.000; cz*=1.0883; // xyz to rgb cr = 3.240479 * cx - 1.537150 * cy - 0.498535 * cz; cg = -0.969256 * cx + 1.875992 * cy + 0.041556 * cz; cb = 0.055648 * cx - 0.204043 * cy + 1.057311 * cz; if ( cr > 0.00304 ) cr = 1.055 * pow(cr,0.41667) - 0.055; else cr = 12.92 * cr; if ( cg > 0.00304 ) cg = 1.055 * pow(cg,0.41667) - 0.055; else cg = 12.92 * cg; if ( cb > 0.00304 ) cb = 1.055 * pow(cb,0.41667) - 0.055; else cb = 12.92 * cb; c.rgbRed =(BYTE)max(0,min(255,(int)(cr*255))); c.rgbGreen=(BYTE)max(0,min(255,(int)(cg*255))); c.rgbBlue =(BYTE)max(0,min(255,(int)(cb*255))); SetPixelColor(xi,yi,c); #if CXIMAGE_SUPPORT_ALPHA if (samplesperpixel==4) AlphaSet(xi,yi,bits[bitsoffset+3]); #endif //CXIMAGE_SUPPORT_ALPHA ii++; xi++; if (xi>=(int)width){ yi--; xi=0; } } } } } free(bits); if (tiled_image) free(tilebuf); switch(orientation){ case ORIENTATION_TOPRIGHT: /* row 0 top, col 0 rhs */ Mirror(); break; case ORIENTATION_BOTRIGHT: /* row 0 bottom, col 0 rhs */ Flip(); Mirror(); break; case ORIENTATION_BOTLEFT: /* row 0 bottom, col 0 lhs */ Flip(); break; case ORIENTATION_LEFTTOP: /* row 0 lhs, col 0 top */ RotateRight(); Mirror(); break; case ORIENTATION_RIGHTTOP: /* row 0 rhs, col 0 top */ RotateLeft(); break; case ORIENTATION_RIGHTBOT: /* row 0 rhs, col 0 bottom */ RotateLeft(); Mirror(); break; case ORIENTATION_LEFTBOT: /* row 0 lhs, col 0 bottom */ RotateRight(); break; } } } catch (char *message) { strncpy(info.szLastError,message,255); if (m_tif) TIFFClose(m_tif); if (info.nEscape==-1) return true; return false; } TIFFClose(m_tif); return true; } //////////////////////////////////////////////////////////////////////////////// #if CXIMAGE_SUPPORT_ENCODE //////////////////////////////////////////////////////////////////////////////// bool CxImageTIF::Encode(CxFile * hFile, bool bAppend) { try{ if (hFile==NULL) throw CXIMAGE_ERR_NOFILE; if (pDib==NULL) throw CXIMAGE_ERR_NOIMAGE; // <RJ> replaced "w+b" with "a", to append an image directly on an existing file if (m_tif2==NULL) m_tif2=_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(m_tif2)) throw "Error saving TIFF directory"; } } catch (char *message) { strncpy(info.szLastError,message,255); if (m_tif2){ TIFFClose(m_tif2); m_tif2=NULL; m_multipage=false; m_pages=0; } return false; } if (!bAppend){ TIFFClose(m_tif2); m_tif2=NULL; m_multipage=false; m_pages=0; } return true; } //////////////////////////////////////////////////////////////////////////////// // Thanks to Abe <God(dot)bless(at)marihuana(dot)com> bool CxImageTIF::Encode(CxFile * hFile, CxImage ** pImages, int pagecount) { try{ if (hFile==NULL) throw "invalid file pointer"; if (pImages==NULL || pagecount==0) throw "multipage TIFF, no images!"; CxImageTIF ghost; for (int i=1; i<=pagecount; i++){ if (pImages[i-1]==NULL) throw "Bad image pointer"; ghost.Ghost(pImages[i-1]); if (!ghost.Encode(hFile,true)) throw "Error saving TIFF file"; } } catch (char *message) { strncpy(info.szLastError,message,255); return false; } return true; } //////////////////////////////////////////////////////////////////////////////// bool CxImageTIF::EncodeBody(TIFF *m_tif, bool multipage, int page, int pagecount) { uint32 height=head.biHeight; uint32 width=head.biWidth; uint16 bitcount=head.biBitCount; uint16 bitspersample; uint16 samplesperpixel; uint16 photometric=0; uint16 compression; // uint16 pitch; // int line; uint32 x, y; samplesperpixel = ((bitcount == 24) || (bitcount == 32)) ? (BYTE)3 : (BYTE)1; #if CXIMAGE_SUPPORT_ALPHA if (bitcount==24 && AlphaIsValid()) { bitcount=32; samplesperpixel=4; } #endif //CXIMAGE_SUPPORT_ALPHA bitspersample = bitcount / samplesperpixel; //set the PHOTOMETRIC tag RGBQUAD *rgb = GetPalette(); switch (bitcount) { case 1: if (CompareColors(&rgb[0],&rgb[1])<0) { /* <abe> some viewers do not handle PHOTOMETRIC_MINISBLACK: * let's transform the image in PHOTOMETRIC_MINISWHITE */ //invert the colors RGBQUAD tempRGB=GetPaletteColor(0); SetPaletteColor(0,GetPaletteColor(1)); SetPaletteColor(1,tempRGB); //invert the pixels BYTE *iSrc=info.pImage; for (unsigned long i=0;i<head.biSizeImage;i++){ *iSrc=(BYTE)~(*(iSrc)); iSrc++; } photometric = PHOTOMETRIC_MINISWHITE; //photometric = PHOTOMETRIC_MINISBLACK; } else { photometric = PHOTOMETRIC_MINISWHITE; } break; case 4: // Check if the DIB has a color or a greyscale palette case 8: photometric = PHOTOMETRIC_MINISBLACK; //default to gray scale for (x = 0; x < head.biClrUsed; x++) { if ((rgb->rgbRed != x)||(rgb->rgbRed != rgb->rgbGreen)||(rgb->rgbRed != rgb->rgbBlue)){ photometric = PHOTOMETRIC_PALETTE; break; } rgb++; } break; case 24: case 32: photometric = PHOTOMETRIC_RGB; break; } #if CXIMAGE_SUPPORT_ALPHA if (AlphaIsValid() && bitcount==8) samplesperpixel=2; //8bpp + alpha layer #endif //CXIMAGE_SUPPORT_ALPHA // line = CalculateLine(width, bitspersample * samplesperpixel); // pitch = (uint16)CalculatePitch(line); //prepare the palette struct RGBQUAD pal[256]; if (GetPalette()){ BYTE b; memcpy(pal,GetPalette(),GetPaletteSize()); for(WORD a=0;a<head.biClrUsed;a++){ //swap blue and red components b=pal[a].rgbBlue; pal[a].rgbBlue=pal[a].rgbRed; pal[a].rgbRed=b; } } // handle standard width/height/bpp stuff TIFFSetField(m_tif, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(m_tif, TIFFTAG_IMAGELENGTH, height); TIFFSetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); TIFFSetField(m_tif, TIFFTAG_BITSPERSAMPLE, bitspersample); TIFFSetField(m_tif, TIFFTAG_PHOTOMETRIC, photometric); TIFFSetField(m_tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // single image plane TIFFSetField(m_tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); uint32 rowsperstrip = TIFFDefaultStripSize(m_tif, (uint32) -1); //<REC> gives better compression TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); // handle metrics TIFFSetField(m_tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); TIFFSetField(m_tif, TIFFTAG_XRESOLUTION, (float)info.xDPI); TIFFSetField(m_tif, TIFFTAG_YRESOLUTION, (float)info.yDPI); // TIFFSetField(m_tif, TIFFTAG_XPOSITION, (float)info.xOffset); // TIFFSetField(m_tif, TIFFTAG_YPOSITION, (float)info.yOffset); // multi-paging - Thanks to Abe <God(dot)bless(at)marihuana(dot)com> if (multipage) { char page_number[20]; sprintf(page_number, "Page %d", page); TIFFSetField(m_tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); TIFFSetField(m_tif, TIFFTAG_PAGENUMBER, page,pagecount); TIFFSetField(m_tif, TIFFTAG_PAGENAME, page_number); } else { TIFFSetField(m_tif, TIFFTAG_SUBFILETYPE, 0); } // palettes (image colormaps are automatically scaled to 16-bits) if (photometric == PHOTOMETRIC_PALETTE) { uint16 *r, *g, *b; r = (uint16 *) _TIFFmalloc(sizeof(uint16) * 3 * 256); g = r + 256; b = g + 256; for (int i = 255; i >= 0; i--) { b[i] = (uint16)SCALE((uint16)pal[i].rgbRed); g[i] = (uint16)SCALE((uint16)pal[i].rgbGreen); r[i] = (uint16)SCALE((uint16)pal[i].rgbBlue); } TIFFSetField(m_tif, TIFFTAG_COLORMAP, r, g, b); _TIFFfree(r); } // compression if (GetCodecOption(CXIMAGE_FORMAT_TIF)) { compression = (WORD)GetCodecOption(CXIMAGE_FORMAT_TIF); } else { switch (bitcount) { case 1 : compression = COMPRESSION_CCITTFAX4; break; case 4 : case 8 : compression = COMPRESSION_LZW; break; case 24 : case 32 : compression = COMPRESSION_JPEG; break; default : compression = COMPRESSION_NONE; break; } } TIFFSetField(m_tif, TIFFTAG_COMPRESSION, compression); switch (compression) { case COMPRESSION_JPEG: TIFFSetField(m_tif, TIFFTAG_JPEGQUALITY, info.nQuality); TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, ((7+rowsperstrip)>>3)<<3); break; case COMPRESSION_LZW: if (bitcount>=8) TIFFSetField(m_tif, TIFFTAG_PREDICTOR, 2); break; } // read the DIB lines from bottom to top and save them in the TIF BYTE *bits; switch(bitcount) { case 1 : case 4 : case 8 : { if (samplesperpixel==1){ for (y = 0; y < height; y++) { bits= info.pImage + (height - y - 1)*info.dwEffWidth; if (TIFFWriteScanline(m_tif,bits, y, 0)==-1) return false; } } #if CXIMAGE_SUPPORT_ALPHA else { //8bpp + alpha layer bits = (BYTE*)malloc(2*width); if (!bits) return false; for (y = 0; y < height; y++) { for (x=0;x<width;x++){ bits[2*x]=GetPixelIndex(x,height - y - 1); bits[2*x+1]=AlphaGet(x,height - y - 1); } if (TIFFWriteScanline(m_tif,bits, y, 0)==-1) { free(bits); return false; } } free(bits); } #endif //CXIMAGE_SUPPORT_ALPHA break; } case 24: { BYTE *buffer = (BYTE *)malloc(info.dwEffWidth); if (!buffer) return false; for (y = 0; y < height; y++) { // get a pointer to the scanline memcpy(buffer, info.pImage + (height - y - 1)*info.dwEffWidth, info.dwEffWidth); // TIFFs store color data RGB instead of BGR BYTE *pBuf = buffer; for (x = 0; x < width; x++) { BYTE tmp = pBuf[0]; pBuf[0] = pBuf[2]; pBuf[2] = tmp; pBuf += 3; } // write the scanline to disc if (TIFFWriteScanline(m_tif, buffer, y, 0)==-1){ free(buffer); return false; } } free(buffer); break; } case 32 : { #if CXIMAGE_SUPPORT_ALPHA BYTE *buffer = (BYTE *)malloc((info.dwEffWidth*4)/3); if (!buffer) return false; for (y = 0; y < height; y++) { // get a pointer to the scanline memcpy(buffer, info.pImage + (height - y - 1)*info.dwEffWidth, info.dwEffWidth); // TIFFs store color data RGB instead of BGR BYTE *pSrc = buffer + 3 * width; BYTE *pDst = buffer + 4 * width; for (x = 0; x < width; x++) { pDst-=4; pSrc-=3; pDst[3] = AlphaGet(width-x-1,height-y-1); pDst[2] = pSrc[0]; pDst[1] = pSrc[1]; pDst[0] = pSrc[2]; } // write the scanline to disc if (TIFFWriteScanline(m_tif, buffer, y, 0)==-1){ free(buffer); return false; } } free(buffer); #endif //CXIMAGE_SUPPORT_ALPHA break; } } return true; } //////////////////////////////////////////////////////////////////////////////// #endif // CXIMAGE_SUPPORT_ENCODE //////////////////////////////////////////////////////////////////////////////// void CxImageTIF::TileToStrip(uint8* out, uint8* in, uint32 rows, uint32 cols, int outskew, int inskew) { while (rows-- > 0) { uint32 j = cols; while (j-- > 0) *out++ = *in++; out += outskew; in += inskew; } } //////////////////////////////////////////////////////////////////////////////// TIFF* CxImageTIF::TIFFOpenEx(CxFile * hFile) { if (hFile) return _TIFFOpenEx(hFile, "rb"); return NULL; } //////////////////////////////////////////////////////////////////////////////// void CxImageTIF::TIFFCloseEx(TIFF* tif) { if (tif) TIFFClose(tif); } //////////////////////////////////////////////////////////////////////////////// #endif // CXIMAGE_SUPPORT_TIF --- NEW FILE: ximatif.h --- /* * File: ximatif.h * Purpose: TIFF Image Class Loader and Writer */ /* ========================================================== * CxImageTIF (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it * For conditions of distribution and use, see copyright notice in ximage.h * * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes * * Special thanks to Abe <God(dot)bless(at)marihuana(dot)com> for MultiPageTIFF code. * * LibTIFF is: * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * ========================================================== */ #if !defined(__ximatif_h) #define __ximatif_h #include "ximage.h" #if CXIMAGE_SUPPORT_TIF #include "../tiff/tiffio.h" class DLL_EXP CxImageTIF: public CxImage { public: CxImageTIF(): CxImage(CXIMAGE_FORMAT_TIF) {m_tif2=NULL; m_multipage=false; m_pages=0;} ~CxImageTIF(); TIFF* TIFFOpenEx(CxFile * hFile); void TIFFCloseEx(TIFF* tif); // bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_TIF);} // bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_TIF);} bool Decode(CxFile * hFile); bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); } #if CXIMAGE_SUPPORT_ENCODE bool Encode(CxFile * hFile, bool bAppend=false); bool Encode(CxFile * hFile, CxImage ** pImages, int pagecount); bool Encode(FILE *hFile, bool bAppend=false) { CxIOFile file(hFile); return Encode(&file,bAppend); } bool Encode(FILE *hFile, CxImage ** pImages, int pagecount) { CxIOFile file(hFile); return Encode(&file, pImages, pagecount); } #endif // CXIMAGE_SUPPORT_ENCODE protected: void TileToStrip(uint8* out, uint8* in, uint32 rows, uint32 cols, int outskew, int inskew); bool EncodeBody(TIFF *m_tif, bool multipage=false, int page=0, int pagecount=0); TIFF *m_tif2; bool m_multipage; int m_pages; }; #endif #endif --- NEW FILE: ximath.cpp --- #include "ximage.h" #include "ximath.h" #include <math.h> //this module should contain some classes for geometrical transformations //usable with selections, etc... once it's done, that is. :) CxPoint2::CxPoint2() { x=y=0.0f; } CxPoint2::CxPoint2(float const x_, float const y_) { x=x_; y=y_; } CxPoint2::CxPoint2(CxPoint2 const &p) { x=p.x; y=p.y; } float CxPoint2::Distance(CxPoint2 const p2) { return (float)sqrt((x-p2.x)*(x-p2.x)+(y-p2.y)*(y-p2.y)); } float CxPoint2::Distance(float const x_, float const y_) { return (float)sqrt((x-x_)*(x-x_)+(y-y_)*(y-y_)); } CxRect2::CxRect2() { } CxRect2::CxRect2(float const x1_, float const y1_, float const x2_, float const y2_) { botLeft.x=x1_; botLeft.y=y1_; topRight.x=x2_; topRight.y=y2_; } CxRect2::CxRect2(CxRect2 const &p) { botLeft=p.botLeft; topRight=p.topRight; } float CxRect2::Surface() const /* * Returns the surface of rectangle. */ { return (topRight.x-botLeft.x)*(topRight.y-botLeft.y); } CxRect2 CxRect2::CrossSection(CxRect2 const &r2) const /* * Returns crossection with another rectangle. */ { CxRect2 cs; cs.botLeft.x=max(botLeft.x, r2.botLeft.x); cs.botLeft.y=max(botLeft.y, r2.botLeft.y); cs.topRight.x=min(topRight.x, r2.topRight.x); cs.topRight.y=min(topRight.y, r2.topRight.y); if (cs.botLeft.x<=cs.topRight.x && cs.botLeft.y<=cs.topRight.y) { return cs; } else { return CxRect2(0,0,0,0); }//if } CxPoint2 CxRect2::Center() const /* * Returns the center point of rectangle. */ { return CxPoint2((topRight.x+botLeft.x)/2.0f, (topRight.y+botLeft.y)/2.0f); } float CxRect2::Width() const //returns rectangle width { return topRight.x-botLeft.x; } float CxRect2::Height() const //returns rectangle height { return topRight.y-botLeft.y; } --- NEW FILE: ximasel.cpp --- // xImaSel.cpp : Selection functions /* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it * CxImage version 5.99c 17/Oct/2004 */ #include "ximage.h" #if CXIMAGE_SUPPORT_SELECTION //////////////////////////////////////////////////////////////////////////////// /** * Checks if the image has a valid selection. */ bool CxImage::SelectionIsValid() { return pSelection!=0; } //////////////////////////////////////////////////////////////////////////////// /** * Gets the smallest rectangle that contains the selection */ void CxImage::SelectionGetBox(RECT& r) { memcpy(&r,&info.rSelectionBox,sizeof(RECT)); } //////////////////////////////////////////////////////////////////////////////// /** * Empties the selection. */ bool CxImage::SelectionClear() { if (pSelection){ memset(pSelection,0,head.biWidth * head.biHeight); info.rSelectionBox.left = head.biWidth; info.rSelectionBox.bottom = head.biHeight; info.rSelectionBox.right = info.rSelectionBox.top = 0; return true; } return false; } //////////////////////////////////////////////////////////////////////////////// /** * Allocates an empty selection. */ bool CxImage::SelectionCreate() { SelectionDelete(); pSelection = (BYTE*)calloc(head.biWidth * head.biHeight, 1); return (pSelection!=0); } //////////////////////////////////////////////////////////////////////////////// /** * Deallocates the selction. */ bool CxImage::SelectionDelete() { if (pSelection){ free(pSelection); pSelection=NULL; } info.rSelectionBox.left = head.biWidth; info.rSelectionBox.bottom = head.biHeight; info.rSelectionBox.right = info.rSelectionBox.top = 0; return true; } //////////////////////////////////////////////////////////////////////////////// /** * Checks if the coordinates are inside the selection. */ bool CxImage::SelectionIsInside(long x, long y) { if (IsInside(x,y)){ if (pSelection==NULL) return true; return pSelection[x+y*head.biWidth]!=0; } return false; } //////////////////////////////////////////////////////////////////////////////// /** * Adds a rectangle to the existing selection. */ bool CxImage::SelectionAddRect(RECT r) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; RECT r2; if (r.left<r.right) {r2.left=r.left; r2.right=r.right; } else {r2.left=r.right ; r2.right=r.left; } if (r.bottom<r.top) {r2.bottom=r.bottom; r2.top=r.top; } else {r2.bottom=r.top ; r2.top=r.bottom; } if (info.rSelectionBox.top < r2.top) info.rSelectionBox.top = max(0L,min(head.biHeight,r2.top)); if (info.rSelectionBox.left > r2.left) info.rSelectionBox.left = max(0L,min(head.biWidth,r2.left)); if (info.rSelectionBox.right < r2.right) info.rSelectionBox.right = max(0L,min(head.biWidth,r2.right)); if (info.rSelectionBox.bottom > r2.bottom) info.rSelectionBox.bottom = max(0L,min(head.biHeight,r2.bottom)); long ymin = max(0L,min(head.biHeight,r2.bottom)); long ymax = max(0L,min(head.biHeight,r2.top)); long xmin = max(0L,min(head.biWidth,r2.left)); long xmax = max(0L,min(head.biWidth,r2.right)); for (long y=ymin; y<ymax; y++) memset(pSelection + xmin + y * head.biWidth, 255, xmax-xmin); return true; } //////////////////////////////////////////////////////////////////////////////// /** * Adds an ellipse to the existing selection. */ bool CxImage::SelectionAddEllipse(RECT r) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; long xradius = abs(r.right - r.left)/2; long yradius = abs(r.top - r.bottom)/2; if (xradius==0 || yradius==0) return false; long xcenter = (r.right + r.left)/2; long ycenter = (r.top + r.bottom)/2; if (info.rSelectionBox.left > (xcenter - xradius)) info.rSelectionBox.left = max(0L,min(head.biWidth,(xcenter - xradius))); if (info.rSelectionBox.right < (xcenter + xradius)) info.rSelectionBox.right = max(0L,min(head.biWidth,(xcenter + xradius))); if (info.rSelectionBox.bottom > (ycenter - yradius)) info.rSelectionBox.bottom = max(0L,min(head.biHeight,(ycenter - yradius))); if (info.rSelectionBox.top < (ycenter + yradius)) info.rSelectionBox.top = max(0L,min(head.biHeight,(ycenter + yradius))); long xmin = max(0L,min(head.biWidth,xcenter - xradius)); long xmax = max(0L,min(head.biWidth,xcenter + xradius)); long ymin = max(0L,min(head.biHeight,ycenter - yradius)); long ymax = max(0L,min(head.biHeight,ycenter + yradius)); long y,yo; for (y=ymin; y<ycenter; y++){ for (long x=xmin; x<xmax; x++){ yo = (long)(ycenter - yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2))); if (yo<y) pSelection[x + y * head.biWidth] = 255; } } for (y=ycenter; y<ymax; y++){ for (long x=xmin; x<xmax; x++){ yo = (long)(ycenter + yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2))); if (yo>y) pSelection[x + y * head.biWidth] = 255; } } return true; } //////////////////////////////////////////////////////////////////////////////// /** * Inverts the selection. */ bool CxImage::SelectionInvert() { if (pSelection) { BYTE *iSrc=pSelection; long n=head.biHeight*head.biWidth; for(long i=0; i < n; i++){ *iSrc=(BYTE)~(*(iSrc)); iSrc++; } return true; } return false; } //////////////////////////////////////////////////////////////////////////////// /** * Imports an existing region from another image with the same width and height. */ bool CxImage::SelectionCopy(CxImage &from) { if (from.pSelection == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false; if (pSelection==NULL) pSelection = (BYTE*)malloc(head.biWidth * head.biHeight); if (pSelection==NULL) return false; memcpy(pSelection,from.pSelection,head.biWidth * head.biHeight); memcpy(&info.rSelectionBox,&from.info.rSelectionBox,sizeof(RECT)); return true; } //////////////////////////////////////////////////////////////////////////////// /** * Adds a polygonal region to the existing selection. points points to an array of POINT structures. * Each structure specifies the x-coordinate and y-coordinate of one vertex of the polygon. * npoints specifies the number of POINT structures in the array pointed to by points. */ bool CxImage::SelectionAddPolygon(POINT *points, long npoints) { if (points==NULL || npoints<3) return false; if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; BYTE* plocal = (BYTE*)calloc(head.biWidth*head.biHeight, 1); RECT localbox = {head.biWidth,0,0,head.biHeight}; long x,y,i=0; POINT *current,*next,*start; //trace contour while (i < npoints){ current = &points[i]; if (current->x!=-1){ if (i==0 || (i>0 && points[i-1].x==-1)) start = &points[i]; if ((i+1)==npoints || points[i+1].x==-1) next = start; else next = &points[i+1]; float beta; if (current->x != next->x){ beta = (float)(next->y - current->y)/(float)(next->x - current->x); if (current->x < next->x){ for (x=current->x; x<=next->x; x++){ y = (long)(current->y + (x - current->x) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } else { for (x=current->x; x>=next->x; x--){ y = (long)(current->y + (x - current->x) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } } if (current->y != next->y){ beta = (float)(next->x - current->x)/(float)(next->y - current->y); if (current->y < next->y){ for (y=current->y; y<=next->y; y++){ x = (long)(current->x + (y - current->y) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } else { for (y=current->y; y>=next->y; y--){ x = (long)(current->x + (y - current->y) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } } } RECT r2; if (current->x < next->x) {r2.left=current->x; r2.right=next->x; } else {r2.left=next->x ; r2.right=current->x; } if (current->y < next->y) {r2.bottom=current->y; r2.top=next->y; } else {r2.bottom=next->y ; r2.top=current->y; } if (localbox.top < r2.top) localbox.top = max(0L,min(head.biHeight-1,r2.top+1)); if (localbox.left > r2.left) localbox.left = max(0L,min(head.biWidth-1,r2.left-1)); if (localbox.right < r2.right) localbox.right = max(0L,min(head.biWidth-1,r2.right+1)); if (localbox.bottom > r2.bottom) localbox.bottom = max(0L,min(head.biHeight-1,r2.bottom-1)); i++; } //fill the outer region long npix=(localbox.right - localbox.left)*(localbox.top - localbox.bottom); POINT* pix = (POINT*)calloc(npix,sizeof(POINT)); BYTE back=0, mark=1; long fx, fy, fxx, fyy, first, last,xmin,xmax,ymin,ymax; for (int side=0; side<4; side++){ switch(side){ case 0: xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.bottom+1; break; case 1: xmin=localbox.right; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.top+1; break; case 2: xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.top; ymax=localbox.top+1; break; case 3: xmin=localbox.left; xmax=localbox.left+1; ymin=localbox.bottom; ymax=localbox.top+1; break; } //fill from the border points for(y=ymin;y<ymax;y++){ for(x=xmin;x<xmax;x++){ if (plocal[x+y*head.biWidth]==0){ // Subject: FLOOD FILL ROUTINE Date: 12-23-97 (00:57) // Author: Petter Holmberg Code: QB, QBasic, PDS // Origin: pet...@us... Packet: GRAPHICS.ABC first=0; last=1; while(first!=last){ fx = pix[first].x; fy = pix[first].y; fxx = fx + x; fyy = fy + y; do { if ((plocal[fxx + fyy*head.biWidth] == back) && fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top ) { plocal[fxx + fyy*head.biWidth] = mark; if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy - 1; last++; if (last == npix) last = 0; } if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy + 1; last++; if (last == npix) last = 0; } } else { break; } fx++; fxx++; } while(1); fx = pix[first].x - 1; fy = pix[first].y; fxx = fx + x; fyy = fy + y; do { if ((plocal[fxx + fyy*head.biWidth] == back) && fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top ) { plocal[fxx + (y + fy)*head.biWidth] = mark; if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy - 1; last++; if (last == npix) last = 0; } if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy + 1; last++; if (last == npix) last = 0; } } else { break; } fx--; fxx--; } while(1); first++; if (first == npix) first = 0; } } } } } //transfer the region long yoffset; for (y=localbox.bottom; y<=localbox.top; y++){ yoffset = y * head.biWidth; for (x=localbox.left; x<=localbox.right; x++) if (plocal[x + yoffset]!=1) pSelection[x + yoffset]=255; } if (info.rSelectionBox.top < localbox.top) info.rSelectionBox.top = localbox.top+1; if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = localbox.left; if (info.rSelection... [truncated message content] |