www.pudn.com > Direct3D-3ds_loader-render.rar > Image.cpp
// Image.cpp: implementation of the Image class. // ////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include#include "Image.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// Image::Image() { planes=0; sizeX=0; sizeY=0; data=NULL; isBGR=0; } Image::~Image() { if(data!=NULL)delete [] data; } Image::Image(const Image &in) { planes=0; sizeX=0; sizeY=0; data=NULL; isBGR=0; Set( in); } int Image::Load(char *filename) { char p[5]; int ret = 0; char* pdest = strrchr( filename, '.' ); // find '.' if( pdest[0]!=NULL)pdest++; strncpy( p, pdest, 4); strlwr(p); // Convert a string to lowercase if( !strcmp(p,"bmp")) ret = LoadBMP( filename); else if( !strcmp(p,"jpg")) ret = LoadJPG( filename); else if( !strcmp(p,"jpeg")) ret = LoadJPG( filename); else if( !strcmp(p,"tga")) ret = LoadTGA( filename); if(ret) return 1; MessageBox(NULL, filename, "Nenájdený súbor", MB_OK ); return 0; } void Image::Set(const Image &in) { if(in.planes<0 || in.planes>4)return; if(in.sizeX<1 || in.sizeY<1) return; if(in.data==NULL)return; planes = in.planes; sizeX = in.sizeX; sizeY = in.sizeY; isBGR = in.isBGR; if(data!=NULL) delete [] data; data = new unsigned char[sizeX*sizeY*planes]; if(data==NULL)return; memcpy( data, in.data, sizeX*sizeY*planes); } int Image::SaveBMP(char *filename) { BITMAPFILEHEADER fileheader; BITMAPINFOHEADER infoheader; FILE *sub; if(data==NULL || planes !=3)return 0; int line_size = planes*sizeX; if(line_size%4)line_size += 4 - line_size%4; fileheader.bfType = 0x4D42; // Magic identifier - "BM" | identifikacia BMP suboru musi byt "BM" fileheader.bfSize = planes*sizeX*sizeY+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); // File size in bytes | velkos suboru v byte fileheader.bfReserved1 = 0; fileheader.bfReserved2 = 0; fileheader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); // Offset to image data, bytes | posun na zaciatok dat infoheader.biSize = sizeof(BITMAPINFOHEADER); // Header size in bytes | velkost hlavicky BITMAPINFOHEADER infoheader.biWidth = sizeX; // Width of image | sirka obrazka - sizeX infoheader.biHeight = sizeY; // Height of image | vyska obrazka - sizeY infoheader.biPlanes = 1; // Number of colour planes | pocet farebnych rovin musi bit 1 infoheader.biBitCount = 24; // Bits per pixel | bitov na pixel moze bit 1,4,8,24 infoheader.biCompression = 0; // Compression type | typ compresie , 0 - bez kompresie infoheader.biSizeImage = line_size*infoheader.biHeight ; // Image size in bytes | velkost obrazka v byte infoheader.biXPelsPerMeter = 0; // Pixels per meter X | pixelov na meter v smere x infoheader.biYPelsPerMeter = 0; // Pixels per meter Y | pixelov na meter v smere y infoheader.biClrUsed = 0; // Number of colours | pocet farieb v palete, ak 0 vsetky su pouzivane infoheader.biClrImportant = 0; // Important colours | dolezite farby v palete, ak 0 vsetky su dolezite sub = fopen(filename,"wb"); if(sub==NULL)return 0; fwrite( &fileheader, sizeof(BITMAPFILEHEADER), 1, sub); fwrite( &infoheader, sizeof(BITMAPINFOHEADER), 1, sub); unsigned char* p = new unsigned char[line_size*sizeY]; for(int y=0; y >= (7-x%8); index &= 0x01; data[(y*sizeX+x)*planes+0] = pal[index].rgbRed; data[(y*sizeX+x)*planes+1] = pal[index].rgbGreen; data[(y*sizeX+x)*planes+2] = pal[index].rgbBlue; } } if(pom_data!=NULL)delete []pom_data; return 1; } int Image::LoadBMP4bit(FILE *f, BITMAPFILEHEADER &fileheader, BITMAPINFOHEADER &infoheader) { RGBQUAD pal[16]; unsigned int countpal; if(infoheader.biBitCount!=4)return 0; if(infoheader.biClrUsed==0)countpal=4; else countpal=infoheader.biClrUsed; if(fread( pal, sizeof(RGBQUAD), countpal, f)!=countpal) { fclose(f); return 0; } unsigned char* pom_data; int line_size = infoheader.biWidth/2+infoheader.biWidth%2; if(line_size%4)line_size += 4 - line_size%4; pom_data = new unsigned char[line_size*infoheader.biHeight]; if(pom_data==NULL){ fclose(f); return 0; } if(!fread( pom_data, line_size*infoheader.biHeight, 1, f)) { fclose(f); delete [] pom_data; return 0; } fclose(f); sizeX=infoheader.biWidth; sizeY=infoheader.biHeight; planes=3; isBGR=0; if(data!=NULL)delete [] data; data = new unsigned char[planes*sizeX*sizeY]; if(data==NULL){ delete [] pom_data; return 0; } for(int y=0; y >4; data[(y*sizeX+x)*planes+0] = pal[index].rgbRed; data[(y*sizeX+x)*planes+1] = pal[index].rgbGreen; data[(y*sizeX+x)*planes+2] = pal[index].rgbBlue; } } if(pom_data!=NULL)delete []pom_data; return 1; } int Image::LoadBMP8bit(FILE *f, BITMAPFILEHEADER &fileheader, BITMAPINFOHEADER &infoheader) { RGBQUAD pal[256]; unsigned int countpal; if(infoheader.biBitCount!=8)return 0; if(infoheader.biClrUsed==0)countpal=256; else countpal=infoheader.biClrUsed; if(fread( pal, sizeof(RGBQUAD), countpal, f)!=countpal) { fclose(f); return 0; } unsigned char* pom_data; int line_size = infoheader.biWidth; if(line_size%4)line_size += 4 - line_size%4; pom_data = new unsigned char[line_size*infoheader.biHeight]; if(pom_data==NULL){ fclose(f); return 0; } if(!fread( pom_data, line_size*infoheader.biHeight, 1, f)) { fclose(f); delete [] pom_data; return 0; } fclose(f); sizeX=infoheader.biWidth; sizeY=infoheader.biHeight; planes=3; isBGR=0; if(data!=NULL)delete [] data; data = new unsigned char[planes*sizeX*sizeY]; if(data==NULL){ delete [] pom_data; return 0; } for(int y=0; y > 3 for more speed). // Next, we calculate the stride and allocate enough memory for the pixels. channels = bits / 8; stride = channels * width; data = new unsigned char[stride * height]; // Load in all the pixel data line by line for(int y = 0; y < height; y++) { // Store a pointer to the current line of pixels unsigned char *pLine = &(data[stride * y]); // Read in the current line of pixels fread(pLine, stride, 1, pFile); } isBGR=1; } // Check if the image is a 16 bit image (RGB stored in 1 unsigned short) else if(bits == 16) { unsigned short pixels = 0; int r=0, g=0, b=0; // Since we convert 16-bit images to 24 bit, we hardcode the channels to 3. // We then calculate the stride and allocate memory for the pixels. channels = 3; stride = channels * width; data = new unsigned char[stride * height]; // Load in all the pixel data pixel by pixel for(int j = 0; j < width*height; j++) { // Read in the current pixel fread(&pixels, sizeof(unsigned short), 1, pFile); // To convert a 16-bit pixel into an R, G, B, we need to // do some masking and such to isolate each color value. // 0x1f = 11111 in binary, so since 5 bits are reserved in // each unsigned short for the R, G and B, we bit shift and mask // to find each value. We then bit shift up by 3 to get the full color. b = (pixels & 0x1f) << 3; g = ((pixels >> 5) & 0x1f) << 3; r = ((pixels >> 10) & 0x1f) << 3; // This essentially assigns the color to our array and swaps the // B and R values at the same time. data[j * 3 + 0] = r; data[j * 3 + 1] = g; data[j * 3 + 2] = b; } } else return 0; } // Else, it must be Run-Length Encoded (RLE) else { int j=0; byte rleID = 0; int colorsRead = 0; channels = bits / 8; stride = channels * width; data = new unsigned char[stride * height]; byte *pColors = new byte [channels]; while(j < width*height) { fread(&rleID, sizeof(byte), 1, pFile); if(rleID < 128) { rleID++; while(rleID) { fread(pColors, sizeof(byte) * channels, 1, pFile); data[colorsRead + 0] = pColors[2]; data[colorsRead + 1] = pColors[1]; data[colorsRead + 2] = pColors[0]; if(bits == 32)data[colorsRead + 3] = pColors[3]; j++; rleID--; colorsRead += channels; } } else { rleID -= 127; fread(pColors, sizeof(byte) * channels, 1, pFile); while(rleID) { data[colorsRead + 0] = pColors[2]; data[colorsRead + 1] = pColors[1]; data[colorsRead + 2] = pColors[0]; if(bits == 32)data[colorsRead + 3] = pColors[3]; j++; rleID--; colorsRead += channels; } } } } fclose(pFile); planes = channels; sizeX = width; sizeY = height; Flip(); return 1; } void Image::BGRtoRGB() { if(!isBGR || planes<3 || data==NULL)return; for(int y=0; y >1; data[(y*sizeX+x)*planes+1] = data[(y*sizeX+x)*planes+1]>>1; data[(y*sizeX+x)*planes+2] = data[(y*sizeX+x)*planes+2]>>1; } } } void Image::invShift() // invertovana a potom jas*0.5 { if(data==NULL)return; for(int y=0; y >1; data[(y*sizeX+x)*planes+1] = (255-data[(y*sizeX+x)*planes+1])>>1; data[(y*sizeX+x)*planes+2] = (255-data[(y*sizeX+x)*planes+2])>>1; } } } int Image::resize(int newx, int newy) { unsigned char *old_data = data; int old_sizeX = sizeX; int old_sizeY = sizeY; float *d; sizeX = newx; sizeY = newy; data = new unsigned char[sizeX*sizeY*planes]; if(data==NULL) { data = old_data; sizeX = old_sizeX; sizeY = old_sizeY; return 0; } d = new float[old_sizeX*old_sizeY*planes]; if(d==NULL) { delete [] data; data = old_data; sizeX = old_sizeX; sizeY = old_sizeY; return 0; } for(int j=0; j 2.0 yf = (float)fmod(yf,1.0); // zvysok po deleni 1 for(int x=0; x 2.0 xf = (float)fmod(xf,1.0); // zvysok po deleni 1 for(int c=0; c = old_sizeY-1 { iy = old_sizeY-1; a = (1.f-xf)*d[(iy*old_sizeX+ix)*planes+c]+xf*d[(iy*old_sizeX+ix+1)*planes+c]; } else if(iy = old_sizeX-1 && iy >=1; // /2 data = new unsigned char[planes*sizeX*sizeY]; if(data==NULL) { data = old_data; sizeX = old_sizeX; sizeY = old_sizeY; return 0; } for(int y=0; y >1; if(planes>1)data[(y*sizeX+x)*planes+1] = ((unsigned int)old_data[(y*old_sizeX+2*x)*planes+1]+(unsigned int)old_data[(y*old_sizeX+2*x+1)*planes+1])>>1; if(planes>2)data[(y*sizeX+x)*planes+2] = ((unsigned int)old_data[(y*old_sizeX+2*x)*planes+2]+(unsigned int)old_data[(y*old_sizeX+2*x+1)*planes+2])>>1; if(planes>3)data[(y*sizeX+x)*planes+3] = ((unsigned int)old_data[(y*old_sizeX+2*x)*planes+3]+(unsigned int)old_data[(y*old_sizeX+2*x+1)*planes+3])>>1; } } delete [] old_data; return 1; } int Image::resizeToHalfY() { unsigned char *old_data = data; int old_sizeX = sizeX; int old_sizeY = sizeY;; if(sizeY<=1)return 0; sizeY >>=1; // /2 data = new unsigned char[planes*sizeX*sizeY]; if(data==NULL) { data = old_data; sizeX = old_sizeX; sizeY = old_sizeY; return 0; } for(int y=0; y >1; if(planes>1)data[(y*sizeX+x)*planes+1] = ((unsigned int)old_data[(2*y*old_sizeX+x)*planes+1]+(unsigned int)old_data[((2*y+1)*old_sizeX+x)*planes+1])>>1; if(planes>2)data[(y*sizeX+x)*planes+2] = ((unsigned int)old_data[(2*y*old_sizeX+x)*planes+2]+(unsigned int)old_data[((2*y+1)*old_sizeX+x)*planes+2])>>1; if(planes>3)data[(y*sizeX+x)*planes+3] = ((unsigned int)old_data[(2*y*old_sizeX+x)*planes+3]+(unsigned int)old_data[((2*y+1)*old_sizeX+x)*planes+3])>>1; } } delete [] old_data; return 1; } int Image::resizeToHalfXY() { unsigned char *old_data = data; int old_sizeX = sizeX; int old_sizeY = sizeY; if(sizeX<=1 && sizeY<=1)return 0; sizeX >>=1; // /2 sizeY >>=1; // /2 data = new unsigned char[planes*sizeX*sizeY]; if(data==NULL) { data = old_data; sizeX = old_sizeX; sizeY = old_sizeY; return 0; } for(int y=0; y >2; if(planes>1)data[(y*sizeX+x)*planes+1] = ( (unsigned int)old_data[(2*y*old_sizeX+2*x)*planes+1]+ (unsigned int)old_data[((2*y+1)*old_sizeX+2*x)*planes+1]+ (unsigned int)old_data[(2*y*old_sizeX+2*x+1)*planes+1]+ (unsigned int)old_data[((2*y+1)*old_sizeX+2*x+1)*planes+1])>>2; if(planes>2)data[(y*sizeX+x)*planes+2] = ( (unsigned int)old_data[(2*y*old_sizeX+2*x)*planes+2]+ (unsigned int)old_data[((2*y+1)*old_sizeX+2*x)*planes+2]+ (unsigned int)old_data[(2*y*old_sizeX+2*x+1)*planes+2]+ (unsigned int)old_data[((2*y+1)*old_sizeX+2*x+1)*planes+2])>>2; if(planes>3)data[(y*sizeX+x)*planes+3] = ( (unsigned int)old_data[(2*y*old_sizeX+2*x)*planes+3]+ (unsigned int)old_data[((2*y+1)*old_sizeX+2*x)*planes+3]+ (unsigned int)old_data[(2*y*old_sizeX+2*x+1)*planes+3]+ (unsigned int)old_data[((2*y+1)*old_sizeX+2*x+1)*planes+3])>>2; } } delete [] old_data; return 1; } void Image::Flip() // up - down { unsigned char *old = data; if(data==NULL)return; data = new unsigned char[planes*sizeX*sizeY]; if(data==NULL) { data = old; return; } for(int y=0; y =sizeX)x=sizeX-1; else if(x<0)x=0; // clamp if(y>=sizeY)y=sizeY-1; else if(y<0)y=0; // clamp return data[(sizeX*y+x)*planes+plane]; } float Image::evaluateMask( int x, int y, int plane, \ float m11, float m12, float m13, \ float m21, float m22, float m23, \ float m31, float m32, float m33 ) { float r; r = m11*getSavePoint( x-1, y-1, plane); r += m12*getSavePoint( x , y-1, plane); r += m13*getSavePoint( x+1, y-1, plane); r += m21*getSavePoint( x-1, y , plane); r += m22*getSavePoint( x , y , plane); r += m23*getSavePoint( x+1, y , plane); r += m31*getSavePoint( x-1, y+1, plane); r += m32*getSavePoint( x , y+1, plane); r += m33*getSavePoint( x+1, y+1, plane); return r/255.f; } void Image::Filter( int maska, int plane, float strong) { if(data==NULL)return; unsigned char *new_data = new unsigned char[sizeX*sizeY*3]; if(new_data==NULL)return; if(plane>=planes)plane = planes-1; float dx,dy; // dx derivacia vysky (farby) v smere x, dy derivacia v smere y for(int x=0; x