Resource* BmpALoader(const std::string& resName) { std::string img = resName.substr(0, resName.size() - 1); std::string alpha = GetFileNoExt(img) + "-a.bmp"; unsigned int w = 0; unsigned int h = 0; unsigned char* rgbdata = LoadDIBitmap(img.c_str(), &w, &h); if (!rgbdata) { //? ReportError("Failed to load texture " + img); return 0; } // Add space for alpha unsigned char* withAlpha = AddAlpha(rgbdata, w, h); Assert(withAlpha); delete [] rgbdata; rgbdata = 0; // Load alpha image unsigned int aw = 0; unsigned int ah = 0; unsigned char* alphadata = LoadDIBitmap(alpha.c_str(), &aw, &ah); Assert(alphadata); Assert(aw == w); Assert(ah == h); // Copy alpha image to alpha channel of RGB image CopyAlpha(alphadata, withAlpha, w, h); delete [] alphadata; alphadata = 0; Texture* pTex = new Texture; pTex->Create(withAlpha, w, h, 4); // 4 bytes per pixel delete [] withAlpha; return (Resource*)pTex; }
int DilateFile(const char *pFileName) { png_t Png; CPixel *pBuffer[3] = {0,0,0}; png_init(0, 0); png_open_file(&Png, pFileName); if(Png.color_type != PNG_TRUECOLOR_ALPHA) { dbg_msg("dilate", "%s: not an RGBA image", pFileName); return 1; } pBuffer[0] = (CPixel*)mem_alloc(Png.width*Png.height*sizeof(CPixel), 1); pBuffer[1] = (CPixel*)mem_alloc(Png.width*Png.height*sizeof(CPixel), 1); pBuffer[2] = (CPixel*)mem_alloc(Png.width*Png.height*sizeof(CPixel), 1); png_get_data(&Png, (unsigned char *)pBuffer[0]); png_close_file(&Png); int w = Png.width; int h = Png.height; Dilate(w, h, pBuffer[0], pBuffer[1]); for(int i = 0; i < 5; i++) { Dilate(w, h, pBuffer[1], pBuffer[2]); Dilate(w, h, pBuffer[2], pBuffer[1]); } CopyAlpha(w, h, pBuffer[0], pBuffer[1]); // save here png_open_file_write(&Png, pFileName); png_set_data(&Png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pBuffer[1]); png_close_file(&Png); return 0; }
void CLinuxRenderer::DrawAlpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) { // OSD is drawn after draw_slice / put_image // this means that the buffer has already been handed off to the RGB converter // solution: have separate OSD textures // if it's down the bottom, use sub alpha blending // m_SubsOnOSD = (y0 > (int)(rs.bottom - rs.top) * 4 / 5); //Sometimes happens when switching between fullscreen and small window if( w == 0 || h == 0 ) { CLog::Log(LOGINFO, "Zero dimensions specified to DrawAlpha, skipping"); return; } //use temporary rect for calculation to avoid messing with module-rect while other functions might be using it. DRAWRECT osdRect; RESOLUTION res = GetResolution(); if (w > m_iOSDTextureWidth) { //delete osdtextures so they will be recreated with the correct width for (int i = 0; i < 2; ++i) { DeleteOSDTextures(i); } m_iOSDTextureWidth = w; } else { // clip to buffer if (w > m_iOSDTextureWidth) w = m_iOSDTextureWidth; if (h > g_settings.m_ResInfo[res].Overscan.bottom - g_settings.m_ResInfo[res].Overscan.top) { h = g_settings.m_ResInfo[res].Overscan.bottom - g_settings.m_ResInfo[res].Overscan.top; } } // scale to fit screen const RECT& rv = g_graphicsContext.GetViewWindow(); // Vobsubs are defined to be 720 wide. // NOTE: This will not work nicely if we are allowing mplayer to render text based subs // as it'll want to render within the pixel width it is outputting. float xscale; float yscale; if(true /*isvobsub*/) // xbox_video.cpp is fixed to 720x576 osd, so this should be fine { // vobsubs are given to us unscaled // scale them up to the full output, assuming vobsubs have same // pixel aspect ratio as the movie, and are 720 pixels wide float pixelaspect = m_fSourceFrameRatio * m_iSourceHeight / m_iSourceWidth; xscale = (rv.right - rv.left) / 720.0f; yscale = xscale * g_settings.m_ResInfo[res].fPixelRatio / pixelaspect; } else { // text subs/osd assume square pixels, but will render to full size of view window // if mplayer could be fixed to use monitorpixelaspect when rendering it's osd // this would give perfect output, however monitorpixelaspect currently doesn't work // that way xscale = 1.0f; yscale = 1.0f; } // horizontal centering, and align to bottom of subtitles line osdRect.left = (float)rv.left + (float)(rv.right - rv.left - (float)w * xscale) / 2.0f; osdRect.right = osdRect.left + (float)w * xscale; float relbottom = ((float)(g_settings.m_ResInfo[res].iSubtitles - g_settings.m_ResInfo[res].Overscan.top)) / (g_settings.m_ResInfo[res].Overscan.bottom - g_settings.m_ResInfo[res].Overscan.top); osdRect.bottom = (float)rv.top + (float)(rv.bottom - rv.top) * relbottom; osdRect.top = osdRect.bottom - (float)h * yscale; int iOSDBuffer = (m_iOSDRenderBuffer + 1) % m_NumOSDBuffers; //if new height is heigher than current osd-texture height, recreate the textures with new height. if (h > m_iOSDTextureHeight[iOSDBuffer]) { CSingleLock lock(g_graphicsContext); DeleteOSDTextures(iOSDBuffer); m_iOSDTextureHeight[iOSDBuffer] = h; // Create osd textures for this buffer with new size #if defined(HAS_SDL_OPENGL) m_pOSDYTexture[iOSDBuffer] = new CGLTexture(SDL_CreateRGBSurface(SDL_HWSURFACE, m_iOSDTextureWidth, m_iOSDTextureHeight[iOSDBuffer], 32, RMASK, GMASK, BMASK, AMASK),false,true); m_pOSDATexture[iOSDBuffer] = new CGLTexture(SDL_CreateRGBSurface(SDL_HWSURFACE, m_iOSDTextureWidth, m_iOSDTextureHeight[iOSDBuffer], 32, RMASK, GMASK, BMASK, AMASK),false,true); if (m_pOSDYTexture[iOSDBuffer] == NULL || m_pOSDATexture[iOSDBuffer] == NULL) #else m_pOSDYTexture[iOSDBuffer] = SDL_CreateRGBSurface(SDL_HWSURFACE, m_iOSDTextureWidth, m_iOSDTextureHeight[iOSDBuffer], 32, RMASK, GMASK, BMASK, AMASK); m_pOSDATexture[iOSDBuffer] = SDL_CreateRGBSurface(SDL_HWSURFACE, m_iOSDTextureWidth, m_iOSDTextureHeight[iOSDBuffer], 32, RMASK, GMASK, BMASK, AMASK); if (m_pOSDYTexture[iOSDBuffer] == NULL || m_pOSDATexture[iOSDBuffer] == NULL) #endif { CLog::Log(LOGERROR, "Could not create OSD/Sub textures"); DeleteOSDTextures(iOSDBuffer); return; } else { CLog::Log(LOGDEBUG, "Created OSD textures (%i)", iOSDBuffer); } } //We know the resources have been used at this point (or they are the second buffer, wich means they aren't in use anyways) //reset these so the gpu doesn't try to block on these #if defined(HAS_SDL_OPENGL) int textureBytesSize = m_pOSDYTexture[iOSDBuffer]->textureWidth * m_pOSDYTexture[iOSDBuffer]->textureHeight * 4; unsigned char *dst = new unsigned char[textureBytesSize]; unsigned char *dsta = new unsigned char[textureBytesSize]; //clear the textures memset(dst, 0, textureBytesSize); memset(dsta, 0, textureBytesSize); //draw the osd/subs int dstPitch = m_pOSDYTexture[iOSDBuffer]->textureWidth * 4; CopyAlpha(w, h, src, srca, stride, dst, dsta, dstPitch); m_pOSDYTexture[iOSDBuffer]->Update(m_pOSDYTexture[iOSDBuffer]->textureWidth, m_pOSDYTexture[iOSDBuffer]->textureHeight, dstPitch, dst, false); m_pOSDATexture[iOSDBuffer]->Update(m_pOSDATexture[iOSDBuffer]->textureWidth, m_pOSDATexture[iOSDBuffer]->textureHeight, dstPitch, dst, false); delete [] dst; delete [] dsta; #else if (SDL_LockSurface(m_pOSDYTexture[iOSDBuffer]) == 0 && SDL_LockSurface(m_pOSDATexture[iOSDBuffer]) == 0) { //clear the textures memset(m_pOSDYTexture[iOSDBuffer]->pixels, 0, m_pOSDYTexture[iOSDBuffer]->pitch*m_iOSDTextureHeight[iOSDBuffer]); memset(m_pOSDATexture[iOSDBuffer]->pixels, 0, m_pOSDATexture[iOSDBuffer]->pitch*m_iOSDTextureHeight[iOSDBuffer]); //draw the osd/subs CopyAlpha(w, h, src, srca, stride, (BYTE*)m_pOSDYTexture[iOSDBuffer]->pixels, (BYTE*)m_pOSDATexture[iOSDBuffer]->pixels, m_pOSDYTexture[iOSDBuffer]->pitch); } SDL_UnlockSurface(m_pOSDYTexture[iOSDBuffer]); SDL_UnlockSurface(m_pOSDATexture[iOSDBuffer]); #endif //set module variables to calculated values m_OSDRect = osdRect; m_OSDWidth = (float)w; m_OSDHeight = (float)h; m_OSDRendered = true; }
void CWinRenderer::DrawAlpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) { // OSD is drawn after draw_slice / put_image // this means that the buffer has already been handed off to the RGB converter // solution: have separate OSD textures // if it's down the bottom, use sub alpha blending // m_SubsOnOSD = (y0 > (int)(rs.bottom - rs.top) * 4 / 5); //Sometimes happens when switching between fullscreen and small window if( w == 0 || h == 0 ) { CLog::Log(LOGINFO, "Zero dimensions specified to DrawAlpha, skipping"); return; } //use temporary rect for calculation to avoid messing with module-rect while other functions might be using it. DRAWRECT osdRect; RESOLUTION res = GetResolution(); if (w > m_iOSDTextureWidth) { //delete osdtextures so they will be recreated with the correct width for (int i = 0; i < 2; ++i) { DeleteOSDTextures(i); } m_iOSDTextureWidth = w; } else { // clip to buffer if (w > m_iOSDTextureWidth) w = m_iOSDTextureWidth; if (h > g_settings.m_ResInfo[res].Overscan.bottom - g_settings.m_ResInfo[res].Overscan.top) { h = g_settings.m_ResInfo[res].Overscan.bottom - g_settings.m_ResInfo[res].Overscan.top; } } // scale to fit screen const RECT& rv = g_graphicsContext.GetViewWindow(); // Vobsubs are defined to be 720 wide. // NOTE: This will not work nicely if we are allowing mplayer to render text based subs // as it'll want to render within the pixel width it is outputting. float xscale; float yscale; if(true /*isvobsub*/) // xbox_video.cpp is fixed to 720x576 osd, so this should be fine { // vobsubs are given to us unscaled // scale them up to the full output, assuming vobsubs have same // pixel aspect ratio as the movie, and are 720 pixels wide float pixelaspect = m_fSourceFrameRatio * m_iSourceHeight / m_iSourceWidth; xscale = (rv.right - rv.left) / 720.0f; yscale = xscale * g_settings.m_ResInfo[res].fPixelRatio / pixelaspect; } else { // text subs/osd assume square pixels, but will render to full size of view window // if mplayer could be fixed to use monitorpixelaspect when rendering it's osd // this would give perfect output, however monitorpixelaspect currently doesn't work // that way xscale = 1.0f; yscale = 1.0f; } // horizontal centering, and align to bottom of subtitles line osdRect.left = (float)rv.left + (float)(rv.right - rv.left - (float)w * xscale) / 2.0f; osdRect.right = osdRect.left + (float)w * xscale; float relbottom = ((float)(g_settings.m_ResInfo[res].iSubtitles - g_settings.m_ResInfo[res].Overscan.top)) / (g_settings.m_ResInfo[res].Overscan.bottom - g_settings.m_ResInfo[res].Overscan.top); osdRect.bottom = (float)rv.top + (float)(rv.bottom - rv.top) * relbottom; osdRect.top = osdRect.bottom - (float)h * yscale; RECT rc = { 0, 0, w, h }; int iOSDBuffer = (m_iOSDRenderBuffer + 1) % m_NumOSDBuffers; //if new height is heigher than current osd-texture height, recreate the textures with new height. if (h > m_iOSDTextureHeight[iOSDBuffer]) { CSingleLock lock(g_graphicsContext); DeleteOSDTextures(iOSDBuffer); m_iOSDTextureHeight[iOSDBuffer] = h; // Create osd textures for this buffer with new size if ( D3D_OK != m_pD3DDevice->CreateTexture(m_iOSDTextureWidth, m_iOSDTextureHeight[iOSDBuffer], 1, 0, D3DFMT_LIN_L8, D3DPOOL_DEFAULT, &m_pOSDYTexture[iOSDBuffer]) || D3D_OK != m_pD3DDevice->CreateTexture(m_iOSDTextureWidth, m_iOSDTextureHeight[iOSDBuffer], 1, 0, D3DFMT_LIN_A8, D3DPOOL_DEFAULT, &m_pOSDATexture[iOSDBuffer]) ) { CLog::Log(LOGERROR, "Could not create OSD/Sub textures"); DeleteOSDTextures(iOSDBuffer); return; } else { CLog::Log(LOGDEBUG, "Created OSD textures (%i)", iOSDBuffer); } } // draw textures D3DLOCKED_RECT lr, lra; if ( (D3D_OK == m_pOSDYTexture[iOSDBuffer]->LockRect(0, &lr, &rc, 0)) && (D3D_OK == m_pOSDATexture[iOSDBuffer]->LockRect(0, &lra, &rc, 0)) ) { //clear the textures memset(lr.pBits, 0, lr.Pitch*m_iOSDTextureHeight[iOSDBuffer]); memset(lra.pBits, 0, lra.Pitch*m_iOSDTextureHeight[iOSDBuffer]); //draw the osd/subs CopyAlpha(w, h, src, srca, stride, (BYTE*)lr.pBits, (BYTE*)lra.pBits, lr.Pitch); } m_pOSDYTexture[iOSDBuffer]->UnlockRect(0); m_pOSDATexture[iOSDBuffer]->UnlockRect(0); //set module variables to calculated values m_OSDRect = osdRect; m_OSDWidth = (float)w; m_OSDHeight = (float)h; m_OSDRendered = true; }