/* Separated graphs mode */ void drwSepgraphs(unsigned long* hist, unsigned mIn, unsigned mOut, unsigned size, unsigned long long rx_max, unsigned long long tx_max) { unsigned int k, msize, txlev, rxlev, center, rxBpp, txBpp; msize = (unsigned)((double)size / 2); rxBpp = getBpp(msize, rx_max); txBpp = getBpp(msize, tx_max); for(k = 0; k < 58; k++) { rxlev = hist[mIn] / rxBpp; txlev = hist[mOut] / txBpp; trunc_normal(msize, &rxlev, &txlev); center = 53 - msize; copy_xpm_area(65, 0, 1, size, k + 3, 53 - size); copy_xpm_area(66, 0, 1, txlev, k + 3, center - txlev); copy_xpm_area(67, 0, 1, rxlev, k + 3, 53 - rxlev); hist += 4; } copy_xpm_area(70, 1, 58, 1, 3, 53 - size); copy_xpm_area(70, 0, 58, 1, 3, 53 - msize); }
/* SImage::getPixel * Returns the palette index of the pixel at [x,y] in the image, or * 0 if the position is out of bounds or the image is not paletted *******************************************************************/ uint8_t SImage::getPixelIndex(unsigned x, unsigned y) { // Get pixel index unsigned index = y * getStride() + x * getBpp(); // Check it if (index >= unsigned(width*height*getBpp()) || type == RGBA) return 0; return data[index]; }
/* Twisted mode */ void drwTwisted(unsigned long* hist, unsigned mIn, unsigned mOut, unsigned size, unsigned long long rx_max, unsigned long long tx_max) { unsigned int k, stpos, itn, txlev, rxlev; int bpp = getBpp(29, MAX(tx_max, rx_max)); stpos = 53 - size; itn = 53 - stpos; hist += 4 * (58-itn); for(k = 0; k < itn; k++) { rxlev = hist[mIn] / bpp; txlev = hist[mOut] / bpp; trunc_normal(29, &rxlev, &txlev); /* Tx on the right, flowing up */ copy_xpm_area(70, 3, 29, 1, 32, stpos + k); if (txlev) copy_xpm_area(70, 4, txlev, 1, 32 + (29-txlev)/2, stpos + k) else copy_xpm_area(70, 0, 1, 1, 46, stpos + k); /* Rx on the left, flowing down */ copy_xpm_area(70, 3, 29, 1, 3, 52 - k); if (rxlev) copy_xpm_area(70, 5, rxlev, 1, 3 + (29 - rxlev) / 2, 52 - k) else copy_xpm_area(70, 0, 1, 1, 17, 52 - k); hist += 4; } copy_xpm_area(70, 1, 58, 1, 3, 53 - size); }
/* Wmnet like modeness */ void drwWmnet(unsigned long* hist, unsigned mIn, unsigned mOut, unsigned size, unsigned long long rx_max, unsigned long long tx_max) { unsigned int k, txlev, rxlev, nolev; int bpp = getBpp(size, rx_max + tx_max); for(k = 0; k < 58; k++) { rxlev = hist[mIn] / bpp; txlev = hist[mOut] / bpp; trunc_normal(size, &rxlev, &txlev); /* handle overlap, smaller in front */ if((rxlev + txlev) > size) { if(rxlev > txlev) rxlev = size - txlev; else txlev = size - rxlev; } nolev = size - (rxlev + txlev); copy_xpm_area(66, 0, 1, txlev, k + 3, 53 - size); copy_xpm_area(65, 0, 1, nolev, k + 3, (53 - size) + txlev); copy_xpm_area(67, 0, 1, rxlev, k + 3, 53 - rxlev); hist += 4; } copy_xpm_area(70, 1, 58, 1, 3, 53 - size); }
/* lines mode */ void drwLines(unsigned long* hist, unsigned mIn, unsigned mOut, unsigned size, unsigned long long rx_max, unsigned long long tx_max) { unsigned int k, oTxlev, oRxlev, txlev, rxlev; int bpp = getBpp(size - 2, MAX(tx_max, rx_max)); static int gcinit = 0; static GC gcs[2]; /* gc initialization */ if (!gcinit) { XGCValues gcval; gcval.foreground = dockapp.stdColors.txColor; gcval.graphics_exposures = False; gcs[0] = XCreateGC(dockapp.d, dockapp.pixmap, GCForeground | GCGraphicsExposures, &gcval); gcval.foreground = dockapp.stdColors.rxColor; gcs[1] = XCreateGC(dockapp.d, dockapp.pixmap, GCForeground | GCGraphicsExposures, &gcval); gcinit = 1; } /* fake old values */ oRxlev = hist[mIn] / bpp; oTxlev = hist[mOut] / bpp; trunc_normal(size - 2, &oRxlev, &oTxlev); for(k = 0; k < 58; k++) { rxlev = hist[mIn] / bpp; txlev = hist[mOut] / bpp; trunc_normal(size - 2, &rxlev, &txlev); /* clear the area */ copy_xpm_area(65, 0, 1, size, k + 3, 53 - size); /* tx and rx */ XDrawLine(dockapp.d, dockapp.pixmap, gcs[0], k + 3, 52 - oTxlev, k + 3, 52 - txlev); XDrawLine(dockapp.d, dockapp.pixmap, gcs[1], k + 3, 52 - oRxlev, k + 3, 52 - rxlev); /* advance */ hist += 4; oTxlev = txlev; oRxlev = rxlev; } copy_xpm_area(70, 1, 58, 1, 3, 53 - size); }
/* SImage::copyImage * Copies all data and properties from [image] *******************************************************************/ bool SImage::copyImage(SImage* image) { // Check image was given if (!image) return false; // Clear current data clearData(); // Copy image properties width = image->width; height = image->height; type = image->type; palette.copyPalette(&image->palette); has_palette = image->has_palette; offset_x = image->offset_x; offset_y = image->offset_y; imgindex = image->imgindex; numimages = image->numimages; // Copy image data if (image->data) { data = new uint8_t[width*height*getBpp()]; memcpy(data, image->data, width*height*getBpp()); } if (image->mask) { mask = new uint8_t[width*height]; memcpy(mask, image->mask, width*height); } // Announce change announce("image_changed"); return true; }
/* SImage::getPixel * Returns the colour of the pixel at [x,y] in the image, or black+ * invisible if out of range *******************************************************************/ rgba_t SImage::getPixel(unsigned x, unsigned y, Palette8bit* pal) { // Get pixel index unsigned index = y * getStride() + x * getBpp(); // Check it if (index >= unsigned(width*height*getBpp())) return rgba_t(0, 0, 0, 0); // Get colour at pixel rgba_t col; if (type == RGBA) { col.r = data[index]; col.g = data[index+1]; col.b = data[index+2]; col.a = data[index+3]; } else if (type == PALMASK) { // Get palette to use if (has_palette || !pal) pal = &palette; col.set(pal->colour(data[index])); } else if (type == ALPHAMAP) { col.r = data[index]; col.g = data[index]; col.b = data[index]; col.a = data[index]; } return col; }
/* Traditional mode */ void drwTraditional(unsigned long* hist, unsigned mIn, unsigned mOut, unsigned size, unsigned long long rx_max, unsigned long long tx_max) { unsigned int k, txlev, rxlev, nolev; int bpp = getBpp(size, rx_max + tx_max); for(k = 0; k < 58; k++) { rxlev = hist[mIn] / bpp; txlev = hist[mOut] / bpp; trunc_stacked(size, &rxlev, &txlev); nolev = (rxlev + txlev); copy_xpm_area(66, 0, 1, txlev, k + 3, 53 - nolev); copy_xpm_area(65, 0, 1, size - nolev, k + 3, 53 - size); copy_xpm_area(67, 0, 1, rxlev, k + 3, 53 - rxlev); hist += 4; } copy_xpm_area(70, 1, 58, 1, 3, 53 - size); }
/** * Sets the alpha value of all pixels of the specified color to transparent. This is know as "color key". Returns 0 if * there is no image loaded. * If you call this method on an image not having 32 bpp and ::IND_RGBA format, it will be converted first to that format. * It is recommended that you use this method with IND_RGBA color format images and 32 bpp. * The method returns true if image could be converted and alpha channel set correctly, false otherwise. * @param pR Byte R (Red). * @param pG Byte G (Green). * @param pB Byte B (Blue). */ bool IND_Image::setAlpha(BYTE pR, BYTE pG, BYTE pB) { // No image loaded if (!isImageLoaded() || !FreeImage_HasPixels(getFreeImageHandle())) return false; bool success = true; // We add alpha channel if the image hasn't. if (getFormatInt() != IND_RGBA) { int targetbpp (32); if (IND_RGB == getFormatInt()) { targetbpp = (getBpp()* 4 )/ 3; } success = convert(IND_RGBA,targetbpp); } if (success) { setAlphaChannel(pR, pG, pB); } return success; }
/* MGraph mode */ void drwMGraph(unsigned long* hist, unsigned mIn, unsigned mOut, unsigned size, unsigned long long rx_max, unsigned long long tx_max) { /* max scale */ unsigned int k, txlev, rxlev; int bpp = getBpp(size, MAX(tx_max, rx_max)); /* process the whole history */ for(k = 0; k < 58; ++k) { rxlev = hist[mIn] / bpp; txlev = hist[mOut] / bpp; trunc_normal(size, &rxlev, &txlev); /* clear the top area */ copy_xpm_area(65, 0, 1, size - MAX(rxlev, txlev), k + 3, 53 - size); /* draw the tx/rx bars */ if(rxlev > txlev) { /* rx is major */ copy_xpm_area(67, 0, 1, rxlev - txlev, k + 3, 53 - rxlev); copy_xpm_area(66, 0, 1, txlev, k + 3, 53 - txlev); } else { /* tx is major */ copy_xpm_area(66, 0, 1, txlev - rxlev, k + 3, 53 - txlev); copy_xpm_area(67, 0, 1, rxlev, k + 3, 53 - rxlev); } /* advance */ hist += 4; } copy_xpm_area(70, 1, 58, 1, 3, 53 - size); }
/* SImage::colourise * Colourises the image to [colour]. If the image is paletted, each * pixel will be set to its nearest matching colour in [pal] *******************************************************************/ bool SImage::colourise(rgba_t colour, Palette8bit* pal) { // Can't do this with alpha maps if (type == ALPHAMAP) return false; // Get palette to use if (has_palette || !pal) pal = &palette; // Go through all pixels uint8_t bpp = getBpp(); rgba_t col; for (int a = 0; a < width*height*bpp; a+= bpp) { // Get current pixel colour if (type == RGBA) col.set(data[a], data[a+1], data[a+2], data[a+3]); else col.set(pal->colour(data[a])); // Colourise it float grey = (col.r*col_greyscale_r + col.g*col_greyscale_g + col.b*col_greyscale_b) / 255.0f; if (grey > 1.0) grey = 1.0; col.r = colour.r*grey; col.g = colour.g*grey; col.b = colour.b*grey; // Set pixel colour if (type == RGBA) col.write(data+a); else data[a] = pal->nearestColour(col); } return true; }
/* Waveform mode */ void drwWaveform(unsigned long* hist, unsigned mIn, unsigned mOut, unsigned size, unsigned long long rx_max, unsigned long long tx_max) { unsigned int k, txlev, rxlev, center; int bpp = getBpp(size, rx_max + tx_max); for(k = 0; k < 58; k++) { rxlev = hist[mIn] / bpp / 2; txlev = hist[mOut] / bpp / 2; trunc_stacked(size / 2, &rxlev, &txlev); center = 53 - size / 2; copy_xpm_area(65, 0, 1, size, k + 3, 53 - size); copy_xpm_area(66, 0, 1, txlev, k + 3, (center - rxlev) - txlev); copy_xpm_area(66, 0, 1, txlev, k + 3, (center + rxlev)); copy_xpm_area(67, 0, 1, rxlev * 2, k + 3, center - rxlev); hist += 4; } copy_xpm_area(70, 1, 58, 1, 3, 53 - size); copy_xpm_area(70, 0, 58, 1, 3, 53 - size / 2); }
/* SImage::tint * Tints the image to [colour] by [amount]. If the image is paletted, * each pixel will be set to its nearest matching colour in [pal] *******************************************************************/ bool SImage::tint(rgba_t colour, float amount, Palette8bit* pal) { // Can't do this with alpha maps if (type == ALPHAMAP) return false; // Get palette to use if (has_palette || !pal) pal = &palette; // Go through all pixels uint8_t bpp = getBpp(); rgba_t col; for (int a = 0; a < width*height*bpp; a+= bpp) { // Get current pixel colour if (type == RGBA) col.set(data[a], data[a+1], data[a+2], data[a+3]); else col.set(pal->colour(data[a])); // Tint it float inv_amt = 1.0f - amount; col.set(col.r*inv_amt + colour.r*amount, col.g*inv_amt + colour.g*amount, col.b*inv_amt + colour.b*amount, col.a); // Set pixel colour if (type == RGBA) col.write(data+a); else data[a] = pal->nearestColour(col); } return true; }
int main( int argc, char **argv ) { int dispDev, csiDev; int chunkMem; chunk_block_t priBlk0, priBlk1; gp_disp_res_t panelRes; gp_bitmap_t priBitmap; UINT16 *data; fd_set fds; struct timeval tv; int r, bufnum; struct v4l2_buffer buf; struct v4l2_format fmt; struct v4l2_queryctrl qc; struct v4l2_input in; spRect_t dstRect={0,0,0,0}; spRect_t srcRect={0,0,0,0}; spBitmap_t dst; spBitmap_t src; /* Opening the device dispDev */ dispDev = open("/dev/disp0",O_RDWR); printf("dispDev = %d\n", dispDev); ioctl(dispDev, DISPIO_SET_INITIAL, 0); ioctl(dispDev, DISPIO_GET_PANEL_RESOLUTION, &panelRes); dstRect.width = panelRes.width; dstRect.height=panelRes.height; srcRect.width=NTSC_WIDTH; srcRect.height=NTSC_HEIGHT; /* Opening /dev/chunkmem */ chunkMem = open("/dev/chunkmem", O_RDWR); /* Allocate primary frame buffer */ priBlk0.size = (NTSC_WIDTH) * (NTSC_HEIGHT) * getBpp(SP_BITMAP_YCbYCr); priBlk1.size = (panelRes.width) * (panelRes.height) *getBpp(SP_BITMAP_YCbYCr); ioctl(chunkMem, CHUNK_MEM_ALLOC, (unsigned long)&priBlk0); ioctl(chunkMem, CHUNK_MEM_ALLOC, (unsigned long)&priBlk1); dst.width = panelRes.width; dst.height = panelRes.height; dst.bpl = panelRes.width * getBpp(SP_BITMAP_YCbYCr); dst.pData = priBlk1.addr; dst.type = SP_BITMAP_YCbYCr; src.width = NTSC_WIDTH; src.height =NTSC_HEIGHT; src.bpl = NTSC_WIDTH *getBpp(SP_BITMAP_YCbYCr); src.pData = priBlk0.addr; src.type = SP_BITMAP_YCbYCr; //gp2dScale(&dst, dstRect, &src, srcRect); /* Set primary layer bitmap */ priBitmap.width = panelRes.width; priBitmap.height = panelRes.height; priBitmap.bpl = panelRes.width*getBpp(SP_BITMAP_YCbYCr); priBitmap.type = SP_BITMAP_YCbYCr; priBitmap.pData = priBlk1.addr; ioctl(dispDev, DISPIO_SET_PRI_BITMAP, &priBitmap); /* Fill primary bitmap data */ #if 0 data = (UINT16*) priBlk0.addr; init_fb(data, 0x0000, 0x001f, 0x0513, 0xffff); data = (UINT16*) priBlk1.addr; init_fb(data, 0xffff, 0x0513, 0x001f, 0x0000); #endif ioctl(dispDev, DISPIO_SET_PRI_ENABLE, 1); ioctl(dispDev, DISPIO_SET_UPDATE, 0); csiDev = open("/dev/csi0",O_RDWR); in.index = 0; ioctl(csiDev, VIDIOC_ENUMINPUT, &in); printf("name=%s\n", in.name); CLEAR(fmt); fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; fmt.fmt.pix.width = NTSC_WIDTH; fmt.fmt.pix.height = NTSC_HEIGHT; ioctl(csiDev, VIDIOC_TRY_FMT, &fmt); CLEAR(qc); qc.id = V4L2_CID_BRIGHTNESS; ioctl(csiDev, VIDIOC_QUERYCTRL, &qc); printf("max=%d\n", qc.maximum); init_userp(csiDev, 1); CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_USERPTR; buf.index = 0; buf.m.userptr = (unsigned long)priBlk0.addr; ioctl(csiDev, VIDIOC_QBUF, &buf); // buf.index = 1; // buf.m.userptr = (unsigned long)priBlk1.addr; // ioctl(csiDev, VIDIOC_QBUF, &buf); // buf.index = 2; // buf.m.userptr = (unsigned long)priBlk2.addr; // ioctl(csiDev, VIDIOC_QBUF, &buf); FD_ZERO (&fds); FD_SET (csiDev, &fds); tv.tv_sec = 2; tv.tv_usec = 0; ioctl(csiDev, VIDIOC_STREAMON, NULL); while(1) { r = select(csiDev+1, &fds, NULL, NULL, NULL);//&tv); gp2dScale(&dst, dstRect, &src, srcRect); CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_USERPTR; ioctl(csiDev, VIDIOC_DQBUF, &buf); ioctl(csiDev, VIDIOC_QBUF, &buf); /* ioctl(csiDev, 3, &bufnum); if( bufnum==0 ) priBitmap.pData = priBlk0.addr; else if(bufnum==1) priBitmap.pData = priBlk1.addr; else priBitmap.pData = priBlk2.addr; ioctl(dispDev, DISPIO_SET_PRI_BITMAP, &priBitmap); ioctl(dispDev, DISPIO_SET_PRI_ENABLE, 1); ioctl(dispDev, DISPIO_SET_UPDATE, 0); ioctl(dispDev, DISPIO_WAIT_FRAME_END, 0);*/ /* r = select(csiDev+1, &fds, NULL, NULL, &tv); priBitmap.pData = priBlk1.addr; ioctl(dispDev, DISPIO_SET_PRI_BITMAP, &priBitmap); ioctl(dispDev, DISPIO_SET_PRI_ENABLE, 1); ioctl(dispDev, DISPIO_SET_UPDATE, 0); r = select(csiDev+1, &fds, NULL, NULL, &tv); priBitmap.pData = priBlk2.addr; ioctl(dispDev, DISPIO_SET_PRI_BITMAP, &priBitmap); ioctl(dispDev, DISPIO_SET_PRI_ENABLE, 1); ioctl(dispDev, DISPIO_SET_UPDATE, 0);*/ } // close(dispDev); // ioctl(chunkMem, CHUNK_MEM_FREE, (unsigned long)&priBlk); // close(chunkMem); return 0; /* int i, ret; int fdcsi; struct v4l2_queryctrl qc; printf("csi test!\n"); fdcsi = open("/dev/csi0", O_RDWR); // init_userp(fdcsi, 0x2000); close(fdcsi); return 0;*/ }
SINT32 gp2dScale( spBitmap_t *pdstBitmap, spRect_t dstRect, spBitmap_t *psrcBitmap, spRect_t srcRect ) { scale_content_t sct; g2d_draw_ctx_t drawCtx; SINT32 handle = -1; SINT32 ret = SP_OK; /*!<scaling with scalar must need the follow conditions 1.size is not smaller than 16X16; 2.addr and pitch must 4 byte aligned if not use 2D to scale*/ if (CHECK_ALIGN(pdstBitmap->pData + dstRect.x * getBpp(pdstBitmap->type)) && (CHECK_ALIGN(dstRect.width * getBpp(pdstBitmap->type))) && (CHECK_ALIGN(psrcBitmap->pData + srcRect.x * getBpp(psrcBitmap->type))) && (CHECK_ALIGN(srcRect.width * getBpp(psrcBitmap->type))) && (CHECK_SIZE(dstRect.width)) && (CHECK_SIZE(dstRect.height)) && (CHECK_SIZE(srcRect.width)) && (CHECK_SIZE(srcRect.height))) /*if (0)*/{ /*!<use scalar to scale*/ //diagLog(DIAG_LVL_INFO, "Use /dev/scalar to do scale...\n"); handle = open("/dev/scalar", O_RDONLY); if (handle < 0) { diagLog(DIAG_LVL_ERROR, "open scale dev fail!\n"); return SP_FAIL; } memset(&sct, 0, sizeof(sct)); memcpy(&sct.dst_img, pdstBitmap, sizeof(spBitmap_t)); memcpy(&sct.scale_rgn, &dstRect, sizeof(spRect_t)); memcpy(&sct.src_img, psrcBitmap, sizeof(spBitmap_t)); memcpy(&sct.clip_rgn, &srcRect, sizeof(spRect_t)); if ((ret = ioctl(handle, SCALE_IOCTL_TRIGGER, &sct)) < 0) { diagLog(DIAG_LVL_ERROR, "do scale error occur!\n"); ret = SP_FAIL; goto _resourceCollection; } } else { /*!<use 2D to scale*/ //diagLog(DIAG_LVL_INFO, "Use /dev/graphic to do scale...\n"); handle = open(G2D_DEV_NAME, O_RDWR); if (handle < 0) { diagLog(DIAG_LVL_ERROR, "[%s:%s:%d] [%s] open fail!\n", __FILE__, __FUNCTION__, __LINE__, G2D_DEV_NAME); return SP_FAIL; } memset(&drawCtx, 0, sizeof(g2d_draw_ctx_t)); memcpy(&drawCtx.dst, pdstBitmap, sizeof(spBitmap_t)); memcpy(&drawCtx.dst_rect, &dstRect, sizeof(spRect_t)); memcpy(&drawCtx.src, psrcBitmap, sizeof(spBitmap_t)); memcpy(&drawCtx.src_rect, &srcRect, sizeof(spRect_t)); drawCtx.func_flag = G2D_FUNC_ROP | G2D_FUNC_SCALE; drawCtx.rop.fg_rop = G2D_ROP_SRCCOPY; ret = ioctl(handle, G2D_IOCTL_DRAW_BITMAP, &drawCtx); if (ret < 0) { diagLog(DIAG_LVL_ERROR, "[%s:%d]G2D_IOCTL_DRAW_BITMAP, errcode = 0x%x\n", __FUNCTION__, __LINE__, ret); ret = SP_FAIL; goto _resourceCollection; } } _resourceCollection: if (handle >= 0) { close(handle); } return ret; }
/* SImage::drawPixel * Draws a pixel of [colour] at [x],[y], blending it according to * the options set in [properties]. If the image is paletted, the * resulting pixel colour is converted to its nearest match in [pal] *******************************************************************/ bool SImage::drawPixel(int x, int y, rgba_t colour, si_drawprops_t& properties, Palette8bit* pal) { // Check valid coords if (x < 0 || y < 0 || x >= width || y >= height) return false; // Get palette to use if (has_palette || !pal) pal = &palette; // Setup alpha if (properties.src_alpha) colour.a *= properties.alpha; else colour.a = 255*properties.alpha; // Do nothing if completely transparent if (colour.a == 0) return true; // Get pixel index unsigned p = y * getStride() + x * getBpp(); // Check for simple case (normal blending, no transparency involved) if (colour.a == 255 && properties.blend == NORMAL) { if (type == RGBA) colour.write(data+p); else { data[p] = pal->nearestColour(colour); mask[p] = colour.a; } return true; } // Not-so-simple case, do full processing rgba_t d_colour; if (type == PALMASK) d_colour = pal->colour(data[p]); else d_colour.set(data[p], data[p+1], data[p+2], data[p+3]); // Additive blending if (properties.blend == ADD) { d_colour.set( MathStuff::clamp(d_colour.r+colour.r*properties.alpha, 0, 255), MathStuff::clamp(d_colour.g+colour.g*properties.alpha, 0, 255), MathStuff::clamp(d_colour.b+colour.b*properties.alpha, 0, 255), MathStuff::clamp(d_colour.a + colour.a, 0, 255)); } // Subtractive blending else if (properties.blend == SUBTRACT) { d_colour.set( MathStuff::clamp(d_colour.r-colour.r*properties.alpha, 0, 255), MathStuff::clamp(d_colour.g-colour.g*properties.alpha, 0, 255), MathStuff::clamp(d_colour.b-colour.b*properties.alpha, 0, 255), MathStuff::clamp(d_colour.a + colour.a, 0, 255)); } // Reverse-Subtractive blending else if (properties.blend == REVERSE_SUBTRACT) { d_colour.set( MathStuff::clamp((-d_colour.r)+colour.r*properties.alpha, 0, 255), MathStuff::clamp((-d_colour.g)+colour.g*properties.alpha, 0, 255), MathStuff::clamp((-d_colour.b)+colour.b*properties.alpha, 0, 255), MathStuff::clamp(d_colour.a + colour.a, 0, 255)); } // 'Modulate' blending else if (properties.blend == MODULATE) { d_colour.set( MathStuff::clamp(colour.r*d_colour.r / 255, 0, 255), MathStuff::clamp(colour.g*d_colour.g / 255, 0, 255), MathStuff::clamp(colour.b*d_colour.b / 255, 0, 255), MathStuff::clamp(d_colour.a + colour.a, 0, 255)); } // Normal blending (or unknown blend type) else { float inv_alpha = 1.0f - properties.alpha; d_colour.set( d_colour.r*inv_alpha + colour.r*properties.alpha, d_colour.g*inv_alpha + colour.g*properties.alpha, d_colour.b*inv_alpha + colour.b*properties.alpha, MathStuff::clamp(d_colour.a + colour.a, 0, 255)); } // Apply new colour if (type == PALMASK) { data[p] = pal->nearestColour(d_colour); mask[p] = d_colour.a; } else if (type == RGBA) d_colour.write(data+p); else if (type == ALPHAMAP) data[p] = d_colour.a; return true; }