int main(int argc, char **argv) 
{
	/* used to read sizes*/
	BMPdata bmpData = {0};
	unsigned int bytesread = 0;
	
	int j=0;

	printf("Starting monochrome bitmap analyzer...\r\n");
	
	if ( argc < 2) 
    {
        printf( "No arguments given! Please provide bmp file name\r\n");
        return 0;
    }
    
    printf("Opening %s\r\n", argv[1]);
    
    FILE* bmp = fopen(argv[1],"r");
    
    if(bmp==0)
    {
		printf("Could not open file!\r\n");
		return 0;
	}
	
	/* seek over BM */
	FSEEK_ERROR(bmp, 2, "File does not start with BM");
	
	FREAD_ERROR((void*)&bmpData.filesize,sizeof(unsigned int),1,bmp,"File does not have size");

	/* seek over app specific */
	FSEEK_ERROR(bmp, 4, "No app specific bytes");
	
	FREAD_ERROR((void*)&bmpData.offset,sizeof(unsigned int),1,bmp,"File does not have pixel offset");
	
	FSEEK_ERROR(bmp, 4, "No app dib header");
	
	FREAD_ERROR((void*)&bmpData.width,sizeof(int),1,bmp,"File does not have width");
	FREAD_ERROR((void*)&bmpData.height,sizeof(int),1,bmp,"File does not have height");
	FREAD_ERROR((void*)&bmpData.colorplane,sizeof(short),1,bmp,"File does not have colorplane");
	FREAD_ERROR((void*)&bmpData.bitsPerPixel,sizeof(short),1,bmp,"File does not have bits per pixel");
	FREAD_ERROR((void*)&bmpData.compression,sizeof(unsigned int),1,bmp,"File does not have compression field");
	FREAD_ERROR((void*)&bmpData.pixelSize,sizeof(unsigned int),1,bmp,"File does not have pixelsize");
	FREAD_ERROR((void*)&bmpData.dpihor,sizeof(unsigned int),1,bmp,"File does not have dpi hor");
	FREAD_ERROR((void*)&bmpData.dpiver,sizeof(unsigned int),1,bmp,"File does not have dpi ver");
	FREAD_ERROR((void*)&bmpData.colorsInPallete,sizeof(unsigned int),1,bmp,"File does not have # colours in pallete");
	FREAD_ERROR((void*)&bmpData.ImportantColors,sizeof(unsigned int),1,bmp,"File does not have important colours");

	printf("Filesize: %d bytes \r\n", bmpData.filesize); 
	printf("Pixeldata starts at: %d %X\r\n", bmpData.offset, bmpData.offset);
	printf("Width: %d\r\n", bmpData.width);
	printf("Height: %d\r\n", bmpData.height); 
	printf("Colorplane: %d\r\n", bmpData.colorplane); 
	printf("Bits Per Pixel: %d\r\n", bmpData.bitsPerPixel); 
	printf("Compression: %d\r\n", bmpData.compression); 
	printf("Pixel size: %d bytes %X\r\n", bmpData.pixelSize, bmpData.pixelSize); 
	printf("DPI horizontal: %u %X\r\n", bmpData.dpihor,bmpData.dpihor); 
	printf("DPI vertical: %u %X\r\n", bmpData.dpiver,bmpData.dpiver);
	printf("Number of colors: %d\r\n", bmpData.colorsInPallete);
	printf("Important colors: %d\r\n", bmpData.ImportantColors);
	
	printf("Header Bytes Read: %d\r\n", bytesread);
	
	if(bmpData.bitsPerPixel != 1)
	{
		printf("WARNING: Image is not a monochrome image! Will try to continue...\r\n");
	}
	
	if(bmpData.compression != 0)
	{
		printf("WARNING: Image has compression! Will try to continue...\r\n");
	}
	
	if(bytesread<bmpData.offset)
	{
		printf("Seeking %d bytes to pixeldata...\r\n",(bmpData.offset-bytesread));
		FSEEK_ERROR(bmp, (bmpData.offset-bytesread), "No pixeldata found");
	}
	else if(bytesread>bmpData.offset)
	{
		printf("WARNING: Image header too small! Will try to continue...\r\n");
	}
	
	/* get number of bytes we need from each row */
	int widthPixBytes = bmpData.width/8 + ((bmpData.width%8)?1:0);
	printf("Each row has %d bytes of pixeldata\r\n", widthPixBytes);
	
	/* get number of bytes for each row with padding */
	int totalWidth = widthPixBytes + ((widthPixBytes%4)?(4-(widthPixBytes%4)):0);
	printf("Each row with padding is %d bytes\r\n", totalWidth);
	
	/* since bmp is upside down malloc memory to fill array upside down */
	char* pixelBuff = malloc(widthPixBytes*bmpData.height);
	
	if(pixelBuff == NULL)
	{
		printf("Error: Could not allocate memory for pixel buffer!");
		return 0;
	}
	
	/* address the pointer to the last row */
	char* rowPointer = pixelBuff+(widthPixBytes*(bmpData.height-1));
	
	int pixelByte;
	int columnoffset = 0;
	int pixelBytesRead = 0;
	
	while(((pixelByte = fgetc(bmp)) != EOF) && pixelBytesRead<(totalWidth*bmpData.height))
	{
		pixelBytesRead++;
		columnoffset++;
		
		if(columnoffset<=widthPixBytes)
		{
			rowPointer[columnoffset-1] = pixelByte;
		}
		
		if(columnoffset>=totalWidth)
		{
			/* move pointer to next row*/
			rowPointer -= (widthPixBytes);
			
			columnoffset=0;
		}
	}
	
	/* Draw the image on the screen and generate the output file */
	FILE* outputFile = NULL; 
	
	if ( argc < 3) 
    {
        printf( "No output arguments given! will not generate output file\r\n");
    }
    else
    {
		outputFile = fopen(argv[2],"w");
		
		if(outputFile==NULL)
		{
			printf("ERROR: Could not open output file for writing!\r\n");
		}
		else
		{
			fprintf(outputFile,"/* Image data for %s %dx%d */\r\n", argv[1], bmpData.width, bmpData.height);
			fprintf(outputFile,"/* Generated by MonochromeBMP2Array */\r\n");
			fprintf(outputFile,"/* Source code available at https://github.com/Krugaroo/MonochromeBMP2Array  */\r\n");
			fprintf(outputFile,"/*\r\n");
		}
	}
	
	unsigned char pixelByteDraw;
	columnoffset=0;
	pixelBytesRead=0;	
	
	/* Draw the image on screen and to the file */
	if(bmpData.width<200)
	{
		do 
		{
			pixelByteDraw = *(pixelBuff+pixelBytesRead);
		  
			if(columnoffset<widthPixBytes)
			{     
				for(j=1;j<=8;j++)
				{
					if(pixelByteDraw&(1<<(8-j)))
					{
						printf("*");
						
						if(outputFile!=NULL)
						{
							fprintf(outputFile,"*");
						}
					}
					else
					{
						printf(" ");
						
						if(outputFile!=NULL)
						{
							fprintf(outputFile," ");
						}
					}
				}
			}
			
			pixelBytesRead++;
			columnoffset++;
			
			if(columnoffset==widthPixBytes)
			{
				if(outputFile!=NULL)
				{
					fprintf(outputFile,"\r\n");
				}
				
				columnoffset=0;
				printf("\r\n");	
			}
		  
		} while (pixelBytesRead<widthPixBytes*bmpData.height);
		
	}
	else
	{
		printf("Image is wider than 200px and is therefore not drawn!\r\n");
		if(outputFile!=NULL)
		{
			fprintf(outputFile,"\r\nImage is wider than 200px and is therefore not drawn!\r\n");
		}
	}
	
    if(outputFile!=NULL)
	{
		fprintf(outputFile,"*/\r\n");
	}
    
	columnoffset=0;
	pixelBytesRead=0;	
	
	/* Generate the array and data to file */
	if(outputFile!=NULL)
	{
		fprintf(outputFile,"\r\n/* Image data */\r\n");
		fprintf(outputFile,"unsigned int ImgWidthBytes = %d;\r\n", widthPixBytes);
		fprintf(outputFile,"unsigned int ImgWidthPixels = %d;\r\n", bmpData.width);
		fprintf(outputFile,"unsigned int ImgHeightPixels = %d;\r\n", bmpData.height);
		fprintf(outputFile,"unsigned int ImgTotalBytes = %d;\r\n\r\n", widthPixBytes*bmpData.height);
		fprintf(outputFile,"const char ImgArray[] = {\r\n");
	}
	
	do 
	{
		pixelByteDraw = *(pixelBuff+pixelBytesRead);
      
		if(columnoffset<widthPixBytes)
		{
			if(outputFile!=NULL)
			{
        fprintf(outputFile,"0x%02X,", pixelByteDraw);
      }
		}
		
		pixelBytesRead++;
		columnoffset++;
		
		if(columnoffset==widthPixBytes)
		{
			if(outputFile!=NULL && pixelBytesRead<widthPixBytes*bmpData.height)
			{
				fprintf(outputFile,"\r\n");
			}
			
			columnoffset=0;	
		}
		
		printf("\rProgress: %3d %%", pixelBytesRead*100/(widthPixBytes*bmpData.height));
      
    } while (pixelBytesRead<widthPixBytes*bmpData.height);
    
    if(outputFile!=NULL)
	{
		fprintf(outputFile,"\r\n};\r\n\r\n");
	}

    /* Free the allocated buffer */
	free(pixelBuff);	
	
	printf("\r\nFile written to %s.\r\n", argv[2]);
	printf("All done\r\n");
	
	return 0;
}
Пример #2
0
int main(int argc, char **argv) {
    FILE *lfile=NULL, *infile ;
    int wantline, currline, furthest, c ;
    size_t maxlinelength=0, maxnlines ;
    long *linepos ;
    char *line=NULL ; /* getline automatically mallocs and reallocs it */
    
    while((c = getopt(argc, argv, "f:")) != -1) {
	switch(c) {
	case 'f':
	    lfile = fopen(optarg, "r") ;
	    break ;
	case '?':
	    usage() ;
	}
    }
    if(lfile == NULL) usage() ;

    maxnlines = 1e3 ;
    linepos = (long *) malloc(maxnlines * sizeof(long)) ;
    for(c = 0 ; c < maxnlines ; c++) linepos[c] = -9 ;
    infile = stdin ; // NB can't use fseek with a pipe! See FSEEK_ERROR above.
    currline = furthest = 0 ;

    while( fscanf(lfile, "%d", &wantline) == 1) {
	/* Each time this loop is entered we have a new wantline, and
	   the task is to find it and print it */
	
	wantline-- ;  // indexing from 1 in shell
	linepos[currline] = ftell(infile) ;

	/* First check whether we need to rewind to get to wantline */
	if(wantline < currline) {
	    if( fseek(infile, linepos[wantline] - linepos[currline], SEEK_CUR) != 0 )
		FSEEK_ERROR() ;
	    if( getline(&line, &maxlinelength, infile) < 0 )
	    	ERROR("Failed to read new line (reached end of file?)") ;
	    printf("%s", line) ;
	    currline = wantline ;
	    continue ;
	}
	
	/* We're either at wantline or it's ahead of us */
	if(furthest > currline) { /* If we've already been further than this point, 
				     than we can fast-forward. */
	    if(wantline <= furthest) {  /* we've been past it previously, but
					   subsequently did a rewind: fast-forward to it,
					   print it and skip to next wantline */
		if( fseek(infile, linepos[wantline] - linepos[currline], SEEK_CUR) != 0 )
		    FSEEK_ERROR() ;
		if( getline(&line, &maxlinelength, infile) < 0 )
		    ERROR("Failed to read new line (reached end of file?)") ;
		printf("%s", line) ;
		currline = wantline + 1 ;
		continue ;
	    }
	    /* Wantline is further than we've been before:
	       fast-forward to our furthest point, then start
	       advancing line-by-line  */
	    if( fseek(infile, linepos[furthest] - linepos[currline], SEEK_CUR) != 0 )
		FSEEK_ERROR() ;
	    currline = furthest ;
	}

	/* Now we're going beyond where we've been before. So advance
	   line-by-line, storing the positions of the new lines, until
	   we find wantline */
	while(wantline > currline) {
	    if( getline(&line, &maxlinelength, infile) < 0 )
		ERROR("Failed to read new line (reached end of file?)") ;
	    currline++ ;
	    if(currline > maxnlines) {
		maxnlines *= 2 ;
		linepos = realloc(linepos, maxnlines * sizeof(long)) ;
	    }
	    linepos[currline] = ftell(infile) ;
	}
	
	/* We're at wantline */
	assert(currline == wantline) ;
	if( getline(&line, &maxlinelength, infile) < 0)
	    ERROR("Failed to read next line") ;
	printf("%s", line) ;
	currline++ ;
	if(currline > maxnlines) {
	    maxnlines *= 2 ;
	    linepos = realloc(linepos, maxnlines * sizeof(long)) ;
	}
	furthest = MAX(furthest, currline) ;
    }
    
    fclose(infile) ;
    fclose(lfile) ;
    free(line) ;
    free(linepos) ;
    return 0 ;
}