快讯

在BMP文件中隐藏信息

2004-02-14 09:34  出处:PConline  作者:网上收集  责任编辑:zwg 

作者: John Collomosse 关键字: BMP 加密 原作者姓名: John Collomosse 文章原始出处: http://www.blindside.co.uk/ 介绍 Blindside is a steganography application that hides information inside .BMP (bitmap) images. It is a command-line utility, for which source code and precompiled Unix binaries are available. The Blindside homepage is located at: http://www.blindside.co.uk/ 正文 #include < stdio.h > #include < stdlib.h > #include < string.h > /************************************\ * B L I N D S I D E * * * * Image stego/crypto tool, please * * see http://www.blindside.co.uk * * * * Compile with GCC or equiv ANSI C * * * * John Collomosse (mapjpc@bath.ac.uk)* * Freeware/public domain * * * \************************************/ #define HEAP_UNITSIZE (102400) #define HEAP_INITUNITS (1) #define LOOKUP_INITLEN (2048) #define FALSE (0) #define TRUE (-1) #define PATH_SEP ('\\') /* OS Specific Path Seperator */ #define BANNER ("BlindSide BMP Cryptographic Tool - (c) John Collomosse 2000\nRelease v0.9. All Rights Reserved, contact: ma7jpc@bath.ac.uk\n\n") #define THIS_PROTO_VER (1) /* Heap Structure (memory storage class for uchars) */ typedef struct heapstruct { unsigned int heapunits; /* Heap size to nearest 'unit' */ unsigned char *dataspace; /* Dataspace where data stored */ unsigned char *nextchar; /* Pointer to end of dataspace */ unsigned long heaplen; /* Length of data in heap */ } HEAP; typedef struct lookupstruct { unsigned long int* dataspace; unsigned long int currentlen; unsigned long int curitem; } LOOKUP; /* Bitmap Structure */ typedef struct bmpstruct { char* signature; long filesize; long x_size; long y_size; int bitplanes; int bpp; long compression; long compresssize; long x_pix_per_metre; long y_pix_per_metre; long colours; long cols_important; HEAP* palette; HEAP* raster; } BITMAP; typedef struct pixstruct { unsigned char red; unsigned char green; unsigned char blue; } PIXEL; /* Function prototypes */ int initialiseHeap (HEAP*); int expandHeap (int, HEAP*); void removeHeap (HEAP*); int putToHeap (unsigned char,HEAP*); int streamFileToHeap (FILE*, HEAP*); int readBitmapFile (FILE*, BITMAP*); void promoteTo24 (BITMAP*, BITMAP*); unsigned long resolveMaxEncode (BITMAP*, LOOKUP*); void writeBitmapFile (FILE*, BITMAP*); unsigned int biggest_of_3 (unsigned int,unsigned int,unsigned int); void longToStream (FILE*,unsigned long int); unsigned long streamToLong (FILE*); void process24gotpixel (unsigned char, unsigned char*,HEAP*); unsigned int calcEOLpad (int, long); PIXEL getIndexedPixel (unsigned long int, BITMAP*); void encodeData (BITMAP*, HEAP*, LOOKUP*); void setIndexedPixel (unsigned long int, BITMAP*, PIXEL); unsigned char getNextHeapBit (unsigned long int, int, HEAP*); int decodeData (BITMAP*, HEAP*); void cryptoData (HEAP* data, unsigned char* key); unsigned char xor (unsigned char, unsigned char); int rotl4 (int); int hash_func (unsigned char*); int pow (int,int); int stricmp (const char*, const char*); int formatDataspace (BITMAP*, HEAP*); void dumpFileDirectory (HEAP*); void dumpFileStats (BITMAP*, HEAP*); void addFileToArchive (HEAP*, FILE*, char*); int checkExists (char*); int extractFile (HEAP*, char*); void flattenBitmap (BITMAP*, LOOKUP*); int main (int argc, char** argv) { int mode; FILE* bitmap_handle=NULL; FILE* plaintext_handle=NULL; FILE* outfile_handle=NULL; BITMAP* BMPsource=NULL; BITMAP* BMPworking=NULL; HEAP* filespace=NULL; LOOKUP* hotspots; unsigned long int i; int isencrypted=FALSE; char password[130]; printf(BANNER); mode=0; if (argc >=2) { /* deduce mode of operation */ if (stricmp(argv[1],"-A")==0) mode=1; if (stricmp(argv[1],"-X")==0) mode=2; if (stricmp(argv[1],"-C")==0) mode=3; if (stricmp(argv[1],"-L")==0) mode=4; } if (mode==0 || (mode==1 && (argc!=5 && argc!=6)) || (mode==2 && (argc!=3 && argc!=4 && argc!=5)) || (mode==3 && argc!=3) || (mode==4 && argc!=3)) { printf("USAGE: BSIDE < option > < filenames - see below >\n\n"); printf("Option Description\n"); printf("~~~~~~ ~~~~~~~~~~~\n"); printf(" -A Add a file into image, need to specify files as follows\n"); printf(" BSIDE -A < BMP file > < plaintext file > < result BMP file > [password]\n\n"); printf(" -X eXtract file(s) from image, need to specify files as follows\n"); printf(" BSIDE -X < BMP file > [file to extract] [password if needed]\n\n"); printf(" -C Calculate data storage statistics of a bitmap\n"); printf(" BSIDE -C < BMP file >\n\n"); printf(" -L List files stored within a bitmap\n"); printf(" BSIDE -L < BMP file >\n\n"); printf("Please note that wildcards are NOT currently supported\n\n"); printf("BlindSide is (c) John Collomosse 2000, All Rights Reserved\nComments/suggestions to ma7jpc@bath.ac.uk, updates see www.blindside.co.uk\n"); exit(1); } /* Read Password off of command line */ for (i=0; i< 129; i++) password[i]='\0'; if ((argc==6 && mode==1) || (argc==5 && mode==2)) { isencrypted=TRUE; for (i=0; i< 129; i++) { password[i]=argv[6-mode][i]; if (argv[6-mode][i]=='\0') break; } password[129]='\0'; } /* Open all necessary files */ bitmap_handle=fopen(argv[2],"rb"); if (mode==1) plaintext_handle=fopen(argv[3],"rb"); if (bitmap_handle==NULL) { printf("FATAL: Could not open bitmap %s!\n",argv[2]); exit(2); } if (plaintext_handle==NULL && mode==1) { printf("FATAL: Could not open plaintext %s!\n",argv[3]); exit(3); } /* Read source bitmap (this must be done for every command line variation) */ printf("? Reading bitmap file...."); BMPsource=(BITMAP*)calloc(1,sizeof(BITMAP)); BMPsource- >palette=(HEAP*)calloc(1,sizeof(HEAP)); BMPsource- >raster=(HEAP*)calloc(1,sizeof(HEAP)); initialiseHeap(BMPsource- >palette); initialiseHeap(BMPsource- >raster); if (!readBitmapFile(bitmap_handle,BMPsource)) { printf("ERROR\n\nFATAL: Out of memory, while reading bitmap file\n"); exit(4); } printf("OK\n"); /* Analyse Bitmap */ if (stricmp("BM",BMPsource- >signature) || BMPsource- >bitplanes!=1) { printf("FATAL: Not a valid bitmap file\n"); exit(5); } if (BMPsource- >compression!=0) { printf("FATAL: BlindSide cannot work with compressed bitmaps yet\n"); exit(6); } if (BMPsource- >bpp==1) { printf("FATAL: BlindSide can't work with monochrome images, as it is the colours\nwithin the image itself that are used to hide files within a bitmap.\nYou can only use bitmaps of greater colour depth (16c, 256c, 16Mc)\n"); exit(8); } if (BMPsource- >bpp!=4 && BMPsource- >bpp!=8 && BMPsource- >bpp!=24) { printf("FATAL: Can't work with a bitmap with %d bits per pixel\n\nTry saving the bitmap into a different bit depth in a graphics package.\n",BMPsource- >bpp); exit(8); } printf("? Image is %ld bytes (%ldx%ld), %d bits/pixel\n",BMPsource- >filesize,BMPsource- >x_size,BMPsource- >y_size,BMPsource- >bpp); /* Colour depth increase if need be */ if (BMPsource- >bpp< 24) { printf("? Increasing Colour Depth to 16M colours (24bpp)..."); BMPworking=(BITMAP*)calloc(1,sizeof(BITMAP)); if (BMPworking==NULL) { printf("\n\nFATAL: Out of memory while increasing colour depth"); exit(4); } BMPworking- >palette=(HEAP*)calloc(1,sizeof(HEAP)); BMPworking- >raster=(HEAP*)calloc(1,sizeof(HEAP)); if (BMPworking- >palette==NULL || BMPworking- >raster==NULL) { printf("\n\nFATAL: Out of memory while increasing colour depth"); exit(4); } if (!initialiseHeap(BMPworking- >palette) || !initialiseHeap(BMPworking- >raster)) { printf("\n\nFATAL: Out of memory while increasing colour depth"); exit(4); } /* Do the promote to 24bpp */ promoteTo24(BMPsource, BMPworking); /* cleanup source */ removeHeap(BMPsource- >palette); removeHeap(BMPsource- >raster); free(BMPsource); BMPsource=NULL; printf("OK\n"); } else { /* Source was fine - > already 24 bpp */ BMPworking=BMPsource; BMPsource=NULL; } /* Prepare BS dataspace */ printf("? Analysing Data Patterns...."); filespace=(HEAP*)calloc(1,sizeof(HEAP)); initialiseHeap(filespace); switch (decodeData(BMPworking,filespace)) { case 0: printf("OK\n"); break; case 1: removeHeap(filespace); initialiseHeap(filespace); if (mode==2 || mode==4) { printf("ERROR\n\nFATAL: File does not contain any BlindSide hidden data\n"); exit(4); } printf("OK\n"); if (mode==1) { printf("? Creating New Archive...."); if (formatDataspace(BMPworking, filespace)) printf("OK\n"); else { printf("ERROR\n\nFATAL: There isn't enough space in the bitmap to hold any Blindside hidden data\n"); exit(4); } } break; case 2: printf("\nFATAL: Out of memory while analysing bitmap\n"); exit(4); break; case 3: printf("\nFATAL: Bitmap was encoded using a higher version of BlindSide than this one\n"); exit(4); break; } /* At this point 'filespace' is always a working BS archive (although it may be one with no files contained) */ /* In case of Mode 3 it MAY NOT be the case that filespace is archive - it may be empty heap */ /* Decrypt if necessary */ if (filespace- >heaplen!=0) { if (*(filespace- >dataspace+1)=='E') { /* decrypt */ if (strcmp(password,"")==0) { /* get pword */ printf("\nData is encrypted, please enter password: "); scanf("%s",password); printf("\n"); } printf("? Decrypting Data...."); cryptoData(filespace,password); if (*(filespace- >dataspace+7)=='O' && *(filespace- >dataspace+8)=='K') { printf("OK\n"); isencrypted=TRUE; } else { printf("ERROR\n\nFATAL: Incorrect password\n"); exit(9); } } } /* Do whichever of the operations was requested */ switch (mode) { case 1: printf("\n"); for (i=strlen(argv[3]); i >0; i--) { if (argv[3][i]==PATH_SEP) break; } if (i!=0 || (argv[3][0]==PATH_SEP)) i++; addFileToArchive(filespace,plaintext_handle,&(argv[3][i])); printf("\n"); break; case 2: printf("\n"); if (argc >=3) extractFile(filespace,argv[3]); else extractFile(filespace,NULL); break; case 3: dumpFileStats(BMPworking, filespace); break; case 4: dumpFileDirectory(filespace); break; } /* Output to disk */ /* If we were in ADD mode, write the bitmap out (Xtract, Calc, and List are READ ONLY) */ if (mode==1) { /* close plaintext */ fclose(plaintext_handle); if (isencrypted==TRUE) { printf("? Encrypting Data...."); cryptoData(filespace,password); printf("OK\n"); } printf("? Encoding Data...."); hotspots=(LOOKUP*)calloc(1,sizeof(LOOKUP)); if (hotspots==NULL) { printf("ERROR\n\nOut of memory\n"); exit(4); } hotspots- >dataspace=(unsigned long int*)calloc(LOOKUP_INITLEN,sizeof(unsigned long int)); if (hotspots==NULL) { printf("ERROR\n\nOut of memory\n"); exit (4); } hotspots- >currentlen=LOOKUP_INITLEN; flattenBitmap(BMPworking,hotspots); encodeData(BMPworking,filespace,hotspots); printf("OK\n"); printf("? Writing result to %s....",argv[4]); outfile_handle=fopen(argv[4],"wb"); writeBitmapFile(outfile_handle, BMPworking); fclose(outfile_handle); printf("OK\n"); } /* Cleaup and exit */ printf("\nDone!\n"); removeHeap(filespace); free(filespace); removeHeap(BMPworking- >palette); free(BMPworking- >palette); removeHeap(BMPworking- >raster); free(BMPworking- >raster); free(BMPworking); return(0); } /***************************** HEAP MANAGEMENT ***********************/ int initialiseHeap(HEAP* heap) { heap- >dataspace=NULL; heap- >heapunits=0; heap- >nextchar=NULL; heap- >heaplen=0; heap- >dataspace=(unsigned char*)calloc(HEAP_INITUNITS,HEAP_UNITSIZE*sizeof(unsigned char)); if (heap- >dataspace==NULL) return FALSE; else { heap- >heapunits=HEAP_INITUNITS; heap- >nextchar=heap- >dataspace; return TRUE; } } int expandHeap(int newunits, HEAP* heap) { if (newunits >heap- >heapunits) { unsigned char* tmpheap; int i; tmpheap=heap- >dataspace; heap- >dataspace=(unsigned char*)calloc(newunits,HEAP_UNITSIZE*sizeof(unsigned char)); if (heap- >dataspace==NULL) { heap- >dataspace=tmpheap; return FALSE; } else { for (i=0; i< heap- >heapunits*HEAP_UNITSIZE; i++) heap- >dataspace[i]=tmpheap[i]; free(tmpheap); heap- >nextchar=(heap- >dataspace)+(heap- >heapunits*HEAP_UNITSIZE); heap- >heapunits=newunits; } } return TRUE; } void removeHeap(HEAP* heap) { if (heap- >dataspace!=NULL) { free (heap- >dataspace); heap- >heapunits=0; heap- >dataspace=NULL; heap- >nextchar=NULL; heap- >heaplen=0; } } int streamFileToHeap(FILE* infile, HEAP* heap) { unsigned char readchar; while (fscanf(infile,"%c",&readchar) >0) { if (!putToHeap(readchar,heap)) return FALSE; } return TRUE; } int putToHeap(unsigned char data, HEAP* heap) { unsigned long hopeful_pos=heap- >heaplen; unsigned long current_pos=(heap- >heapunits*HEAP_UNITSIZE); if (hopeful_pos >= current_pos) { int discrep=(int)hopeful_pos/HEAP_UNITSIZE; discrep++; if (!expandHeap(discrep, heap)) { return FALSE; } } *(heap- >nextchar)=data; heap- >heaplen++; heap- >nextchar++; return TRUE; } /*********************************************************************/ /******************************BMP HANDLER ROUTINES*******************/ int readBitmapFile(FILE* bmpfile, BITMAP* datazone) { unsigned char tmpchar; int dataread; int i; long offsetToRaster=0; /* Get Signature */ datazone- >signature=(char*)calloc(3,sizeof(char)); datazone- >signature[2]='\0'; dataread=fscanf(bmpfile,"%c",&tmpchar); if (dataread==1) datazone- >signature[0]=tmpchar; dataread=fscanf(bmpfile,"%c",&tmpchar); if (dataread==1) datazone- >signature[1]=tmpchar; /* Get Filesize */ datazone- >filesize=streamToLong(bmpfile); /* Skip reserved section */ for (i=0; i< 4; i++) dataread=fscanf(bmpfile,"%c",&tmpchar); /* Get Raster Offset */ offsetToRaster=streamToLong(bmpfile); /* Skip size of infoheader (always=40 anyway) */ for (i=0; i< 4; i++) dataread=fscanf(bmpfile,"%c",&tmpchar); /* Get Bitmap width (x_size) */ datazone- >x_size=streamToLong(bmpfile); /* Get Bitmap height (y_size) */ datazone- >y_size=streamToLong(bmpfile); /* Get number bitplanes */ dataread=fscanf(bmpfile,"%c",&tmpchar); if (dataread==1) datazone- >bitplanes=((unsigned int)tmpchar*1); dataread=fscanf(bmpfile,"%c",&tmpchar); if (dataread==1) datazone- >bitplanes+=((unsigned int)tmpchar*256); /* Get bits per pixel */ dataread=fscanf(bmpfile,"%c",&tmpchar); if (dataread==1) datazone- >bpp=((unsigned int)tmpchar*1); dataread=fscanf(bmpfile,"%c",&tmpchar); if (dataread==1) datazone- >bpp+=((unsigned int)tmpchar*256); /* Get Compression */ datazone- >compression=streamToLong(bmpfile); /* Get Compressed Image Size */ datazone- >compresssize=streamToLong(bmpfile); /* Get X pix per metre */ datazone- >x_pix_per_metre=streamToLong(bmpfile); /* Get Y pix per metre */ datazone- >y_pix_per_metre=streamToLong(bmpfile); /* Get Colours Used */ datazone- >colours=streamToLong(bmpfile); /* Get num important colours*/ datazone- >cols_important=streamToLong(bmpfile); if (datazone- >bpp< =8) { int numcolors=0; switch(datazone- >bpp) { case 1: numcolors=1; case 4: numcolors=16; case 8: numcolors=256; } for (i=0; i< numcolors; i++) { unsigned char readchar; /* RED */ if (fscanf(bmpfile,"%c",&readchar) >0) { if (!putToHeap(readchar,datazone- >palette)) return FALSE; } /* GREEN */ if (fscanf(bmpfile,"%c",&readchar) >0) { if (!putToHeap(readchar,datazone- >palette)) return FALSE; } /* BLUE */ if (fscanf(bmpfile,"%c",&readchar) >0) { if (!putToHeap(readchar,datazone- >palette)) return FALSE; } /* RESERVED */ if (fscanf(bmpfile,"%c",&readchar) >0) { if (!putToHeap(readchar,datazone- >palette)) return FALSE; } } } if (fseek(bmpfile,offsetToRaster,SEEK_SET)==0) if(!streamFileToHeap(bmpfile,datazone- >raster)) return FALSE; return TRUE;} void promoteTo24(BITMAP* source, BITMAP* dest) { unsigned long int ctr; unsigned char* tmpptr; unsigned char tmpchar[4]; unsigned char split16_1,split16_2; unsigned int EOLtargetpadding; /*in bits, for 24 target*/ unsigned long int xpos; int i; /* translate */ EOLtargetpadding=calcEOLpad(24,source- >x_size); xpos=0; tmpptr=source- >raster- >dataspace; for (ctr=0; ctr< source- >raster- >heaplen; ctr+=4) { switch(source- >bpp) { case 4: /* 16colour */ for (i=0; i< 4; i++) tmpchar[i]=*(tmpptr++); for (i=0; i< 4; i++) { split16_1=tmpchar[i]; split16_2=tmpchar[i]; split16_1=(split16_1&0xf0) > >4; split16_2=split16_2&0xf; if (xpos< source- >x_size) { process24gotpixel(split16_1,source- >palette- >dataspace,dest- >raster); xpos++; } if (xpos< source- >x_size) { process24gotpixel(split16_2,source- >palette- >dataspace,dest- >raster); xpos++; } } break; case 8: /* 256 cols */ for (i=0; i< 4; i++) { tmpchar[i]=*(tmpptr++); } for (i=0; i< 4; i++) { if (xpos< source- >x_size) { process24gotpixel(tmpchar[i],source- >palette- >dataspace,dest- >raster); xpos++; } } break; } if (xpos==source- >x_size) { /* align on source */ xpos=0; /* align on 24bit target */ for (i=0; i< EOLtargetpadding; i++) putToHeap('\0',dest- >raster); } } /* sort header info out */ dest- >signature=(char*)calloc(3,sizeof(char)); dest- >signature[0]='B'; dest- >signature[1]='M'; dest- >signature[2]='\0'; dest- >compression=0; dest- >x_pix_per_metre=source- >x_pix_per_metre; dest- >y_pix_per_metre=source- >y_pix_per_metre; dest- >bitplanes=1; dest- >bpp=24; dest- >x_size=source- >x_size; dest- >y_size=source- >y_size; dest- >colours=0; dest- >cols_important=0; /*file sizes */ dest- >compresssize=dest- >raster- >heaplen; dest- >filesize=54+(dest- >compresssize); } void process24gotpixel(unsigned char pal, unsigned char* palette, HEAP* raster) { /* got pixel palette entry# PAL */ palette+=(unsigned int)pal*4; putToHeap(*palette,raster); putToHeap(*(palette+1),raster); putToHeap(*(palette+2),raster); } void writeBitmapFile(FILE* outfile, BITMAP* source) { unsigned char* curspace=NULL; unsigned long int ctr; fprintf(outfile,"%c%c",source- >signature[0],source- >signature[1]); longToStream(outfile,source- >filesize); longToStream(outfile,0); longToStream(outfile,54); longToStream(outfile,40); longToStream(outfile,source- >x_size); longToStream(outfile,source- >y_size); fprintf(outfile,"%c%c%c%c",1,0,24,0); longToStream(outfile,source- >compression); longToStream(outfile,source- >compresssize); longToStream(outfile,source- >x_pix_per_metre); longToStream(outfile,source- >y_pix_per_metre); longToStream(outfile,0); longToStream(outfile,0); /* stream out dataspace */ ctr=0; curspace=(source- >raster- >dataspace); while (ctr< source- >raster- >heaplen) { fprintf(outfile,"%c",*(curspace++)); ctr++; } } /*********************************************************************/ /**************************** ENCODE FUNCTIONS ***********************/ unsigned long int resolveMaxEncode(BITMAP* bmp, LOOKUP* store) { /* return maximum possible storage space in BMP */ unsigned long storage; unsigned long offset,tmp; unsigned char thisR; unsigned char thisG; unsigned char thisB; unsigned char lookaheadR; unsigned char lookaheadG; unsigned char lookaheadB; int dom,lookaheaddom; int keepflag,keepflag2; unsigned long int hits; PIXEL getdata, corrupta; unsigned long int longtmp; unsigned long int longtmp2; unsigned long int *longptrtmp; offset=0; storage=0; /* running total */ while (offset< (bmp- >x_size*bmp- >y_size)) { getdata=getIndexedPixel(offset, bmp); thisR=getdata.red; thisG=getdata.green; thisB=getdata.blue; dom=biggest_of_3(thisR,thisG,thisB); keepflag=FALSE; /* If 1 col varies from others by at least 3 = > candidate */ if (dom==thisG && abs(thisG-thisR) >2 && abs(thisG-thisB) >2) keepflag=TRUE; if (dom==thisB && abs(thisB-thisR) >2 && abs(thisB-thisG) >2) keepflag=TRUE; if (dom==thisR && abs(thisR-thisB) >2 && abs(thisR-thisG) >2) keepflag=TRUE; if (keepflag==FALSE) { offset++; continue; } /* only one of the 3 cols=dom here, and that col is at least 3 points greater than the others */ /* see if dominant col continues on more pixels + that other cols dont challenge its dominance */ tmp=offset+1; hits=1; while (tmp< (bmp- >x_size*bmp- >y_size)) { getdata=getIndexedPixel(tmp, bmp); lookaheadR=getdata.red; lookaheadG=getdata.green; lookaheadB=getdata.blue; keepflag=FALSE; if (dom==thisG && lookaheadG==thisG) keepflag=TRUE; if (dom==thisR && lookaheadR==thisR) keepflag=TRUE; if (dom==thisB && lookaheadB==thisB) keepflag=TRUE; /* check dom is still dominant col by at least 4 */ lookaheaddom=biggest_of_3(lookaheadR,lookaheadG,lookaheadB); keepflag2=FALSE; if (thisR==dom && lookaheadR==lookaheaddom && abs(lookaheadR-lookaheadG) >2 && abs(lookaheadR-lookaheadB) >2) keepflag2=TRUE; if (thisG==dom && lookaheadG==lookaheaddom && abs(lookaheadG-lookaheadR) >2 && abs(lookaheadG-lookaheadB) >2) keepflag2=TRUE; if (thisB==dom && lookaheadB==lookaheaddom && abs(lookaheadB-lookaheadR) >2 && abs(lookaheadB-lookaheadG) >2) keepflag2=TRUE; if (keepflag==FALSE || keepflag2==FALSE) { /* make this byte (that broke chain) much different to running colour byte to prevent decode confusion */ if (thisR==dom && lookaheadR!=thisR && abs(thisR-lookaheadR)< 3) { /* chain was red, and broke with a minor difference*/ corrupta.blue=lookaheadB; corrupta.green=lookaheadG; if (lookaheadR >thisR) { if (lookaheadR< 253) corrupta.red=lookaheadR+3; else corrupta.red=lookaheadR-6; } else { if (lookaheadR< 253) corrupta.red=lookaheadR-3; else corrupta.red=lookaheadR-6; } setIndexedPixel(tmp,bmp,corrupta); } else if (thisG==dom && lookaheadG!=thisG && abs(thisG-lookaheadG)< 3) { /* chain was green and broke with minor diff*/ corrupta.red=lookaheadR; corrupta.blue=lookaheadB; if (lookaheadG >thisG) { if (lookaheadG< 253) corrupta.green=lookaheadG+3; else corrupta.green=lookaheadG-6; } else { if (lookaheadG< 253) corrupta.green=lookaheadG-3; else corrupta.green=lookaheadG-6; } setIndexedPixel(tmp,bmp,corrupta); } else if (thisB==dom && lookaheadB!=thisB && abs(thisB-lookaheadB)< 3) { /* chain was blue and broke with minor diff */ corrupta.green=lookaheadG; corrupta.red=lookaheadR; if (lookaheadB >thisB) { if (lookaheadB< 253) corrupta.blue=lookaheadB+3; else corrupta.blue=lookaheadB-6; } else { if (lookaheadB< 253) corrupta.blue=lookaheadB-3; else corrupta.blue=lookaheadB-6; } setIndexedPixel(tmp,bmp,corrupta); } break; } hits++; tmp++; } if (hits >2) { storage+=(hits-2); /* store in lookup table */ for (longtmp=offset+2; longtmp< offset+hits; longtmp++) { if (store- >curitem >=store- >currentlen) { longptrtmp=store- >dataspace; store- >dataspace=(unsigned long int*)calloc(2*store- >currentlen,sizeof(unsigned long int)); for (longtmp2=0; longtmp2< store- >currentlen; longtmp2++) { *(store- >dataspace+longtmp2)=*(longptrtmp+longtmp2); } free (longptrtmp); longptrtmp=NULL; store- >currentlen*=2; } *(store- >dataspace+(store- >curitem++))=longtmp; } offset+=hits; } else { offset++; } } return (unsigned long)(storage/8); } unsigned int biggest_of_3 (unsigned int a, unsigned int b, unsigned int c) { int pr1,pr2; if (a >b) pr1=a; else pr1=b; if (b >c) pr2=b; else pr2=c; if (pr1 >pr2) return pr1; else return pr2; } /*********************************************************************/ void longToStream(FILE* strm, unsigned long int x) { unsigned int bit4,bit3,bit2,bit1; bit4=(unsigned int)x/16777216; x=x-(unsigned long)((unsigned long)bit4*16777216); bit3=(unsigned int)x/65536; x=x-(unsigned long)((unsigned long)bit3*65536); bit2=(unsigned int)x/256; x=x-(unsigned long)((unsigned long)bit2*256); bit1=(unsigned int)x; fprintf(strm,"%c%c%c%c",bit1,bit2,bit3,bit4); } unsigned long int streamToLong(FILE* strm) { unsigned char dataread; unsigned char tmpchar; unsigned long int result=0; dataread=fscanf(strm,"%c",&tmpchar); if (dataread==1) result+=((unsigned long int)tmpchar*1); dataread=fscanf(strm,"%c",&tmpchar); if (dataread==1) result+=((unsigned long int)tmpchar*256); dataread=fscanf(strm,"%c",&tmpchar); if (dataread==1) result+=((unsigned long int)tmpchar*65536); dataread=fscanf(strm,"%c",&tmpchar); if (dataread==1) result+=((unsigned long int)tmpchar*16777216); return result; } unsigned int calcEOLpad(int bitlen, long linelen) { unsigned long int bitsperline; unsigned int padder; bitsperline=(unsigned long)bitlen*(unsigned long)linelen; padder=bitsperline%32; padder=32-padder; if (padder==32) padder=0; return (int)(padder/8); } PIXEL getIndexedPixel(unsigned long int idx, BITMAP* bmp) { unsigned long int offset; PIXEL result; unsigned int EOLpad; unsigned long int x; unsigned long int y; EOLpad=calcEOLpad(24,bmp- >x_size); x=idx%(bmp- >x_size); y=(idx-x)/(bmp- >x_size); y=(bmp- >y_size-1)-y; offset=(y*((bmp- >x_size*3)+EOLpad))+(x*3); result.blue=*(bmp- >raster- >dataspace+(offset++)); result.green=*(bmp- >raster- >dataspace+(offset++)); result.red=*(bmp- >raster- >dataspace+(offset)); return result; } void setIndexedPixel(unsigned long int idx, BITMAP* bmp, PIXEL pix) { unsigned long int offset; unsigned int EOLpad; unsigned long int x; unsigned long int y; EOLpad=calcEOLpad(24,bmp- >x_size); x=idx%(bmp- >x_size); y=(idx-x)/(bmp- >x_size); y=(bmp- >y_size-1)-y; offset=(y*((bmp- >x_size*3)+EOLpad))+(x*3); *(bmp- >raster- >dataspace+(offset++))=pix.blue; *(bmp- >raster- >dataspace+(offset++))=pix.green; *(bmp- >raster- >dataspace+(offset))=pix.red; } /****************DATA CODING **********************************/ void encodeData(BITMAP* dest, HEAP* data, LOOKUP* hotspots) { /* encodes data bit by bit into dest */ /* hotspots contains actual data storage locations */ unsigned long int i; unsigned long int heapitem; PIXEL blititem; int bitshift; unsigned char theBool; unsigned char dom; bitshift=0; heapitem=0; for (i=0; i< hotspots- >curitem; i++) { /* get next bit */ theBool=getNextHeapBit(heapitem,bitshift,data); bitshift++; if (bitshift==8) { bitshift=0; heapitem++; if (heapitem >data- >heaplen) break; } blititem=getIndexedPixel(*(hotspots- >dataspace+i),dest); dom=biggest_of_3(blititem.red, blititem.green, blititem.blue); if (dom==blititem.red) { if (theBool==1) { /* R */ if (dom==255) dom--; else dom++; blititem.red=dom; } } else if (dom==blititem.green) { if (theBool==1) { /* G */ if (dom==255) dom--; else dom++; blititem.green=dom; } } else { if (theBool==1) { /* B */ if (dom==255) dom--; else dom++; blititem.blue=dom; } } setIndexedPixel(*(hotspots- >dataspace+i),dest,blititem); } } unsigned char getNextHeapBit (unsigned long int item, int bit, HEAP* data) { unsigned char thisitem; int bitshift; bit=7-bit; /* reverse bit order */ thisitem=*(data- >dataspace+item); bitshift=pow(2,bit); thisitem=thisitem&bitshift; thisitem=thisitem > >bit; return thisitem; } int decodeData(BITMAP* src, HEAP* dest) { unsigned long offset,tmp; unsigned char thisR; unsigned char thisG; unsigned char thisB; unsigned char lookaheadR; unsigned char lookaheadG; unsigned char lookaheadB; int dom,lookaheaddom; int keepflag,keepflag2; unsigned long int hits; PIXEL getdata; PIXEL controlPixel, thisPixel; int theBool; unsigned long int longtmp; int currentBit; int bitshifts; offset=0; currentBit=0; bitshifts=0; while (offset< (src- >x_size*src- >y_size)) { getdata=getIndexedPixel(offset, src); thisR=getdata.red; thisG=getdata.green; thisB=getdata.blue; dom=biggest_of_3(thisR,thisG,thisB); keepflag=FALSE; /* If 1 col varies from others by at least 3 = > candidate */ if (dom==thisG && abs(thisG-thisR) >2 && abs(thisG-thisB) >2) keepflag=TRUE; if (dom==thisB && abs(thisB-thisR) >2 && abs(thisB-thisG) >2) keepflag=TRUE; if (dom==thisR && abs(thisR-thisB) >2 && abs(thisR-thisG) >2) keepflag=TRUE; if (keepflag==FALSE) { offset++; continue; } /* only one of the 3 cols=dom here, and that col is at least 3 points greater than the others */ /* see if dominant col continues on more pixels(+ or - 1) and that other cols dont challenge its dominance */ tmp=offset+1; hits=1; while (tmp< (src- >x_size*src- >y_size)) { getdata=getIndexedPixel(tmp, src); lookaheadR=getdata.red; lookaheadG=getdata.green; lookaheadB=getdata.blue; keepflag=FALSE; if (dom==thisG && abs(lookaheadG-thisG)< 2) keepflag=TRUE; if (dom==thisR && abs(lookaheadR-thisR)< 2) keepflag=TRUE; if (dom==thisB && abs(lookaheadB-thisB)< 2) keepflag=TRUE; /* check dom is still dominant col by at least 3 */ lookaheaddom=biggest_of_3(lookaheadR,lookaheadG,lookaheadB); keepflag2=FALSE; if (thisR==dom && lookaheadR==lookaheaddom && abs(lookaheadR-lookaheadG) >2 && abs(lookaheadR-lookaheadB) >2) keepflag2=TRUE; if (thisG==dom && lookaheadG==lookaheaddom && abs(lookaheadG-lookaheadR) >2 && abs(lookaheadG-lookaheadB) >2) keepflag2=TRUE; if (thisB==dom && lookaheadB==lookaheaddom && abs(lookaheadB-lookaheadR) >2 && abs(lookaheadB-lookaheadG) >2) keepflag2=TRUE; if (keepflag==FALSE || keepflag2==FALSE) break; hits++; tmp++; } if (hits >2) { /* store in lookup table */ for (longtmp=offset+2; longtmp< offset+hits; longtmp++) { controlPixel=getIndexedPixel(offset,src); thisPixel=getIndexedPixel(longtmp,src); dom=biggest_of_3(controlPixel.red, controlPixel.green, controlPixel.blue); if (dom==controlPixel.red) { if (thisPixel.red-dom==0) theBool=0; else theBool=1; } if (dom==controlPixel.green) { if (thisPixel.green-dom==0) theBool=0; else theBool=1; } if (dom==controlPixel.blue) { if (thisPixel.blue-dom==0) theBool=0; else theBool=1; } currentBit=currentBit< < 1; currentBit+=theBool; bitshifts++; if (bitshifts==8) { if (!putToHeap((char)currentBit,dest)) return 2; bitshifts=0; currentBit=0; } } offset+=hits; } else { offset++; } } /* decoded and in heap */ if (dest- >heaplen< 13) return 1; if (!(*(dest- >dataspace)=='B') || (*(dest- >dataspace+1)!='S' && *(dest- >dataspace+1)!='E')) return 1; if (*(dest- >dataspace+6) >THIS_PROTO_VER) return 3; /* set data length by truncation */ longtmp=0; longtmp+=((unsigned long int)(*(dest- >dataspace+2))*1); longtmp+=((unsigned long int)(*(dest- >dataspace+3))*256); longtmp+=((unsigned long int)(*(dest- >dataspace+4))*65536); longtmp+=((unsigned long int)(*(dest- >dataspace+5))*16777216); if (longtmp< =dest- >heaplen) dest- >heaplen=longtmp; else return 1; return 0; } /*************************** ENCRYPTION ROUTINES ***********************/ int hash_func(unsigned char* password) { /* This hash function steps thru the string, storing the */ /* lowest 4 bits, and shifting the running total left 4 bits */ /* The shift is a rotational one, e.g. the top nibble comes */ /* back in the bottom (LSB) nibble */ unsigned int hash_ttl=0; unsigned int ptr=0; char this_chr; while (password[ptr] != '\0') { /* Step through string one char at a time */ this_chr=password[ptr++]; /* Add lowest 4 bits of character */ hash_ttl=hash_ttl + (this_chr & 0x0f); /* Rotate hash total 4 bits to left (to MSB) */ hash_ttl = rotl4 (hash_ttl); } return (hash_ttl); } int rotl4(int inval) { /* Rotate 16bit integer INVAL left by 4 bits */ unsigned int result; unsigned int tmp; tmp = inval & 0xf000; /* MSB nibble of the 4 */ result = inval & 0xfff; /* 3 LSB nibbles of the 4 */ result < < = 4; /* Shift nibs 2-0 to 3-1 posns */ tmp > >= 12; /* Shift nib 3 to nib 0 posn */ result = result + tmp; /* Add nib 0 into 3-1 value */ return (result); } void cryptoData(HEAP* data, unsigned char* password) { unsigned long int i; unsigned int passhash; unsigned char pupper,plower; int alternhash=FALSE; passhash=hash_func(password); pupper=passhash&0xff00; plower=passhash&0xff; *(data- >dataspace+1)='E'; for (i=7; i< data- >heaplen; i++) { if (alternhash) { *(data- >dataspace+i)=xor(*(data- >dataspace+i),pupper); alternhash=FALSE; } else { *(data- >dataspace+i)=xor(*(data- >dataspace+i),plower); alternhash=TRUE; } } } unsigned char xor(unsigned char A, unsigned char B) { unsigned char t1,t2,t3; t1=A|B; t2=A&B; t3=t1-t2; return ~t3; } /************************************POW******************************/ int pow (int a, int b) { int result=1; int lp; for (lp=b; lp >0; lp--) { result=result*a; } return result; } /*******************************STRICMP*******************************/ int stricmp (const char* a, const char* b) { int i; char acmp,bcmp; if (strlen(a)!=strlen(b)) return 1; for (i=0; i< strlen(a); i++) { acmp=a[i]; bcmp=b[i]; if (acmp >='a' && acmp< ='z') acmp=acmp-0x20; if (bcmp >='a' && bcmp< ='z') bcmp=bcmp-0x20; if (acmp!=bcmp) return 1; } return 0; } /**********************ARCHIVE MANAGER*******************************/ int formatDataspace(BITMAP* BMPworking, HEAP* filespace) { LOOKUP* hotspots; unsigned long int bit1,bit2,bit3,bit4; unsigned long int maxencode,longtemp,i; putToHeap('B',filespace); putToHeap('S',filespace); putToHeap('\0',filespace); /* archive total length inc all hdr:- changed later LONG */ putToHeap('\0',filespace); putToHeap('\0',filespace); putToHeap('\0',filespace); putToHeap(THIS_PROTO_VER,filespace); putToHeap('O',filespace); putToHeap('K',filespace); putToHeap('\0',filespace); /* length of this file block inc filename hdr */ putToHeap('\0',filespace); putToHeap('\0',filespace); putToHeap('\0',filespace); hotspots=(LOOKUP*)calloc(1,sizeof(LOOKUP)); if (hotspots==NULL) { printf("ERROR\n\nOut of memory\n"); exit(4); } hotspots- >dataspace=(unsigned long int*)calloc(LOOKUP_INITLEN,sizeof(unsigned long int)); if (hotspots==NULL) { printf("ERROR\n\nOut of memory\n"); exit (4); } hotspots- >currentlen=LOOKUP_INITLEN; maxencode=resolveMaxEncode(BMPworking, hotspots); if (maxencode< 13) return FALSE; longtemp=maxencode; bit4=(unsigned int)longtemp/16777216; longtemp=longtemp-(unsigned long)((unsigned long)bit4*16777216); bit3=(unsigned int)longtemp/65536; longtemp=longtemp-(unsigned long)((unsigned long)bit3*65536); bit2=(unsigned int)longtemp/256; longtemp=longtemp-(unsigned long)((unsigned long)bit2*256); bit1=(unsigned int)longtemp; *(filespace- >dataspace+2)=bit1; *(filespace- >dataspace+3)=bit2; *(filespace- >dataspace+4)=bit3; *(filespace- >dataspace+5)=bit4; for (i=filespace- >heaplen; i< maxencode; i++) putToHeap('\0',filespace); /* encode blank data into bitmap */ encodeData(BMPworking,filespace,hotspots); return TRUE; } void dumpFileDirectory(HEAP* filespace) { unsigned long int offset,filelen; unsigned long int filectr,bytectr; int filenamelen; offset=9; filectr=0; bytectr=0; printf("\nFilename Size (bytes)\n-------- ------------\n"); for (;;) { filelen=0; filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*1); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*256); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*65536); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*16777216); if (filelen==0) break; filenamelen=strlen(filespace- >dataspace+offset)+1; printf("%-18s%lu\n",filespace- >dataspace+offset,filelen-filenamelen); offset=offset+filelen; filectr++; bytectr+=filelen-filenamelen; } if (filectr==0) printf("No files found in archive!\n"); else printf("\nTotal %lu byte(s), in %lu file(s)\n",bytectr,filectr); } void dumpFileStats(BITMAP* BMPworking, HEAP* filespace) { unsigned long int offset,filelen,totalsize; unsigned long int filectr,bytectr; unsigned long int maxencode; float perc_used; LOOKUP* hotspots; if (filespace- >heaplen==0) { hotspots=(LOOKUP*)calloc(1,sizeof(LOOKUP)); hotspots- >dataspace=(unsigned long int*)calloc(LOOKUP_INITLEN,sizeof(unsigned long int)); hotspots- >currentlen=LOOKUP_INITLEN; printf("? Calculating Data Capacity...."); maxencode=resolveMaxEncode(BMPworking, hotspots); free(hotspots); printf("OK\n\nThis file does not contain any BlindSide hidden data\n"); printf("The predicted storage capacity for this image is %lu byte(s) [%d Kb]\n",maxencode,(int)((float)maxencode/1024)); } else { totalsize=0; totalsize+=((unsigned long int)(*(filespace- >dataspace+2))*1); totalsize+=((unsigned long int)(*(filespace- >dataspace+3))*256); totalsize+=((unsigned long int)(*(filespace- >dataspace+4))*65536); totalsize+=((unsigned long int)(*(filespace- >dataspace+5))*16777216); offset=9; filectr=0; bytectr=0; for (;;) { filelen=0; filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*1); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*256); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*65536); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*16777216); bytectr+=filelen+4; if (filelen==0) break; offset=offset+filelen; filectr++; } bytectr+=9; perc_used=(float)100/totalsize; perc_used=perc_used*(float)(totalsize-bytectr); printf("\nArchive Found - Capacity %lu byte(s) [%lu Kb]\n\n",totalsize,totalsize/1024); printf("Total files - %lu, using %lu byte(s)\n",filectr,bytectr); printf("Freespace remaining: %lu byte(s) [%d%%]\n",totalsize-bytectr,(int)perc_used); } } void addFileToArchive(HEAP* filespace, FILE* handle, char* filename) { HEAP* filedump; int i; unsigned long int offset,filelen,freespace,ilong; unsigned long int lastfile,lastfile2; unsigned int bit4,bit3,bit2,bit1; offset=9; for (;;) { filelen=0; filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*1); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*256); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*65536); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*16777216); lastfile=offset-4; if (filelen==0) break; if (stricmp(filename,filespace- >dataspace+offset)==0) { printf("FATAL: File %s already exists in the archive\n",filename); exit(4); } offset=offset+filelen; } freespace=(filespace- >heaplen)-(lastfile+4); filedump=(HEAP*)calloc(1,sizeof(HEAP)); initialiseHeap(filedump); printf("Adding.... %s\n",filename); /* Write filename */ for (i=0; i< strlen(filename); i++) { putToHeap(filename[i],filedump); } putToHeap('\0',filedump); /* Write file */ if (!streamFileToHeap(handle,filedump)) { printf("\nFATAL: Out of memory, while reading file to encode\n"); exit(4); } if (filedump- >heaplen==(strlen(filename)+1)) { printf("\nFATAL: File to encode is empty! (zero length)\n"); exit(4); } /* Write next file length (end of chain) */ putToHeap('\0',filedump); putToHeap('\0',filedump); putToHeap('\0',filedump); putToHeap('\0',filedump); if (freespace< filedump- >heaplen) { printf("\nFATAL: There isn't enough room inside your image to encode that file\n\nYour data coding needs: %ld bytes\nFreespace inside bitmap: %ld bytes\n\n",filedump- >heaplen,freespace); printf("It is possible the image you are trying to encode into is too complex,\nor your file to encode is too large. Maybe try zipping it first?\n"); exit(7); } for (ilong=0; ilong< filedump- >heaplen; ilong++) { *(filespace- >dataspace+offset+ilong)=*(filedump- >dataspace+ilong); } lastfile2=filedump- >heaplen-4; bit4=(unsigned int)lastfile2/16777216; lastfile2=lastfile2-(unsigned long)((unsigned long)bit4*16777216); bit3=(unsigned int)lastfile2/65536; lastfile2=lastfile2-(unsigned long)((unsigned long)bit3*65536); bit2=(unsigned int)lastfile2/256; lastfile2=lastfile2-(unsigned long)((unsigned long)bit2*256); bit1=(unsigned int)lastfile2; *(filespace- >dataspace+lastfile)=bit1; *(filespace- >dataspace+lastfile+1)=bit2; *(filespace- >dataspace+lastfile+2)=bit3; *(filespace- >dataspace+lastfile+3)=bit4; removeHeap(filedump); free(filedump); } int extractFile(HEAP* filespace, char* criteria) { unsigned long int offset,filelen,filectr; unsigned long int extractctr,i; int alwaysoverwrite; int extractIt; int wasprompt; char tmpchar[129]; FILE* outfile; int filenamelen; offset=9; extractctr=0; filectr=0; alwaysoverwrite=FALSE; for (;;) { filelen=0; filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*1); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*256); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*65536); filelen+=((unsigned long int)(*(filespace- >dataspace+(offset++)))*16777216); if (filelen==0) break; filectr++; if (criteria==NULL || stricmp(filespace- >dataspace+offset,criteria)==0) { /* extract this file */ printf("Extracting.... %s",filespace- >dataspace+offset); extractIt=TRUE; if (checkExists(filespace- >dataspace+offset) && !alwaysoverwrite) { wasprompt=TRUE; printf(" - already exists, Overwrite? (y/N/a)"); fflush(stdin); fscanf(stdin,"%s",tmpchar); if (stricmp(tmpchar,"A")==0) { alwaysoverwrite=TRUE; printf("\n"); } else if (stricmp(tmpchar,"Y")==0) { printf("\n"); } else { printf("Skipping file--^\n"); extractIt=FALSE; } } else { printf("\n"); wasprompt=FALSE; } if (extractIt) { /* Do the actual extraction */ extractctr++; outfile=fopen(filespace- >dataspace+offset,"wb"); filenamelen=strlen(filespace- >dataspace+offset)+1; while ((*(filespace- >dataspace+offset))!='\0') { offset++; } offset++; for (i=0; i< filelen-filenamelen; i++) fprintf(outfile,"%c",*(filespace- >dataspace+offset+i)); fclose(outfile); offset=offset+(filelen-filenamelen); } else { offset+=filelen; } } else { offset+=filelen; } } if (filectr==0) { printf("This BlindSide archive is empty - no files to extract\n"); } else { if (!wasprompt) printf("\n"); if (extractctr==0) printf("No files in the archive matched your extract request!\n"); else printf("Extracted %lu file(s) successfully.\n",extractctr); } return extractctr; } int checkExists(char* filename) { FILE* tester; if ((tester=fopen(filename,"rb"))) { fclose(tester); return TRUE; } return FALSE; } void flattenBitmap(BITMAP* src, LOOKUP* store) { /* passes over data as if reading it - but just flattens all data to '0' bits and compiles a hotspots list */ unsigned long offset,tmp; unsigned char thisR; unsigned char thisG; unsigned char thisB; unsigned char lookaheadR; unsigned char lookaheadG; unsigned char lookaheadB; int dom,lookaheaddom; int keepflag,keepflag2; unsigned long int hits; PIXEL getdata; PIXEL controlPixel, thisPixel; unsigned long int longtmp; unsigned long int longtmp2; unsigned long int *longptrtmp; offset=0; while (offset< (src- >x_size*src- >y_size)) { getdata=getIndexedPixel(offset, src); thisR=getdata.red; thisG=getdata.green; thisB=getdata.blue; dom=biggest_of_3(thisR,thisG,thisB); keepflag=FALSE; /* If 1 col varies from others by at least 3 = > candidate */ if (dom==thisG && abs(thisG-thisR) >2 && abs(thisG-thisB) >2) keepflag=TRUE; if (dom==thisB && abs(thisB-thisR) >2 && abs(thisB-thisG) >2) keepflag=TRUE; if (dom==thisR && abs(thisR-thisB) >2 && abs(thisR-thisG) >2) keepflag=TRUE; if (keepflag==FALSE) { offset++; continue; } /* only one of the 3 cols=dom here, and that col is at least 3 points greater than the others */ /* see if dominant col continues on more pixels(+ or - 1) and that other cols dont challenge its dominance */ tmp=offset+1; hits=1; while (tmp< (src- >x_size*src- >y_size)) { getdata=getIndexedPixel(tmp, src); lookaheadR=getdata.red; lookaheadG=getdata.green; lookaheadB=getdata.blue; keepflag=FALSE; if (dom==thisG && abs(lookaheadG-thisG)< 2) keepflag=TRUE; if (dom==thisR && abs(lookaheadR-thisR)< 2) keepflag=TRUE; if (dom==thisB && abs(lookaheadB-thisB)< 2) keepflag=TRUE; /* check dom is still dominant col by at least 3 */ lookaheaddom=biggest_of_3(lookaheadR,lookaheadG,lookaheadB); keepflag2=FALSE; if (thisR==dom && lookaheadR==lookaheaddom && abs(lookaheadR-lookaheadG) >2 && abs(lookaheadR-lookaheadB) >2) keepflag2=TRUE; if (thisG==dom && lookaheadG==lookaheaddom && abs(lookaheadG-lookaheadR) >2 && abs(lookaheadG-lookaheadB) >2) keepflag2=TRUE; if (thisB==dom && lookaheadB==lookaheaddom && abs(lookaheadB-lookaheadR) >2 && abs(lookaheadB-lookaheadG) >2) keepflag2=TRUE; if (keepflag==FALSE || keepflag2==FALSE) break; hits++; tmp++; } if (hits >2) { for (longtmp=offset+2; longtmp< offset+hits; longtmp++) { controlPixel=getIndexedPixel(offset,src); thisPixel=getIndexedPixel(longtmp,src); dom=biggest_of_3(controlPixel.red, controlPixel.green, controlPixel.blue); if (dom==controlPixel.red) { thisPixel.red=controlPixel.red; } if (dom==controlPixel.green) { thisPixel.green=controlPixel.green; } if (dom==controlPixel.blue) { thisPixel.blue=controlPixel.blue; } setIndexedPixel(longtmp,src,thisPixel); /* store in lookup table */ if (store- >curitem >=store- >currentlen) { longptrtmp=store- >dataspace; store- >dataspace=(unsigned long int*)calloc(2*store- >currentlen,sizeof(unsigned long int)); for (longtmp2=0; longtmp2< store- >currentlen; longtmp2++) { *(store- >dataspace+longtmp2)=*(longptrtmp+longtmp2); } free (longptrtmp); longptrtmp=NULL; store- >currentlen*=2; } *(store- >dataspace+(store- >curitem++))=longtmp; } offset+=hits; } else { offset++; } } } 正文完 附件: 在BMP中隐藏信息-Win32下的可执行文件 bs_win32.zip
IT热词搜索 来源:360新闻
相关文章

相关软件:

腾讯QQ2012
大小:52.93 MB 授权:免费
腾讯QQ2012
立即下载
腾讯QQ2013
大小:49.32 MB 授权:免费
腾讯QQ2013
立即下载