/** * Stretches the image so that the resulting image has a new size. * * @param w the new width to stretch to * @param h the new height to stretch to */ void stretch(int w, int h, struct IMAGE* image) { struct IMAGE newimage; int x; int y; int matrixX; int matrixY; int matrixWidth; int matrixHeight; int blockWidth; int blockHeight; int blockWidthRest; int blockHeightRest; int fillIndexWidth; int fillIndexHeight; int fill; int xx; int yy; int sum; int sumR; int sumG; int sumB; int sumCount; int pixel; if (verbose >= VERBOSE_MORE) { printf("stretching %dx%d -> %dx%d\n", image->width, image->height, w, h); } // allocate new buffer's memory initImage(&newimage, w, h, image->bitdepth, image->color, WHITE); blockWidth = image->width / w; // (0 if enlarging, i.e. w > image->width) blockHeight = image->height / h; if (w <= image->width) { blockWidthRest = (image->width) % w; } else { // modulo-operator doesn't work as expected: (3680 % 7360)==3680 ! (not 7360 as expected) // shouldn't always be a % b = b if a < b ? blockWidthRest = w; } if (h <= image->height) { blockHeightRest = (image->height) % h; } else { blockHeightRest = h; } // for each new pixel, get a matrix of pixels from which the new pixel should be derived // (when enlarging, this matrix is always of size 1x1) matrixY = 0; fillIndexHeight = 0; for (y = 0; y < h; y++) { fillIndexWidth = 0; matrixX = 0; if ( ( (y * blockHeightRest) / h ) == fillIndexHeight ) { // next fill index? // (If our optimizer is cool, the above "* blockHeightRest / h" will disappear // when images are enlarged, because in that case blockHeightRest = h has been set before, // thus we're in a Kripke-branch where blockHeightRest and h are the same variable. // No idea if gcc's optimizer does this...) (See again below.) fillIndexHeight++; fill = 1; } else { fill = 0; } matrixHeight = blockHeight + fill; for (x = 0; x < w; x++) { if ( ( (x * blockWidthRest) / w ) == fillIndexWidth ) { // next fill index? fillIndexWidth++; fill = 1; } else { fill = 0; } matrixWidth = blockWidth + fill; // if enlarging, map corrdinates directly if (blockWidth == 0) { // enlarging matrixX = (x * image->width) / w; } if (blockHeight == 0) { // enlarging matrixY = (y * image->height) / h; } // calculate average pixel value in source matrix if ((matrixWidth == 1) && (matrixHeight == 1)) { // optimization: quick version pixel = getPixel(matrixX, matrixY, image); } else { sumCount = 0; if (!image->color) { sum = 0; for (yy = 0; yy < matrixHeight; yy++) { for (xx = 0; xx < matrixWidth; xx++) { sum += getPixelGrayscale(matrixX + xx, matrixY + yy, image); sumCount++; } } sum = sum / sumCount; pixel = pixelGrayscaleValue(sum); } else { // color sumR = 0; sumG = 0; sumB = 0; for (yy = 0; yy < matrixHeight; yy++) { for (xx = 0; xx < matrixWidth; xx++) { pixel = getPixel(matrixX + xx, matrixY + yy, image); sumR += (pixel >> 16) & 0xff; sumG += (pixel >> 8) & 0xff; sumB += pixel & 0xff; //sumR += getPixelComponent(matrixX + xx, matrixY + yy, RED, image); //sumG += getPixelComponent(matrixX + xx, matrixY + yy, GREEN, image); //sumB += getPixelComponent(matrixX + xx, matrixY + yy, BLUE, image); sumCount++; } } pixel = pixelValue( sumR/sumCount, sumG/sumCount, sumB/sumCount ); } } setPixel(pixel, x, y, &newimage); // pixel may have resulted in a gray value, which will be converted to 1-bit // when the file gets saved, if .pbm format requested. black-threshold will apply. if (blockWidth > 0) { // shrinking matrixX += matrixWidth; } } if (blockHeight > 0) { // shrinking matrixY += matrixHeight; } } replaceImage(image, &newimage); }
linked_list* connComponents(const image_t *imgGy,int32_t minNumPixels){ int32_t i,j; struct pixel seed; uint8_t T; uint8_t **dummy; int32_t Nset, ClassLabel; int32_t dummyClass; symbol_t *symbol, *symbol_tmp; linked_list *symbols_list; int32_t height, width; height = imgGy->height; width = imgGy->width; /* Set up segmented image structure */ dummy=(uint8_t **) multialloc (sizeof (uint8_t), 2, (int)height, (int)width); symbols_list = create_linked_list(); symbol_tmp = malloc(sizeof(symbol_t)); /********************** Segment Image ******************/ /* set threshold */ T=1; /* Initialize segmentation image */ for ( i = 0; i < height; i++ ){ for ( j = 0; j < width; j++ ) { dummy[i][j] = 0; } } dummyClass = -1; /* Start class labeling at 1 */ ClassLabel = 1; for ( i = 0; i < height; i++ ) for ( j = 0; j < width; j++ ) { /* If not yet classified */ if (dummy[i][j] == 0 && getPixel(imgGy,i,j) == 1) { seed.row=i; seed.col=j; /* using this only to find Nset; will also indicate tested regions */ ConnectedSet(seed, T, imgGy, width, height, &dummyClass, dummy, &Nset, symbol_tmp); /* If more than 100 pixels, classify set*/ if (Nset > minNumPixels) { symbol = malloc(sizeof(symbol_t)); symbol->top=(uint16_t)height; symbol->bottom=0; symbol->left=(uint16_t)width; symbol->right=0; ConnectedSet(seed, T, imgGy, width, height, &ClassLabel, dummy, &Nset, symbol); symbol->height = (uint16_t)(symbol->bottom - symbol->top + 1); symbol->width = (uint16_t)(symbol->right - symbol->left + 1); symbol->HtW = (uint16_t)(symbol->height/symbol->width); symbol->NumBlack = (uint16_t)(Nset); symbol->class_label = -1; push_bottom(symbols_list, symbol); ClassLabel = ClassLabel + 1; if (ClassLabel > 255) { printf("Error: More than 256 classes.\n"); printf("Need to increase minimum pixels per class.\n"); exit(1); } } } } ClassLabel = ClassLabel - 1; multifree(dummy, 2); free(symbol_tmp); return symbols_list; }
RGB RGBImageStudent::getPixel(int x, int y) const { //int throwError = 0, e = 1 / throwError; //TODO: no comment needed :) int i = x + (getWidth() * y); return getPixel(i); }
PNM* BinarizationGradient::transform() { int width = image->width(); int height = image->height(); PNM* newImage = new PNM(width, height, QImage::Format_Mono); if (image->format() == QImage::Format_Mono) { } else if (image->format() == QImage::Format_Indexed8) { int numerator = 0; int denominator = 0; for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { QRgb pixel = image->pixel(x,y); // Getting the pixel(x,y) value int l=qGray(pixel); QRgb pixel1 = getPixel(x+1,y, RepeatEdge); QRgb pixel2 = getPixel(x-1,y, RepeatEdge); int l1 = qGray(pixel1); int l2 = qGray(pixel2); int gx = l1-l2; pixel1 = getPixel(x,y+1, RepeatEdge); pixel2 = getPixel(x,y-1, RepeatEdge); l1 = qGray(pixel1); l2 = qGray(pixel2); int gy = l1-l2; int g=max(gx, gy); numerator+=(l*g); denominator+=g; } } int threshold=(numerator/denominator); for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { QRgb pixel = image->pixel(x,y); // Getting the pixel(x,y) value int l = qGray(pixel); newImage->setPixel(x,y, l < threshold ? Qt::color0 : Qt::color1); } } } else { //if (image->format() == QImage::Format_RGB32) int numerator = 0; int denominator = 0; for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { QRgb pixel = image->pixel(x,y); // Getting the pixel(x,y) value int ri = qRed(pixel); // Get the 0-255 value of the R channel int gi = qGreen(pixel); // Get the 0-255 value of the G channel int bi = qBlue(pixel); // Get the 0-255 value of the B channel int ti = (ri+gi+bi)/3; QRgb pixelx1 = getPixel(x+1,y, RepeatEdge); QRgb pixelx2 = getPixel(x-1,y, RepeatEdge); int rx1 = qRed(pixelx1); // Get the 0-255 value of the R channel int gx1 = qGreen(pixelx1); // Get the 0-255 value of the G channel int bx1 = qBlue(pixelx1); // Get the 0-255 value of the B channel int tx1 = (rx1+gx1+bx1)/3; int rx2 = qRed(pixelx2); // Get the 0-255 value of the R channel int gx2 = qGreen(pixelx2); // Get the 0-255 value of the G channel int bx2 = qBlue(pixelx2); // Get the 0-255 value of the B channel int tx2 = (rx2+gx2+bx2)/3; int gx = tx1-tx2; int pixely1 = getPixel(x,y+1, RepeatEdge); int pixely2 = getPixel(x,y-1, RepeatEdge); int ry1 = qRed(pixely1); // Get the 0-255 value of the R channel int gy1 = qGreen(pixely1); // Get the 0-255 value of the G channel int by1 = qBlue(pixely1); // Get the 0-255 value of the B channel int ty1 = (ry1+gy1+by1)/3; int ry2 = qRed(pixely2); // Get the 0-255 value of the R channel int gy2 = qGreen(pixely2); // Get the 0-255 value of the G channel int by2 = qBlue(pixely2); // Get the 0-255 value of the B channel int ty2 = (ry2+gy2+by2)/3; int gy = ty1-ty2; int g=max(gx, gy); numerator=numerator+(ti*g); denominator+=g; } } int threshold=(numerator/denominator); for (int x=0; x<width; x++) { for (int y=0; y<height; y++) { QRgb pixel = image->pixel(x,y); // Getting the pixel(x,y) value int r = qRed(pixel); // Get the 0-255 value of the R channel int g = qGreen(pixel); // Get the 0-255 value of the G channel int b = qBlue(pixel); // Get the 0-255 value of the B channel int t = (r+g+b)/3; newImage->setPixel(x,y, t < threshold ? Qt::color0 : Qt::color1); } } } return newImage; }
void ImageDecoder::MipMap::setPixel(int x, int y, float r, float g, float b, float a) { getPixel(y * width + x, r, g, b, a); }
/*! Get the view of the virtual camera. Be careful, the image I is modified. The projected image is not added as an overlay! \param I : The image used to store the result. \param cam : The parameters of the virtual camera. */ void vpImageSimulator::getImage(vpImage<vpRGBa> &I, const vpCameraParameters &cam) { if (cleanPrevImage) { for (unsigned int i = 0; i < I.getHeight(); i++) { for (unsigned int j = 0; j < I.getWidth(); j++) { I[i][j] = bgColor; } } } if(visible) { if(!needClipping) getRoi(I.getWidth(),I.getHeight(),cam,pt,rect); else getRoi(I.getWidth(),I.getHeight(),cam,ptClipped,rect); double top = rect.getTop(); double bottom = rect.getBottom(); double left = rect.getLeft(); double right= rect.getRight(); vpRGBa *bitmap = I.bitmap; unsigned int width = I.getWidth(); vpImagePoint ip; int nb_point_dessine = 0; for (unsigned int i = (unsigned int)top; i < (unsigned int)bottom; i++) { for (unsigned int j = (unsigned int)left; j < (unsigned int)right; j++) { double x=0,y=0; ip.set_ij(i,j); vpPixelMeterConversion::convertPoint(cam,ip, x,y); ip.set_ij(y,x); if (colorI == GRAY_SCALED) { unsigned char Ipixelplan; if(getPixel(ip,Ipixelplan)) { vpRGBa pixelcolor; pixelcolor.R = Ipixelplan; pixelcolor.G = Ipixelplan; pixelcolor.B = Ipixelplan; *(bitmap+i*width+j) = pixelcolor; nb_point_dessine++; } } else if (colorI == COLORED) { vpRGBa Ipixelplan; if(getPixel(ip,Ipixelplan)) { *(bitmap+i*width+j) = Ipixelplan; nb_point_dessine++; } } } } } }
uint8_t AVDMVideoSmooth::getFrameNumberNoAlloc(uint32_t frame, uint32_t *len, ADMImage *data, uint32_t *flags) { uint8_t *dst,*dstu,*dstv,*src,*srcu,*srcv; int16_t l,u=0,v=0; int16_t nb; int16_t fl,fu,fv; int16_t ldelta,udelta,vdelta; int16_t threshold=10,su=0,sv=0; if(frame>=_info.nb_frames) return 0; ADM_assert(_uncompressed); // read uncompressed frame if(!_in->getFrameNumberNoAlloc(frame, len,_uncompressed,flags)) return 0; src=YPLANE(_uncompressed); srcu=UPLANE(_uncompressed);; srcv=VPLANE(_uncompressed);; dst=YPLANE(data); dstu=UPLANE(data); dstv=VPLANE(data); int16_t radius=_param->radius; for(int32_t y=0;y<(int32_t)(_info.height );y++) { for(int32_t x=0;x<(int32_t)(_info.width );x++) { // for each pixel we take the surrounding one // if threshold is not met l=getPixel(x,y,_uncompressed->data); if(!(x&1)) { u=getPixelU(x,y,srcu); v=getPixelU(x,y,srcv); } nb=0; fl=0;fu=0;fv=0; //------------------------ for(int16_t yy=-radius+1;yy<radius;yy++) { for(int16_t xx=-radius+1;xx<radius;xx++) { if( (xx*xx+yy*yy)<radius*radius) { ldelta =getPixel(x+xx,y+yy,_uncompressed->data)-l; udelta=getPixelU(x+xx,y+yy,srcu)-u; vdelta=getPixelU(x+xx,y+yy,srcv)-v; if((udelta*udelta<threshold*threshold)&& (vdelta*vdelta<threshold*threshold) && (ldelta*ldelta<threshold*threshold)) { nb++; fl=fl+ldelta+l; fu=fu+udelta+u; fv=fv+vdelta+v; } } } } //---------------------------------- // // average value fl=fl/nb; fu=fu/nb; fv=fv/nb; // now melt it // 50/50 /* fl=(fl+l)>>1; fu=(fu+u)>>1; fv=(fv+v)>>1;*/ *dst++=fl; if(y&1) if(x&1) { setPixelU( (su+fu)>>1,x,y,dstu); setPixelU( (sv+fv)>>1,x,y,dstv); } else { su=fu; sv=fv; } } // end for x
Pixel* Surface::getPixel(Point *pt) { return getPixel(pt->getX(), pt->getY()); }
/* Applies a threshold filter to a BMP file and writes the result to another. Takes care of opening and closing the output file. */ int applyThreshold(FILE* inFile, struct bmpFileHeader* fileHead, struct bmpInfoHeader* infoHead, char* outFileName, float threshold) { // check that threshold value is in range if (threshold < 0.0 || threshold > 1.0) { fprintf(stderr, "Threshold value not in range.\n"); return EXIT_FAILURE; } // open file for writing FILE *outFile = fopen(outFileName, "w+"); // check that file opened okay if (outFile == NULL) { fprintf(stderr, "Unable to open file: %s for writing.\n", outFileName); return EXIT_FAILURE; } // write the headers to the output file, checking for errors if (writeFileHeader(fileHead, outFile) != 0) { fprintf(stderr, "Unable to write file header.\n"); return EXIT_FAILURE; } if (writeInfoHeader(infoHead, outFile) != 0) { fprintf(stderr, "Unable to write info header.\n"); return EXIT_FAILURE; } // calculate amount of padding added to width int padding = (4 - (infoHead->width*3 % 4)) % 4; // to store pixel being worked on struct pixel* curPixel = NULL; // run through pixels, modifying and saving them to out file for (int i = 0; i < infoHead->height; i++) { for (int j = 0; j < infoHead->width; j++) { // get a pixel curPixel = getPixel(inFile); // make sure we actually got a pixel if (curPixel == NULL) { fprintf(stderr, "Unable to get pixel.\n"); return EXIT_FAILURE; } double maxPixelValue = pow(2, infoHead->colourDepth/3) - 1; // calculate individual intensity values for each colour double redIntensity = (curPixel->red)/maxPixelValue; double greenIntensity = (curPixel->green)/maxPixelValue; double blueIntensity = (curPixel->blue)/maxPixelValue; // determine if pixel above thresh, make it black/white accordingly if ((redIntensity + greenIntensity + blueIntensity)/3.0 > threshold) { const uint32_t white = 0xFFFFFF; // write pixel, checking for error if (fwrite(&white, 3, 1, outFile) != 1) { fprintf(stderr, "Unable to write white pixel to file.\n"); return EXIT_FAILURE; } } else { const uint32_t black = 0x000000; // write pixel, checking for error if(fwrite(&black, 3, 1, outFile) != 1) { fprintf(stderr, "Unable to write black pixel to file.\n"); return EXIT_FAILURE; } } } // move in-file on by padding amount fseek(inFile, padding, SEEK_CUR); // add padding to out-file for (int k = 0; k < padding; k++) { fputc(0x00, outFile); } } // free memory allocated to pixel storage free(curPixel); // close the output file, checking for error if (fclose(outFile) != 0) { fprintf(stderr, "Unable to close output file: %s.\n", outFileName); return EXIT_FAILURE; } // if program gets to here, everything is okay return EXIT_SUCCESS; }
int cropImage(FILE* inFile, struct bmpFileHeader* fileHead, struct bmpInfoHeader* infoHead, char* outFileName, int cropWidth, int cropHeight, int cropStart[]) { // check that cropping parameters make sense if (((cropWidth + cropStart[0]) > infoHead->width) || ((cropHeight + cropStart[1]) > infoHead->height)) { fprintf(stderr, "Cropping parameters incorrect.\n"); return EXIT_FAILURE; } // open file for writing FILE *outFile = fopen(outFileName, "w+"); // check that file opened okay if (outFile == NULL) { fprintf(stderr, "Unable to open file: %s for writing.\n", outFileName); return EXIT_FAILURE; } // store old width/height for use in loop LONG oldWidth = infoHead->width; LONG oldHeight = infoHead->height; // calculate padding used in old image int oldPadding = (4 - (oldWidth*sizeof(struct pixel) % 4)) % 4; // calculate padding to be used in new image int newPadding = (4 - (cropWidth*sizeof(struct pixel) % 4)) % 4; // new image size infoHead->imageSize = (cropWidth*sizeof(struct pixel) + newPadding)*cropHeight; // file size fileHead->fileSize = sizeof(struct bmpFileHeader) + sizeof(struct bmpInfoHeader) + infoHead->imageSize; // new dimensions infoHead->width = cropWidth; infoHead->height = cropHeight; // write the headers to the output file, checking for errors if (writeFileHeader(fileHead, outFile) != 0) { fprintf(stderr, "Unable to write file header.\n"); return EXIT_FAILURE; } if (writeInfoHeader(infoHead, outFile) != 0) { fprintf(stderr, "Unable to write info header.\n"); return EXIT_FAILURE; } // to store pixel being worked on struct pixel* curPixel = NULL; // run through old pixels, discarding those which are to be cropped // and writing the rest to file for (int i = 0; i < oldHeight; i++) { // only run through line if we're out of region to be cropped if (!(i < (oldHeight - cropStart[1] - cropHeight) || i > (oldHeight - cropStart[1]))) { for (int j = 0; j < oldWidth; j++) { // only write to file if not in cropped region if (!(j < cropStart[0] || j > cropStart[0] + cropWidth)) { // read in the current pixel curPixel = getPixel(inFile); // make sure read worked if (curPixel == NULL) { fprintf(stderr, "Unable to read pixel.\n"); return EXIT_FAILURE; } // write current pixel, checking for error if (writePixel(curPixel, outFile) != EXIT_SUCCESS) { fprintf(stderr, "Unable to write pixel.\n"); return EXIT_FAILURE; } } else { // move old file on by a pixel fseek(inFile, sizeof(struct pixel), SEEK_CUR); } } } else { // move old file on by width + padding fseek(inFile, oldWidth*sizeof(struct pixel) + oldPadding, SEEK_CUR); } // move old file on by padding fseek(inFile, oldPadding, SEEK_CUR); // add padding to new file for (int k = 0; k < newPadding; k++) { fputc(0x00, outFile); } } // free memory allocated to current pixel storage free(curPixel); // close the output file, checking for error if (fclose(outFile) != 0) { fprintf(stderr, "Unable to close output file: %s.\n", outFileName); return EXIT_FAILURE; } // if program gets to here, everything is okay return EXIT_SUCCESS; }
font * ttf_write_tga (char *name, int32_t pointsize) { uint32_t rmask, gmask, bmask, amask; double glyph_per_row; char filename[200]; SDL_Surface *dst; uint32_t height; uint32_t width; double maxx; double maxy[TTF_GLYPH_MAX]; uint32_t c; int x; int y; double h; font *f; snprintf(filename, sizeof(filename), "%s_pointsize%u.tga", name, pointsize); if (tex_find(filename)) { return (0); } /* * x glyphs horizontally and y vertically. */ glyph_per_row = 16; f = ttf_new(name, pointsize, TTF_STYLE_NORMAL); if (!f) { ERR("could not create font %s", name); } maxx = 0; memset(maxy, 0, sizeof(maxy)); /* * Find the largest font glyph pointsize. */ x = 0; y = 0; height = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { if (f->tex[c].image) { maxx = max(maxx, f->tex[c].image->w); maxy[y] = max(maxy[y], f->tex[c].image->h); } if (++x >= glyph_per_row) { x = 0; height += maxy[y]; y++; } } if (!maxx) { ERR("no glyphs in font %s", name); } width = glyph_per_row * maxx; if (MULTIPLE_BITS(width)) { width = nextpoweroftwo(width); } height += 40; if (MULTIPLE_BITS(height)) { height = nextpoweroftwo(height); } /* * Make a large surface for all glyphs. */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif dst = SDL_CreateRGBSurface(0, width, height, 32, rmask, gmask, bmask, amask); if (!dst) { ERR("no surface created for size %dx%d font %s", width, height, name); } newptr(dst, "SDL_CreateRGBSurface"); /* * Blit each glyph to the large surface. */ x = 0; y = 0; h = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { if (f->tex[c].image) { SDL_Rect dstrect = { maxx * x, h, maxx, maxy[y] }; SDL_BlitSurface(f->tex[c].image, 0, dst, &dstrect); } if (++x >= glyph_per_row) { x = 0; h += maxy[y]; y++; } } /* * Convert the black border smoothing that ttf adds into alpha. */ { double x; double y; for (x = 0; x < dst->w; x++) { for (y = 0; y < dst->h; y++) { color c; c = getPixel(dst, x, y); if ((c.a == 255) && (c.r == 255) && (c.g == 255) && (c.b == 255)) { /* * Do nothing. */ } else if ((c.a == 0) && (c.r == 0) && (c.g == 0) && (c.b == 0)) { /* * Do nothing. */ } else { /* * Convery gray to white with alpha. */ c.a = (c.r + c.g + c.b) / 3; c.r = 255; c.g = 255; c.b = 255; } putPixel(dst, x, y, c); } } } #define MAX_TEXTURE_HEIGHT 4096 if (dst->h > MAX_TEXTURE_HEIGHT) { ERR("ttf is too large"); } uint8_t filled_pixel_row[MAX_TEXTURE_HEIGHT] = {0}; /* * What the hell am I doing here? The ttf library returns incorrect * boounds for the top and bottom of glyphs, so I'm looking for a line of * no pixels above and below each glyph so I can really find the texture * bounds of a glyph. This allows squeezing of text together. */ { int x; int y; for (y = 0; y < dst->h; y++) { for (x = 0; x < dst->w; x++) { color c; c = getPixel(dst, x, y); if (c.r || c.g || c.b || c.a) { filled_pixel_row[y] = true; break; } } } } /* * Work our the tex co-ords for each glyph in the large tex. */ x = 0; y = 0; h = 0; int d1_max = 0; int d2_max = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { { int y = (h + (h + f->glyphs[c].height)) / 2; int miny = y; int maxy = y; for (;;) { if (!filled_pixel_row[miny]) { break; } miny--; if (miny <= 0) { break; } } for (;;) { if (!filled_pixel_row[maxy]) { break; } maxy++; if (maxy >= MAX_TEXTURE_HEIGHT - 1) { break; } } int d1 = y - miny; if (d1 > d1_max) { d1_max = d1; } int d2 = maxy - y; if (d2 > d2_max) { d2_max = d2; } } if (++x >= glyph_per_row) { x = 0; h += maxy[y]; y++; } } x = 0; y = 0; h = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { f->glyphs[c].texMinX = (double)(x * maxx) / (double)dst->w; f->glyphs[c].texMaxX = (double)((x * maxx) + f->glyphs[c].width) / (double)dst->w; { int y = (h + (h + f->glyphs[c].height)) / 2; int y1 = y - d1_max; int y2 = y + d2_max; if (y1 < 0) { y1 = 0; } f->glyphs[c].texMinY = (double)(y1) / (double)dst->h; f->glyphs[c].texMaxY = (double)(y2) / (double)dst->h; } if (++x >= glyph_per_row) { x = 0; h += maxy[y]; y++; } } SDL_LockSurface(dst); stbi_write_tga(filename, dst->w, dst->h, STBI_rgb_alpha, dst->pixels); SDL_UnlockSurface(dst); texp tex; tex = tex_from_surface(dst, filename, filename); if (!tex) { ERR("could not convert %s to tex", filename); } /* * Work our the tex co-ords for each glyph in the large tex. */ x = 0; y = 0; h = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { f->tex[c].image = dst; f->tex[c].tex = tex_get_gl_binding(tex); } /* * Save the glyph data. */ snprintf(filename, sizeof(filename), "%s_pointsize%u.data", name, pointsize); FILE *out = fopen(filename, "w"); fwrite(f->glyphs, sizeof(f->glyphs), 1, out); fclose(out); printf("wrote %s\n",filename); return (f); }
int effect(ImageData *img,ImageData *outimg) { int val; int x,y; int xx,yy; int hh; int endn; int vv, vr, vg, vb; int ave, rr, gg,bb; Pixel col,ncol; Pixel ans; int *sobel; int sadr; int rate,nn,i; int x1,y1,x2,y2; x1=0; y1=0; x2=img->width-1; y2=img->height-1; setRegInfo(); nn=2; for(y=y1;y<=y2;y++){ for(x=x1;x<=x2;x++){ rr=gg=bb=0; sadr=0; for(yy=(-nn);yy<=nn;yy++){ for(xx=(-nn);xx<=nn;xx++){ val = getPixel(img,x+xx,y+yy,&ncol); imgR[sadr]=ncol.r; imgG[sadr]=ncol.g; imgB[sadr]=ncol.b; sadr++; } } vr=vg=vb=1000; for(i=0;i<=8;i++){ vv=getRegVal(imgR,i,&ave); if(vr>vv){ vr=vv; rr=ave; } vv=getRegVal(imgG,i,&ave); if(vg>vv){ vg=vv; gg=ave; } vv=getRegVal(imgB,i,&ave); if(vb>vv){ vb=vv; bb=ave; } } vv=getRegVal(imgB,i,&ave); if(vb>vv){ vb=vv; bb=ave; } } ans.r = rr; ans.g = gg; ans.b = bb; setPixel(outimg,x,y,&ans); } }
int _bmpImage::createHeaderFile(int bpp, int dimensions) { int arrayWidth; FILE *fDest; std::string destfile = workingDir; if(dimensions == 1) { destfile += "_1dim"; } else if(dimensions == 2) { destfile += "_2dim"; } if(bpp == bit32) { destfile += "_32bit.h"; arrayWidth = bih.biWidth*4; } else if(bpp == bit24) { destfile += "_24bit.h"; arrayWidth = bih.biWidth*3; } else if(bpp == bit18) { destfile += "_18bit.h"; arrayWidth = bih.biWidth*3; } else if(bpp == bit16) { destfile += "_16bit.h"; arrayWidth = bih.biWidth*2; } else if(bpp == bit8) { destfile += "_8bit.h"; arrayWidth = bih.biWidth; } if((fDest = fopen(destfile.c_str(), "wb")) == NULL) { printf("The file %s cannot be created\n", destfile.c_str()); exit(0); } fprintf(fDest, "PROGMEM const unsigned char %c_%ibit", fname, bpp); if(dimensions == 2) { fprintf(fDest, "[%i][%i]", bih.biHeight, arrayWidth); } fprintf(fDest, " = {\n"); long Line = 0; for(LONG y = 0; y < bih.biWidth; y++) { for(LONG x = 0; x < bih.biHeight; x++) { BYTE newValue = 0; BYTE msb, lsb; RGBTRIPLE pixel = getPixel(x, y); RGBTRIPLE newPixel; if( (Line==0 || Line%bih.biWidth == 0) && (dimensions == 2) ) { fprintf(fDest, "{"); } if(bpp == bit32) { //32Bit Easy... done fprintf(fDest, "0x%02x, ", alpha); fprintf(fDest, "0x%02x, ", pixel.rgbtRed); fprintf(fDest, "0x%02x, ", pixel.rgbtGreen); fprintf(fDest, "0x%02x, ", pixel.rgbtBlue); } else if(bpp == bit24) { //24Bit fprintf(fDest, "0x%02x, ", pixel.rgbtRed); fprintf(fDest, "0x%02x, ", pixel.rgbtGreen); fprintf(fDest, "0x%02x, ", pixel.rgbtBlue); } else if(bpp == bit18) { //18Bit downConvert18(&pixel, &newPixel); fprintf(fDest, "0x%02x, ", newPixel.rgbtRed); fprintf(fDest, "0x%02x, ", newPixel.rgbtGreen); fprintf(fDest, "0x%02x, ", newPixel.rgbtBlue); } else if(bpp == bit16) { //16Bit downConvert16(&pixel, &msb, &lsb); fprintf(fDest, "0x%02x, ", msb); fprintf(fDest, "0x%02x, ", lsb); } else if(bpp == bit8) { //8 bit downConvert8(&pixel, &newValue); fprintf(fDest, "0x%02x, ", newValue); } if(++Line==0 || Line%bih.biWidth == 0) { if(dimensions == 2) { fprintf(fDest, "},\n"); if(x == bih.biHeight) { fprintf(fDest, "{"); } } else { fprintf(fDest, "\n"); } } } } //Print the closing string that makes this a variable fprintf(fDest, "};\n"); //All finished fclose(fDest); return 0; }
void remove_lines_2(image_t* img,params* parameters,uint32_t numCuts,image_t* lineless_img, uint32_t* stafflines, staff_info* staff){ /*initlize stafflines to a 5 elt array*/ uint32_t line_thickness, line_spacing, line_w, beginCut, endCut, *yprojection, linesFound, *stafflines_tmp, **STAFFLINES, i, j, vertSplice, sum, max_project, loc, eraseTop, eraseBottom, min_thisLineY,max_thisLineY, shift_variable,h,w, **last_stafflines, ii, jj; int32_t min_thisLineY_tmp; image_t *fixThatImage; h = img->height; w = img->width; /*CHANGES: GET RID OF*/ /* line_thickness = (uint32_t)(parameters->thickness); line_spacing = (uint32_t)(parameters->spacing);*/ /*END CHANGES*/ line_w = (uint32_t)(parameters->thickness + parameters->spacing); beginCut = 0; /*CHANGES: W-1 => W*/ endCut = (uint32_t)((w)/numCuts); /*END CHANGES*/ yprojection= (uint32_t *)mget_spc((uint32_t)h, sizeof(uint32_t)); for(i=0;i<h;i++){ sum = 0; for(j=0;j<w;j++){ sum += getPixel(img,i,j); } yprojection[i] = sum; } linesFound = 0; stafflines_tmp = (uint32_t *)mget_spc((uint32_t)10, sizeof(uint32_t)); while(linesFound < 5){ max_project = yprojection[0]; loc = 0; for(i=1; i<h; i++){ if(yprojection[i]>max_project){ max_project = yprojection[i]; loc = i; } } linesFound = linesFound + 1; /*all y coordinates of a line that is part of same staff line:*/ eraseTop = loc-(uint32_t)((line_w+1)/3 ); eraseBottom = loc+(uint32_t)((line_w+1)/3); if (eraseTop < 0){ eraseTop = 0; } /*avoid segfault*/ if (eraseBottom > h-1){ eraseBottom = h-1; } /*avoid segfault*/ min_thisLineY_tmp = -1; for(i=eraseTop; i<=eraseBottom; i++){ if(yprojection[i]>=(9*max_project)/10){ if(min_thisLineY_tmp == -1){ min_thisLineY_tmp = i; } max_thisLineY = i; } /*erase to avoid line in futher iterations*/ yprojection[i] = 0; } min_thisLineY = (uint32_t)(min_thisLineY_tmp); stafflines_tmp[2*(linesFound-1)] = min_thisLineY; stafflines_tmp[2*(linesFound-1)+1] = max_thisLineY; } free(yprojection); quickSort(stafflines_tmp,0,9); last_stafflines = (uint32_t **)multialloc (sizeof(uint32_t),2, 5,2); STAFFLINES = (uint32_t **)multialloc (sizeof (uint32_t),2, 5,2); for(i=0; i<5; i++){ last_stafflines[i][0] = stafflines_tmp[2*i]; last_stafflines[i][1] = stafflines_tmp[2*i + 1]; } free(stafflines_tmp); /*LOOP THRU VERTICAL CUTS*/ shift_variable=0; for(vertSplice =0; vertSplice<numCuts; vertSplice++){ fixThatImage = get_sub_img(img,-1,-1,beginCut,endCut); /*pretty up staff lines*/ fix_lines_and_remove(fixThatImage,parameters,last_stafflines,&shift_variable, vertSplice); for(ii=0;ii<h;ii++){ for(jj=beginCut;jj<=endCut;jj++){ setPixel(img,ii,jj,getPixel(fixThatImage,ii,jj-beginCut)); } } delete_image(fixThatImage); if (vertSplice==0){ for(i=0; i<5; i++){ STAFFLINES[i][0] = last_stafflines[i][0]; STAFFLINES[i][1] = last_stafflines[i][1]; } } beginCut = endCut + 1; /*CHANGED: W-1 TO W*/ endCut = endCut + (uint32_t)((w)/numCuts) + 1; /*END CHANGED*/ if (endCut > w-1){ endCut = w-1; } } /*copy over image*/ for(i=0; i<h;i++){ for(j=0; j<w;j++){ setPixel(lineless_img,i,j,getPixel(img,i,j)); } } for(i=0;i<5;i++){ /*CHANGED 1->0 2->1*/ stafflines[i] = (uint32_t)(((STAFFLINES[i][0]+STAFFLINES[i][1]+1)/2)); /*shift because of zero padding above*/ /*END CHANGE*/ } multifree(STAFFLINES,2); multifree(last_stafflines,2); }
inline Pixel getKeyPixel( BrightnessType br ) const { return getPixel(Im::Position::Zero(), br ); }
void fix_lines_and_remove(image_t* img,params* parameters, uint32_t** last_STAFFLINES, uint32_t *previous_start, uint32_t cutNum){ /*function [result,new_start,STAFFLINES] = fix_lines_and_remove(img,params,last_STAFFLINES,previous_start,cutNum)*/ /*remvoe lines from small portion of staff. also straightens staff.*/ flex_array_t *stafflines_tmp; uint32_t *yprojection, line_thickness, line_spacing, line_w, *last_STAFFLINES_avg, max_project, sum, h, w, i, j, ii, count, **STAFFLINES, dummy, loc, shift, findLine, match, lineBegin, lineEnd, found_thickness, middle, tooThick, tooHigh, any_stafflines_zero, now_avg, last_avg, goodLine, tooLow, curr, extend, lastDelete, cW, cH, topStop, botStop, thickness, paramThickness, thickness_th, topLine, shift_loop,k; int16_t *tempData,*temp_array; int32_t lineY; uint8_t pixelData; linked_list *staffLines, *allLINES, *temp; STAFFLINES=multialloc(sizeof(uint32_t),2,5,2); h = img->height; w = img->width; line_thickness = (uint32_t)(parameters->thickness); line_spacing = (uint32_t)(parameters->spacing); line_w = (uint32_t)(parameters->thickness + parameters->spacing); last_STAFFLINES_avg = (uint32_t *)malloc(sizeof(uint32_t)*5);/*mget_spc((uint32_t)5, sizeof(uint32_t));*/ for(i=0; i<5; i++){ last_STAFFLINES_avg[i] = (uint32_t)((last_STAFFLINES[i][0] + last_STAFFLINES[i][1] + 1)/2); } yprojection= (uint32_t *)mget_spc((uint32_t)h, sizeof(uint32_t)); max_project = 0; for(i=0;i<h;i++){ sum = 0; for(j=0;j<w;j++){ sum += getPixel(img,i,j); } yprojection[i] = sum; if(yprojection[i] > max_project){ max_project = yprojection[i]; } } count = 0; for(i=0;i<h;i++){ if (yprojection[i] >= (9*max_project)/10){ /*delete staff line, twiddle with the 80% later (90%)*/ count++; } } stafflines_tmp=make_flex_array(count); count = 0; for(i=0;i<h;i++){ if (yprojection[i] >= (9*max_project)/10){ /*delete staff line, twiddle with the 80% later (90%)*/ stafflines_tmp->data[count] = i; count++; } } free(yprojection); staffLines = group(stafflines_tmp, 3); /*CHANGE: CUTNUM = 1 TO 0*/ if (cutNum == 0 && staffLines->length == 5 ){ /*END CHANGE*/ i=0; while(is_list_empty(staffLines)==0){ tempData=(int16_t*)pop_top(staffLines); STAFFLINES[i][0] = tempData[0]; STAFFLINES[i][1] = tempData[1]; i++; free(tempData); } } else if ((staffLines->length) == 0){ for(i=0;i<5;i++){ STAFFLINES[i][0] = last_STAFFLINES[i][0]; STAFFLINES[i][1] = last_STAFFLINES[i][1]; } } /*CHANGE: CUTNUM = 1 TO 0*/ else if (cutNum == 0 && (staffLines->length) < 5){ /*END CHANGE*/ /*choose one line, then find closest line in last_STAFFLINES*/ tempData = (int16_t*)(getIndexData(staffLines, 0)); goodLine = (uint32_t)((tempData[0]+tempData[1]+1)/2); dummy = abs(last_STAFFLINES_avg[0] - goodLine); loc = 0; for(i=1;i<5;i++){ curr = abs(last_STAFFLINES_avg[i] - goodLine); if(curr<dummy){ dummy = curr; loc = i; } } shift = goodLine - last_STAFFLINES_avg[loc]; for(i=0;i<5;i++){ STAFFLINES[i][0] = last_STAFFLINES[i][0]+shift; STAFFLINES[i][1] = last_STAFFLINES[i][1]+shift; } } else{ count = 0; for(findLine=0;findLine<5;findLine++){ match = 0; for(i=0;i<(staffLines->length);i++){ tempData = (int16_t*)(getIndexData(staffLines, i)); lineBegin = (uint32_t)tempData[0]; lineEnd = (uint32_t)tempData[1]; /*lineBegin is top of line, lineEnd is bottom*/ found_thickness = lineEnd-lineBegin+1; /*CHANGED: 0.5 TO 1/2*/ middle = (uint32_t)((lineBegin + lineEnd+1)/2); /*END CHANGED*/ /*determine if the line is of expected location/size*/ tooThick = 0; tooHigh = 0; tooLow = 0; if(found_thickness > (line_thickness+2)) tooThick=1; if(middle < (last_STAFFLINES_avg[findLine] - 3)) tooHigh=1; if(middle > (last_STAFFLINES_avg[findLine] + 3)) tooLow=1; /*CHANGED: 1 TO 0*/ if (cutNum == 0){ /*END CHANGED*/ tooHigh = 0; tooLow = 0; if(middle < (last_STAFFLINES_avg[0] - 2*line_spacing)){tooHigh=1;} /*CHANGED + TO - ALSO, avg[5] -> avg[4] */ if(middle > (last_STAFFLINES_avg[4] + 2*line_spacing)){tooLow=1;} /*END CHANGED*/ } if (tooThick || tooHigh || tooLow){ continue; } else{ /*we found good match for staffline*/ match = 1; /*SAVE STAFF LINE LOCATIONS*/ STAFFLINES[count][0] = lineBegin; STAFFLINES[count][1] = lineEnd; count++; deleteIndexData(staffLines,i); break; } } /*end looping thru found lines*/ if(!match){ /*CHANGED*/ /*flag that no match was found*/ STAFFLINES[count][0] = 0; STAFFLINES[count][1] = 0; count++; } } /*end looping through matching staff lines*/ /*CHANGED BELOW*/ /*check for lines that did not get match*/ any_stafflines_zero = 0; for(i=0;i<5;i++){ if(STAFFLINES[i][0] == 0){ any_stafflines_zero = 1; break; } } if (any_stafflines_zero){ /*find shift value first*/ shift = 100; /*big value*/ for (findLine = 0; findLine<5;findLine++){ /*loop to find nonzero entry in STAFFLINES, then calculate shift*/ if (STAFFLINES[findLine][0]){ /*if nonzero*/ now_avg = (uint32_t)((STAFFLINES[findLine][0]+STAFFLINES[findLine][1]+1)/2); last_avg = last_STAFFLINES_avg[findLine]; shift = now_avg - last_avg; break; } } if (shift==100){ shift = 0;} /*replace any flagged (with 0) entries in STAFFLINES*/ for(findLine=0;findLine<5;findLine++){ if (STAFFLINES[findLine][0] == 0){ STAFFLINES[findLine][0] = last_STAFFLINES[findLine][0]+shift; STAFFLINES[findLine][1] = last_STAFFLINES[findLine][1]+shift; } } } } extend = (uint32_t)((line_w+2)/4)+1; /*create stafflines above*/ allLINES=create_linked_list(); lineY = (int32_t)(((STAFFLINES[0][0] + STAFFLINES[0][1]+1)/2) - line_w); /*first above line*/ while (1){ if (lineY < (int32_t)(extend + 2)){ break; } else{ temp_array=malloc(sizeof(int16_t)*2); temp_array[0]=(int16_t)lineY; temp_array[1]=(int16_t)lineY; push_top(allLINES,temp_array); lineY = (int32_t)(lineY - (int32_t)line_w ); } } for(i=0;i<5;i++){ temp_array=malloc(sizeof(uint32_t)*2); temp_array[0]=(int16_t)STAFFLINES[i][0]; temp_array[1]=(int16_t)STAFFLINES[i][1]; push_bottom(allLINES,temp_array); } /*create stafflines below*/ lineY = (uint32_t)(((STAFFLINES[4][0] + STAFFLINES[4][1]+1)/2) + line_w); /*first above line*/ while (1){ if (lineY > (h - extend - 3)){ break; } else{ temp_array=malloc(sizeof(int16_t)*2); temp_array[0]=(int16_t)lineY; temp_array[1]=(int16_t)lineY; push_bottom(allLINES,temp_array); lineY = (uint32_t)(lineY + (int32_t)line_w); } } /*REMOVE STAFF LINES*/ while( is_list_empty(allLINES)==0){ tempData = (int16_t*)pop_top(allLINES); lineBegin = tempData[0]; lineEnd = tempData[1]; middle = (lineBegin + lineEnd + 1)/2; lastDelete = 0; free(tempData); for(j=0;j<w;j++){ /*top of staff line*/ topStop = 0; /*CHANGED*/ for(ii = (lineBegin-1); ii>=(lineBegin-extend); ii--){ /*END CHANGED*/ if (ii < 0){ break; } if (getPixel(img,ii,j)==0){ /*then erase*/ topStop = ii+1; break; } } /*bottom of staff line*/ botStop = h-1; /*CHANGED*/ for(ii = lineEnd+1; ii<=(lineEnd+extend); ii++){ /*END CHANGED*/ if (ii > h-1){ break; } if(getPixel(img,ii,j)==0){ botStop = ii-1; break; } } /*check thickness of line, delete if skinny*/ thickness = botStop - topStop + 1; if (parameters->thickness < 3){ paramThickness = parameters->thickness + 1; } else{ paramThickness = parameters->thickness; } if (lastDelete){ /*there was a line deletion last iteration*/ thickness_th = paramThickness*2; /*higher threshold*/ } else{ thickness_th = paramThickness*2-2; } if (thickness <= thickness_th){ for(ii=topStop; ii<=botStop; ii++){ setPixel(img,ii,j,0); } lastDelete = 1; } else{ lastDelete = 0; } } } /*end staff line*/ topLine = STAFFLINES[0][0]; if(*previous_start){ if(*previous_start<topLine){ shift=topLine-(*previous_start); /*CHANGED H-SHIFT-1 TO H-SHIFT*/ for(shift_loop=0; shift_loop<(h-shift); shift_loop++){ /*END CHANGED*/ for(cW=0; cW<w; cW++){ pixelData=getPixel(img,shift_loop+shift,cW); setPixel(img,shift_loop,cW,pixelData); } } for(cH=h-shift-1; cH<h; cH++){ for(cW=0; cW<w; cW++){ setPixel(img,cH,cW,0); } } } else if(*previous_start>topLine){ shift=*previous_start-topLine; for(shift_loop=h-1; shift_loop>=shift; shift_loop--){ for(cW=0; cW<w; cW++){ pixelData=getPixel(img,shift_loop-shift,cW); setPixel(img,shift_loop,cW, pixelData); } } /*CHANGED: SHIFT-1 TO SHIFT*/ for(cH=0; cH<shift; cH++){ /*END CHANGED*/ for(cW=0; cW<w; cW++){ setPixel(img,cH,cW,0); } } } } else{ *previous_start=topLine; } for(i=0; i<5;i++){ last_STAFFLINES[i][0] = STAFFLINES[i][0]; last_STAFFLINES[i][1] = STAFFLINES[i][1]; } delete_list(staffLines); delete_list(allLINES); multifree(STAFFLINES,2); }
// parallel access from threads // do not modify class variable values here without mutex void Threshold::computeEdgemap(int size, int offset, int y1, int y2) { long threshold = 0, lastdelta = 0, di = 0; bool thispixel = false, epixel = false; int ex = 0, ey = 0, ei = 0; int blocksize = size*size, radius = size/2, half_block = blocksize/2; //overlapping segment correction if( y1 > 0 ) y1-=size; //all segments beginning in middle of tagimage if( y2 < height ) y2+=size; //all segments ending in the middle of tagimage int new_radius = radius + y1; int *td = new int[width*height]; //threshold deltas //TODO moving window of (size*width) int *ts = new int[width]; //threshold sums for(int x = 0; x < (width*height); x++) td[x] = 0; for(int x = 0; x < width; x++) ts[x] = 0; for(int y = y1; y < y2; y++){ if(config->TAG_DEBUG) { //TODO: Remove once threads are final if(y1 == 0) printf("*"); if(y1 > 0) printf("-"); } for(int x = 0; x < width; x++){ if( y >= (height-radius) ){ //partial: bottom rows ts[x] -= td[((y-radius)*width)+x]; threshold = ts[x] / (size*(radius+height-y)); }else if( y > radius && x == 0 ){ //normal: very first di = ((y+radius)*width) + x; for(int i = 0; i < radius; i++) td[di]+=getPixel(i, y+radius); ts[x] += td[di] - td[((y-radius-1)*width)+x]; threshold = ts[x] /half_block; lastdelta = td[di]; }else if( y > radius && x >= width - radius ){//normal: partial end di = ((y+radius)*width) + x; td[di] = lastdelta - getPixel(x-radius-1,y+radius); ts[x] += td[di] - td[((y-radius)*width)+x]; threshold = ts[x] / ((width-x+radius)*size); lastdelta = td[di]; }else if( y > radius && x <=radius ){ //normal: partial begin di = ((y+radius)*width) + x; td[di]=lastdelta + getPixel(x+radius, y+radius); ts[x]+= td[di] - td[((y-radius)*width)+x]; threshold = ts[x] / ((x+radius)*size); lastdelta = td[di]; }else if( y > radius ){ //normal: all full (90% of all) di = ((y+radius)*width) + x; td[di] = lastdelta + getPixel(x+radius, y+radius) - getPixel(x-radius-1,y+radius); ts[x] += td[di] - td[((y-radius)*width)+x]; threshold = ts[x] / blocksize; lastdelta = td[di]; }else if( x == 0 && y == 0 ){ //first top left block for(int j = y1; j < radius; j++){ di = j*width; for(int i = 0; i < radius; i++) td[di] += getPixel(i, j); ts[x] += td[di]; } threshold = ts[x] /(blocksize/4); }else if( y == y1 ){ //partial: topmost row all for(int j = y1; j < radius; j++){ di = (j*width) + x; td[di] = td[di-1]; if(x > radius) td[di] -= getPixel(x-radius-1, j); if(x <= width-radius) td[di] += getPixel(x+radius, j); ts[x] += td[di]; } if(x <= radius) threshold = ts[x] / (radius*(x+radius)); else if(x <= width-radius) threshold = ts[x] / half_block; else threshold = ts[x] / ((width-x+radius)*radius); }else if( y <= new_radius && x <= radius){ //partial: top row begin di = ((y+radius)*width) + x; for(int i = 0; i < x+radius; i++) td[di] += getPixel(i, y+radius); ts[x] += td[di]; threshold = ts[x] / ((x+radius)*(y+radius)); }else if( y <= new_radius && x >= width -radius){ //partial: top row end di = ((y+radius)*width) + x; for(int i = width; i > x-radius; i--) td[di] += getPixel(i, y+radius); ts[x] += td[di]; threshold = ts[x] / ((width-x+radius)*(y+radius)); }else if( y <= new_radius ){ //partial: top row all di = ((y+radius)*width) + x; for(int i = 0; i < size; i++) td[di] += getPixel((x-radius)+i, y+radius); ts[x] += td[di]; threshold = ts[x] / (size*(y+radius)); } //skip overlap only for beginning on the middle //will be covered by the one above ( applies to multi thread only) if( y1 == 0 || y > y1+size){ threshold-=offset; thispixel = getPixel(x, y) < threshold ? true : false; ta[(y*width)+x] = thispixel; if(pixdebug) thispixel ? d_setPixelFilled(x, y) : d_setPixelBlank(x, y); } if( config->THREADS < 2 ){ //single thread do it in the thresholding loop if( y > 2){ //edge marking based on ta[] ex = x; ey = y-2; ei = ((ey)*width)+ex; epixel = ta[ei]; if( epixel ){ if( ex > 0 && ex < width ){ if( epixel ^ ta[(ey*width)+ex-1] || epixel ^ ta[(ey*width)+ex+1] || epixel ^ ta[((ey-1)*width)+ex] || epixel ^ ta[((ey-1)*width)+ex+1] || epixel ^ ta[((ey-1)*width)+ex-1] || epixel ^ ta[((ey+1)*width)+ex] || epixel ^ ta[((ey+1)*width)+ex+1] || epixel ^ ta[((ey+1)*width)+ex-1] ){ edgemap[ei] = true; if(pixdebug || config->V_D_PIXDEBUG) d_setPixelMarked(ex, ey); }else{ if(pixdebug || config->V_D_PIXDEBUG) d_setPixelBlank(ex, ey); } } }else{ //if(VIDEO) d_setPixelBlank(ex, ey); } } } //close out borders on bottom edge //if((y == height-1) && thispixel) d_setPixelMarked(x, y); } //close out borders on right edge //if((x == width) && thispixel) d_setPixelMarked(x-1, y); } delete [] ts; delete [] td; }
void ImageDecoder::MipMap::getPixel(int x, int y, float &r, float &g, float &b, float &a) const { getPixel(y * width + x, r, g, b, a); }
void Draw (SDL_Surface *screen, char *bmpfile) { char messageText[128]; Uint32 rmask, gmask, bmask, amask; SDL_Surface *picture; SDL_Surface *mapped_picture; SDL_Surface *rotozoom_picture; SDL_PixelFormat *pixelFormat; Uint8 *grayscale, *map, *curmap; double *unrelaxed, *relaxed, *currelax; int mapsize, relaxsize; int rowskip; char *pixel; Uint32 p; int x, y; Uint8 r, g, b, a; double dy; double t, s; int i; double c1, c2, c3, c4, ca; Uint8 lookupTable[256]; double zw, zh, zf; /* SDL interprets each pixel as a 32-bit number, so our masks must depend on the endianness (byte order) of the machine */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif /* Load the image into a surface */ printf("Loading picture: %s\n", bmpfile); picture = SDL_LoadBMP(bmpfile); if ( picture == NULL ) { fprintf(stderr, "Couldn't load %s: %s\n", bmpfile, SDL_GetError()); return; } /* Convert image to a brightness map */ printf("Allocating workbuffers\n"); mapsize = picture->w * picture->h; relaxsize = mapsize * sizeof(double); grayscale = (Uint8 *)malloc(mapsize); map = (Uint8 *)malloc(mapsize); unrelaxed = (double *)malloc(relaxsize); relaxed = (double *)malloc(relaxsize); if ((grayscale == NULL) || (map == NULL) || (unrelaxed == NULL) || (relaxed == NULL)) { fprintf(stderr, "Out of memory\n"); return; } memset(grayscale, 0, mapsize); memset(map, 0, mapsize); memset(unrelaxed, 0, relaxsize); memset(relaxed, 0, relaxsize); printf("Converting image to brightness map\n"); pixel = picture->pixels; pixelFormat = picture->format; rowskip = (picture->pitch - picture->w * picture->format->BytesPerPixel); curmap = grayscale; for (y=0; y < picture->h; y++) { for (x=0; x < picture->w; x++) { // Get RGB p = getPixel(picture, x, y); SDL_GetRGBA(p, pixelFormat, &r, &g, &b, &a); // Calculate luminance (Y = 0.3R + 0.59G + 0.11B;) dy = (0.30 * r) + (0.59 * g) + (0.11 * b); if (dy<0.0) { dy=0.0; } else if (dy>255.0) { dy=255.0; } *curmap = (Uint8)dy; // Next pixel pixel += picture->format->BytesPerPixel; curmap++; } // Next row pixel += rowskip; } /* --- Prepare relaxation loop --- */ /* Binarize luminance map */ SDL_imageFilterBinarizeUsingThreshold(grayscale, map, mapsize, threshold); /* Create cos^5 based lookup table */ t = 0.0; for (i = 0; i < 256; i++) { s = 1.0 - 0.5 * (1.0 + cos(t)); s = 255.0 * s * s * s * s * s; lookupTable[i] = (Uint8)s; t += ((double)contours*2.0*3.141592653589/128.0); } /* Create new surface for relaxed image */ mapped_picture = SDL_CreateRGBSurface(SDL_SWSURFACE, picture->w, picture->h, 32, rmask, gmask, bmask, amask); if (mapped_picture == NULL) { fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError()); return; } /* Apply relaxation algorithm */ printf("Applying Laplacian relaxation: %i iterations\n", iterations); // Iterate to relax for (i = 0; i <= iterations; i++) { // Backup original memcpy(unrelaxed, relaxed, relaxsize); // Average into relaxed for (x=0; x < picture->w; x++) { for (y=0; y < picture->h; y++) { // up c1 = GetPotential(map, grayscale, unrelaxed, x, y-1, picture->w, picture->h); // down c2 = GetPotential(map, grayscale, unrelaxed, x, y+1, picture->w, picture->h); // left c3 = GetPotential(map, grayscale, unrelaxed, x-1, y, picture->w, picture->h); // right c4 = GetPotential(map, grayscale, unrelaxed, x+1, y, picture->w, picture->h); // average and store ca = ((c1 + c2 + c3 + c4)/4.0); relaxed[x+y*picture->w] = ca; } } // Draw only sometimes if (((i % 10)==0) || (i==iterations)) { /* --- Create image with contour map --- */ /* Fill output surface via colormap */ currelax = relaxed; for (y=0; y<mapped_picture->h; y++) { for (x=0; x<mapped_picture->w; x++) { if (map[x+y*picture->w]!=0) { r = g = b = grayscale[x+y*picture->w]; } else { r = g = b = lookupTable[(Uint8)*currelax]; } pixelRGBA(mapped_picture, x, y, r, g, b, 255); currelax++; } } /* --- Scale and draw to screen --- */ /* Scale to screen size */ zw = (double)screen->w/(double)mapped_picture->w; zh = (double)screen->h/(double)mapped_picture->h; zf = (zw < zh) ? zw : zh; if ((rotozoom_picture=zoomSurface(mapped_picture, zf, zf, 1))==NULL) { fprintf(stderr, "Rotozoom failed: %s\n", SDL_GetError()); return; } /* Draw surface to screen */ if ( SDL_BlitSurface(rotozoom_picture, NULL, screen, NULL) < 0 ) { fprintf(stderr, "Blit failed: %s\n", SDL_GetError()); return; } SDL_FreeSurface(rotozoom_picture); /* Info */ if (i != iterations) { sprintf(messageText,"%i", i); stringRGBA(screen, 8, 8, messageText, 255, 255, 255, 255); } /* Display by flipping screens */ SDL_Flip(screen); } /* Maybe quit */ HandleEvent(); } /* Save final picture */ if (SDL_SaveBMP(mapped_picture, "result.bmp") <0) { fprintf(stderr, "Save BMP failed: %s\n", SDL_GetError()); return; } free(map); free(grayscale); free(unrelaxed); free(relaxed); SDL_FreeSurface(picture); SDL_FreeSurface(mapped_picture); return; }
/*! Get the view of the virtual camera. Be careful, the image I is modified. The projected image is not added as an overlay! \param I : The image used to store the result. \param cam : The parameters of the virtual camera. */ void vpImageSimulator::getImage(vpImage<unsigned char> &I, const vpCameraParameters &cam) { if (setBackgroundTexture) // The Ig has been set to a previously defined background texture I = Ig; else { if (cleanPrevImage) { unsigned char col = (unsigned char) (0.2126 * bgColor.R + 0.7152 * bgColor.G + 0.0722 * bgColor.B); for (unsigned int i = 0; i < I.getHeight(); i++) { for (unsigned int j = 0; j < I.getWidth(); j++) { I[i][j] = col; } } } } if(visible) { if(!needClipping) getRoi(I.getWidth(),I.getHeight(),cam,pt,rect); else getRoi(I.getWidth(),I.getHeight(),cam,ptClipped,rect); double top = rect.getTop(); double bottom = rect.getBottom(); double left = rect.getLeft(); double right= rect.getRight(); unsigned char *bitmap = I.bitmap; unsigned int width = I.getWidth(); vpImagePoint ip; int nb_point_dessine = 0; for (unsigned int i = (unsigned int)top; i < (unsigned int)bottom; i++) { for (unsigned int j = (unsigned int)left; j < (unsigned int)right; j++) { double x=0,y=0; ip.set_ij(i,j); vpPixelMeterConversion::convertPoint(cam,ip, x,y); ip.set_ij(y,x); if (colorI == GRAY_SCALED) { unsigned char Ipixelplan = 0; if(getPixel(ip,Ipixelplan)) { *(bitmap+i*width+j)=Ipixelplan; nb_point_dessine++; } } else if (colorI == COLORED) { vpRGBa Ipixelplan; if(getPixel(ip,Ipixelplan)) { unsigned char pixelgrey = (unsigned char)(0.2126 * Ipixelplan.R + 0.7152 * Ipixelplan.G + 0.0722 * Ipixelplan.B); *(bitmap+i*width+j)=pixelgrey; nb_point_dessine++; } } } } } }
void poImage::blur(int kernel_size, float sig, int stepMultiplier) { float e = 2.718281828f; int hk = kernel_size / 2; float *kernel = new float[kernel_size]; for(int i=0; i<kernel_size; i++) { float contrib = powf(i - hk, 2) / (2 * sig*sig); kernel[i] = powf(e, -contrib); } poImage* tmp = copy(); int width = getWidth(); int height = getHeight(); for(int y=0; y<height; y++) { for(int x=0; x<width; x++) { poColor sum; float k_tot = 0; for(int i=-hk; i<hk; i++) { int stp = i * stepMultiplier; if(x+stp < 0 || x+stp >= width) continue; float k = kernel[i+hk]; k_tot += k; poColor c = getPixel(poPoint(x+stp,y)); sum = sum + (c*k); } tmp->setPixel(poPoint(x,y), sum/k_tot); } } for(int y=0; y<height; y++) { for(int x=0; x<width; x++) { poColor sum; float k_tot = 0; for(int i=-hk; i<hk; i++) { int stp = i * stepMultiplier; if(y+stp < 0 || y+stp >= height) continue; float k = kernel[i+hk]; k_tot += k; poColor c = tmp->getPixel(poPoint(x,y+stp)); sum = sum + (c*k); } setPixel(poPoint(x,y), sum/k_tot); } } delete tmp; delete [] kernel; }
/*! Get the view of the virtual camera. Be carefull, the image I is modified. The projected image is not added as an overlay! To take into account the projection of several images, a matrix \f$ zBuffer \f$ is given as argument. This matrix contains the z coordinates of all the pixel of the image \f$ I \f$ in the camera frame. During the projection, the pixels are updated if there is no other plan between the camera and the projected image. The matrix \f$ zBuffer \f$ is updated in this case. \param I : The image used to store the result. \param cam : The parameters of the virtual camera. \param zBuffer : A matrix containing the z coordinates of the pixels of the image \f$ I \f$ */ void vpImageSimulator::getImage(vpImage<vpRGBa> &I, const vpCameraParameters &cam, vpMatrix &zBuffer) { if (I.getWidth() != (unsigned int)zBuffer.getCols() || I.getHeight() != (unsigned int)zBuffer.getRows()) throw (vpMatrixException(vpMatrixException::incorrectMatrixSizeError, " zBuffer must have the same size as the image I ! ")); if (cleanPrevImage) { for (unsigned int i = 0; i < I.getHeight(); i++) { for (unsigned int j = 0; j < I.getWidth(); j++) { I[i][j] = bgColor; } } } if(visible) { if(!needClipping) getRoi(I.getWidth(),I.getHeight(),cam,pt,rect); else getRoi(I.getWidth(),I.getHeight(),cam,ptClipped,rect); double top = rect.getTop(); double bottom = rect.getBottom(); double left = rect.getLeft(); double right= rect.getRight(); vpRGBa *bitmap = I.bitmap; unsigned int width = I.getWidth(); vpImagePoint ip; int nb_point_dessine = 0; for (unsigned int i = (unsigned int)top; i < (unsigned int)bottom; i++) { for (unsigned int j = (unsigned int)left; j < (unsigned int)right; j++) { double x=0,y=0; ip.set_ij(i,j); vpPixelMeterConversion::convertPoint(cam,ip, x,y); ip.set_ij(y,x); if (colorI == GRAY_SCALED) { unsigned char Ipixelplan; if(getPixel(ip,Ipixelplan)) { if (Xinter_optim[2] < zBuffer[i][j] || zBuffer[i][j] < 0) { vpRGBa pixelcolor; pixelcolor.R = Ipixelplan; pixelcolor.G = Ipixelplan; pixelcolor.B = Ipixelplan; *(bitmap+i*width+j) = pixelcolor; nb_point_dessine++; zBuffer[i][j] = Xinter_optim[2]; } } } else if (colorI == COLORED) { vpRGBa Ipixelplan; if(getPixel(ip,Ipixelplan)) { if (Xinter_optim[2] < zBuffer[i][j] || zBuffer[i][j] < 0) { *(bitmap+i*width+j) = Ipixelplan; nb_point_dessine++; zBuffer[i][j] = Xinter_optim[2]; } } } } } } }
image_t* remove_lines(image_t* img, params* staff_params, uint16_t numCuts, uint16_t **STAFFLINES) { /*returns staff without lines, and STAFFLINES as a 5x2 array*/ uint16_t line_thickness,height,width,line_spacing; uint16_t beginCut,endCut; projection_t* yprojection; projection_t* yprojection2; flex_array_t* ones_array; flex_array_t* ones_array2; flex_array_t* staffLines; uint16_t** last_stafflines; int16_t* array_staff; linked_list* stack; int16_t max_project; uint16_t i,j,lines_found; int16_t shift_variable; uint16_t vertSplice; image_t* fixThatImage; image_t* new_img; /*End Var Declarations*/ line_thickness=staff_params->thickness; line_spacing=staff_params->spacing; height=img->height; width=img->width; beginCut = 0; endCut = (width+numCuts/2)/numCuts; /*/ get inital staff line estimates*/ yprojection2 = project(img,2); ones_array=array_ones(line_thickness); ones_array2=array_ones(1); yprojection = filter(ones_array,ones_array2,yprojection2); /* reduce impact of 'double peaks' (curvy lines)*/ delete_flex_array(ones_array); delete_flex_array(ones_array2); delete_flex_array(yprojection2); max_project = index_of_max(yprojection); for (i=max_project-(line_spacing+1)/2;i<max_project+(line_spacing+1)/2;i++){ yprojection->data[i]=0; } staffLines=find(yprojection,.8*max_project,greater); /*delete staff line, twiddle with the 85% later*/ stack = group(staffLines,3); last_stafflines=multialloc(sizeof(uint16_t),2,5,2); i=0; while (is_list_empty( stack)==0){ array_staff=pop_bottom(stack); last_stafflines[i][0]=(uint16_t)array_staff[0]; last_stafflines[i][1]=(uint16_t)array_staff[1]; free(array_staff); i++; } /* LOOP THRU VERTICAL CUTS*/ shift_variable=0; for (vertSplice = 0;vertSplice<numCuts; vertSplice++){ fixThatImage = get_sub_img(img,-1,-1,beginCut,endCut); /*pretty up staff lines*/ /*implement this once created...*/ /*[img(:,beginCut:endCut),shift_variable,stafflines] = ...*/ /* fix_lines_and_remove_smart(fixThatImage,params,last_stafflines,shift_variable,vertSplice);*/ /*modify last_stafflines in place */ delete_image(fixThatImage); if (vertSplice==1 && STAFFLINES){ for (i=0;i<5;i++){ for (j=0;j<2;j++){ STAFFLINES[i][j]=last_stafflines[i][j]+2;/*create STAFFLINES*/ } } } beginCut = endCut + 1; endCut += (width+numCuts/2)/numCuts; if (endCut >= width) endCut = width-1; } new_img=make_image(img->height +4,img->width +4); for (i=0;i<(img->height +4);i++){ for (j=0;j<(img->width +4);j++){ if (i<2 ||j<2 ||(i>(img->height +1)) ||(j>(img->width +1))){ setPixel(new_img,i,j,0); } else { setPixel(new_img,i,j,getPixel(img,i-2,j-2)); } } } return new_img; }
void edge_counter(ac_int<PIXEL_WL*KERNEL_WIDTH, false> vin[NUM_PIXELS], ac_int<PIXEL_WL, false> vout[NUM_PIXELS], ac_int<30, false> & sum, ac_int<1, false> * flag) { // Declrea and initialize variables and registers ac_int<16, true> x_arr[KERNEL_WIDTH], y_arr[KERNEL_WIDTH]; ac_int<16, true> gx, gy, res; static int tmp_sum = 0; static shift_class<ac_int<PIXEL_WL*KERNEL_WIDTH,false>, KERNEL_WIDTH> regs; // declare variables int i = 0; // initialize the variables gx = gy = res = 0; // Initialize sum as previous accumulated value and initialize flag as true (rised edge) sum = tmp_sum; tmp_sum = 0; *flag = 1; FRAME: for(int p = 0; p < NUM_PIXELS; p++) { *flag = (p <= (NUM_PIXELS / 2)); // init gx and accumulators gx = 0; gy = 0; RESET: for(i = 0; i < KERNEL_WIDTH; i++) { x_arr[i] = 0; y_arr[i] = 0; } // shift input data in the filter fifo regs << vin[p]; // advance the pointer address by the pixel number (testbench/simulation only) // accumulate ACC1: for(i = 0; i < KERNEL_WIDTH; i++) { // current line // NB : Unroll this loop! ACC1_1: for (int j = 0 ; j < 3 ; j++) { x_arr[j] += MASK_X[i][j] * getPixel(regs, i, j); y_arr[j] += MASK_Y[i][j] * getPixel(regs, i, j); } } // add the accumualted value for all processed lines ACC2: for(i = 0; i < KERNEL_WIDTH; i++) { gx += x_arr[i]; gy += y_arr[i]; } // normalize result gx /= 3; gy /= 3; // absolute value if(gx < 0) { gx = -gx; } if(gy < 0) { gy = -gy; } // Compute absolute sum res = gx + gy; if (res >= 1023) { res = 1023; } // group the RGB components into a single signal vout[p] = getGrayScalePixel(res, p % 2, *flag); // add the original value rather than the capped-value tmp_sum += (gx + gy); } sum = tmp_sum; *flag = 1; // Trigger the flag on completion }
linked_list* find_top_bottom(const image_t* img,uint16_t height_min,uint16_t leftCutoff,linked_list* groupings){ /* finds all vertical lines (stems, measure markers) Returns: groupings - indices within goodLines array of start and end of each vertical line ex: [40 42 55 58 100 110] goodLines - array of structs for each vertical found .top .bottom .left .right*/ /*Var Declarations*/ uint16_t height,width,col,row,test_length,i,real_length; linked_list *goodlines_first;/*since unsure of size, trim down later*/ flex_array_t *starts; uint8_t inLine,shift,step; uint16_t cursor1,cursor2; good_lines_t *lines; /*End Var Declarations*/ height=img->height; width=img->width; goodlines_first=create_linked_list(); real_length=0; for (col=0;col<width;col++){ test_length=0; i=0; for (row=1;row<height;row++){ if(!getPixel(img,row-1,col) && getPixel(img,row,col)) test_length++; } starts=make_flex_array(test_length); for (row=1;row<height;row++){ if(!getPixel(img,row-1,col) && getPixel(img,row,col)) starts->data[i++]=row;; } for (i=0;i<test_length;i++) {/*start = starts;*/ inLine = 1; cursor1=starts->data[i]; cursor2=col; shift = 0; while(inLine){ step = 0; if ( getPixel(img,cursor1+1,cursor2)==1 ){ /*right below*/ cursor1++; step = 1; } if ( cursor2+1 < width && !step ){ /*to the bottom right*/ if (getPixel(img,cursor1+1,cursor2+1) ){ cursor1++; cursor2++; step = 1; shift++; } } if ( cursor2-1 >= 0 && !step){ /*to the bottom left*/ if (getPixel(img,cursor1+1,cursor2-1) ){ cursor1++; cursor2--; step = 1; shift ++; } } if (!step || shift > 3){ /*can't continue black run*/ if (cursor1-(starts->data[i])>=height_min){ real_length++; lines=(good_lines_t *)malloc(sizeof(good_lines_t)); lines->bottom=cursor1; lines->index=col; lines->left= col<cursor2 ? col : cursor2; lines->top=starts->data[i]; lines->right=col>cursor2 ? col: cursor2; lines->left +=leftCutoff-1; lines->right+= leftCutoff-1; push_bottom(goodlines_first,lines); } inLine = 0; } } /*end while in line*/ } /*end for thru each starting location*/ delete_flex_array(starts); } /*end for thru each column*/ starts=make_flex_array(real_length); for (i=0;i<real_length;i++){ starts->data[i]=((good_lines_t*)getIndexData(goodlines_first,i))->left; } /*GROUP LINES TOGETHER*/ fill_group_indices(groupings,starts,5); /*2nd arg chosen to group close lines together*/ delete_flex_array(starts); return goodlines_first; }
/***************************************************** ** 不要修改下面的任何函数和代码!!! ** ** ** 如果需要,你可以阅读这些代码,或调用它们,或copy其中的部分。 ** (注意不要让它们过多的局限你的修改思路) ** ** 但是,请仔细阅读下面函数中的注释. ** 便于你理解 slow_rescale()是如何实现图片放大的 *****************************************************/ unsigned char *slow_rescale(unsigned char *src, int src_x, int src_y, int dest_x, int dest_y) { /* 图像数据类似于一个矩阵,矩阵的宽和高分别就是图像的宽(x方向长度)和高(y方向长度) 每个矩阵的元素就是图像中的一个像素点,记录的是这个点的颜色 但一个颜色需要用3个8位的元素分别记录构成这个颜色的RGB值。 因此,假设图像的宽为sx,高为sy 那么存储图像中所有像素的颜色信息需要sx * sy * 3个字节 在本实验中,PPM图像将所有信息按行顺序存放在一维数组中 [(0,0) (1,0) (2,0) ... (sx-1,0) (0,1) (1,1) ... (sx-1,1) ... ... ... (sx-1,sy-1)] 注意:这里的每个(x,y)代表一个像素,而真正存放这个像素的地址空间是连续的3个字节。. 本文件中提供的 getPixel() 和 setPixel() 可以用来存取图像的像素颜色. 你也可以写你字节的存取函数或甚至不使用存取函数以达到更快的速度 ---------------------- 双线性插值放大算法思路: 我们提供分辨率较小(???)的实验图片和一个大的目标分辨率(1920x1080). 因此需要用插值的方法从小图像的颜色计算出大图像的颜色。 (1)计算目标图像和源图像的宽高比值. 例如源图像的宽高为 (src_x, src_y) 目标图像的宽高为 (dst_x, dst_y): 则: step_x=src_x/dst_x; step_y=src_y/dst_y; 例如: 源(10 x 10) 和目标 (25 x 25) 可计算出step_x=step_y=0.4 (2)源图像中的0.4个像素将要“变”为目标图像中的一个像素! 也就是说,我们需要进行下列赋值: dst(0,0) <- src(0,0) dst(0,1) <- src(0,0.4) dst(0,2) <- src(0,0.8) dst(0,3) <- src(0,1.2) . . . dst(1,0) <- src(0.4,0) dst(1,1) <- src(0.4,0.4) . . 等等 但是, src(0.4,0.4) 这样以小数为下标的像素点并不是真实存在的。 所以, 需要插值。 (3) 插值的方法就是找到这个小数下标的上下左右共四个最近的整数下标像素点。如下图: 对于 src(0.4,0.4)找到的4个点就是N1-N4: N1 T1 N2 src(0,0) -----------*----------------------src(1,0) | | | src(0.4,0.4) | | | | | | | src(0,1)-------------*----------------------src(1,1) N3 T2 N4 利用N1和N2的颜色,以及根据0.4和“0”“1”之间各自的距离,可以插值计算得到T1的颜色, (即0.6*N1 + 0.4*N2 = T1) 类似的, 利用N3和N4的颜色,可以插值计算得到T2的颜色, 利用T1和T2的颜色,可以插值计算得到最终所需要的src(0.4,0.4)的颜色, (4)注意这里的“颜色”都需要分RGB三个字节分别进行计算。 而当源或目标分辨率很大的时候,计算次数十分庞大。所以,优化是十分必要的。 下面是一个十分“不优化”的函数。你可以将之作为“反例”进行参考。 重要的是只要你理解上面的插值过程,你就可以完成你自己的fast函数了! */ double step_x,step_y; // Step increase as per instructions above unsigned char R1,R2,R3,R4; // Colours at the four neighbours unsigned char G1,G2,G3,G4; unsigned char B1,B2,B3,B4; double RT1, GT1, BT1; // Interpolated colours at T1 and T2 double RT2, GT2, BT2; unsigned char R,G,B; // Final colour at a destination pixel unsigned char *dst; // Destination image - must be allocated here! int x,y; // Coordinates on destination image double fx,fy; // Corresponding coordinates on source image double dx,dy; // Fractional component of source image coordinates dst=(unsigned char *)calloc(dest_x*dest_y*3,sizeof(unsigned char)); // Allocate and clear destination image if (!dst) return(NULL); // Unable to allocate image step_x=(double)(src_x-1)/(double)(dest_x-1); step_y=(double)(src_y-1)/(double)(dest_y-1); for (x=0;x<dest_x;x++) // Loop over destination image for (y=0;y<dest_y;y++) { fx=x*step_x; fy=y*step_y; dx=fx-(int)fx; dy=fy-(int)fy; getPixel(src,floor(fx),floor(fy),src_x,&R1,&G1,&B1); // get N1 colours getPixel(src,ceil(fx),floor(fy),src_x,&R2,&G2,&B2); // get N2 colours getPixel(src,floor(fx),ceil(fy),src_x,&R3,&G3,&B3); // get N3 colours getPixel(src,ceil(fx),ceil(fy),src_x,&R4,&G4,&B4); // get N4 colours // Interpolate to get T1 and T2 colours RT1=(dx*R2)+(1-dx)*R1; GT1=(dx*G2)+(1-dx)*G1; BT1=(dx*B2)+(1-dx)*B1; RT2=(dx*R4)+(1-dx)*R3; GT2=(dx*G4)+(1-dx)*G3; BT2=(dx*B4)+(1-dx)*B3; // Obtain final colour by interpolating between T1 and T2 R=(unsigned char)((dy*RT2)+((1-dy)*RT1)); G=(unsigned char)((dy*GT2)+((1-dy)*GT1)); B=(unsigned char)((dy*BT2)+((1-dy)*BT1)); // Store the final colour setPixel(dst,x,y,dest_x,R,G,B); } return(dst); }
//void rotate(double radians, struct IMAGE* source, struct IMAGE* target, double* trigonometryCache, int trigonometryCacheBaseSize) { void rotate(double radians, struct IMAGE* source, struct IMAGE* target) { const int w = source->width; const int h = source->height; const int halfX = (w-1)/2; const int halfY = (h-1)/2; const int midX = w/2; const int midY = h/2; const int midMax = max(midX,midY); // create 2D rotation matrix const float sinval = sinf(radians); const float cosval = cosf(radians); const float m11 = cosval; const float m12 = sinval; const float m21 = -sinval; const float m22 = cosval; // step through all pixels of the target image, // symmetrically in all four quadrants to reduce trigonometric calculations int dX; int dY; for (dY = 0; dY <= midMax; dY++) { for (dX = 0; dX <= midMax; dX++) { // matrix multiplication to get rotated pixel pos (as in quadrant I) const int diffX = dX * m11 + dY * m21; const int diffY = dX * m12 + dY * m22; int x; int y; // quadrant I x = midX + dX; y = midY - dY; if ((x < w) && (y >= 0)) { const int oldX = midX + diffX; const int oldY = midY - diffY; const int pixel = getPixel(oldX, oldY, source); setPixel(pixel, x, y, target); } // quadrant II x = halfX - dY; y = midY - dX; if ((x >=0) && (y >= 0)) { const int oldX = halfX - diffY; const int oldY = midY - diffX; const int pixel = getPixel(oldX, oldY, source); setPixel(pixel, x, y, target); } // quadrant III x = halfX - dX; y = halfY + dY; if ((x >=0) && (y < h)) { const int oldX = halfX - diffX; const int oldY = halfY + diffY; const int pixel = getPixel(oldX, oldY, source); setPixel(pixel, x, y, target); } // quadrant IV x = midX + dY; y = halfY + dX; if ((x < w) && (y < h)) { const int oldX = midX + diffY; const int oldY = halfY + diffX; const int pixel = getPixel(oldX, oldY, source); setPixel(pixel, x, y, target); } } } }