Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

Teniendo un canvas, poner otro encima semitransparente.

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Consultas
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: Teniendo un canvas, poner otro encima semitransparente. Responder citando

Tengo un cavas, con una imagen cargada de un paisaje. Tengo otro canvas con un dibjujo de un logo.

Como puedo poner el logo enima del paisaje pero que se siga viendo el paisaje?, de forma semitransparente?.

he encontrado este codigo, pero no he encontrado un ejemplo, y la verdad no se por donde cojerlo... (por ejemplo, no se que es HDC)
Código:
void DrawSemiTransparentBitmap(HDC hDstDC, int x, int y, int nWidth, int nHeight, HDC hSrcDC, int xSrc, int ySrc)
   {
   HDC hdcCompatible = CreateCompatibleDC(hDstDC);
   HBITMAP hBmp = CreateCompatibleBitmap(hDstDC, nWidth, nHeight);
   HGDIOBJ hBitmapOld = SelectObject(hdcCompatible, hBmp);

   RECT rc = { 0, 0, nWidth, nHeight };
   HBRUSH hBrush = CreateSolidBrush(RGB(0x7F, 0x7F, 0x7F));
   FillRect(hdcCompatible, &rc, hBrush);
   DeleteObject(hBrush);

   BitBlt(hDstDC, x, y, nWidth, nHeight, hdcCompatible, 0, 0, SRCAND);

   SelectObject(hdcCompatible, hBitmapOld);
   DeleteObject(hBmp);
   DeleteDC(hdcCompatible);
   BitBlt(hDstDC, x, y, nWidth, nHeight, hSrcDC, 0, 0, SRCPAINT);
  }


Si a alguien le suena algo de esto, solo pido como teniendo dos canvas puedo llamar a esta función.

MUCHAS GRACIAS!!!!
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Tal como está a mi no me funciona..
Si quieres algo similar y que funciona prueba con la siguiente rutina:

Código:
void DrawSemiTransparentBitmap(HDC hDstDC, int x, int y, int nWidth,
        int nHeight, HDC hSrcDC, int xSrc, int ySrc, BYTE op=50)
{
    BLENDFUNCTION bf;
    ZeroMemory(&bf, sizeof(bf));
    bf.BlendOp = AC_SRC_OVER;
    bf.SourceConstantAlpha = MulDiv(op, 255, 100);
    AlphaBlend(hDstDC, x, y, nWidth, nHeight,
        hSrcDC, xSrc, ySrc, nWidth, nHeight, bf);
}

He mantenido los mismos argumentos, pero añadiendo un nuevo parámetro opcional donde le indicamos el porcentaje de opacidad.

IMPORTANTE: Para poder usar la función AlphaBlend del API tenemos que añadir "msimg32.lib" a nuestro proyecto. La podemos encontrar en el subdirectorio "\Lib\Psdk\" donde tengamos instalado nuestro BCB.

Y para probar la rutina podemos añadir 2 TImage, en el primero que usaremos como destino cargamos el paisaje y en el segundo el logo:

Código:
Image1->Picture->LoadFromFile("d:\\imagen.bmp");
Image2->Picture->LoadFromFile("d:\\logo.bmp");
DrawSemiTransparentBitmap(Image1->Canvas->Handle, 512, 10, 78, 118, Image2->Canvas->Handle, 0, 0);
Image1->Update();

               

Si miras más a fondo la función AlphaBlend veras que incluso te permitiría definir el nivel de transparencia de cada pixel..
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Bien... Responder citando

Hola,
muchas gracias por contestar, la verdad es que ya me funciona, pero solo con algunas imagines.

te pongo un ejemplo:
Código:
// Declaracion
Graphics::TBitmap *b = new Graphics::TBitmap();
b->PixelFormat=pf24bit;
b->Width=Screen->Width;
b->Height=Screen->Height;

Graphics::TBitmap *Rectangulo = new Graphics::TBitmap();
Rectangulo->PixelFormat=pf24bit;
Rectangulo->Width=100;
Rectangulo->Height=200;

// Se prepara un rectangulo azul
Rectangulo->Canvas->Brush->Color = clBlue;
Rectangulo->Canvas->FillRect(Rectangulo->Canvas->ClipRect);
Src=Rect(0,0,Rectangulo->Width,Rectangulo->Height);
Dest=Rect(200,200,300,400);

// se copia el rectangulo azul en b
b->Canvas->CopyRect(Dest, Rectangulo->Canvas, Src);

// se pega al 50% en b
SemiTransparent(b->Canvas->Handle, 20, 20, 300, 300, Rectangulo->Canvas->Handle, 0, 0, 50);


Al copiar con copyrect funciona bien, pero el Semitransparent no.
He estado probando con algunas fotos y si funcina, con otras no, por ejemplo si abro el paint y creo un dibujo tampoco me funciona, pero si cojo una foto si me deja.
Creo que va a ser problema de color o algo asi... en realidad no tengo mucha idea de por que sucede esto con algunas imagenes,
¿puede ser que haya que dar algún tipo de formato al canvas antes?

MUCHAS GRACIAS DE NUEVO!
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

En el caso del ejemplo que pones ocurre porque estas especificando un tamaño de imagen más grande que el tamaño real del bitmap de origen.

SemiTransparent(b->Canvas->Handle, 20, 20, 300, 300, Rectangulo->Canvas->Handle, 0, 0, 50);

Si cambiamos estos dos valores al tamaño máximo o menor de la imagen origen funciona..

Si quieres pegar siempre la imagen origen completa sobre la destino sin preocuparte del tamaño podriamos simplificar un poco la rutina:
Código:
void SemiTransparent(Graphics::TBitmap* dst, int x, int y,
        Graphics::TBitmap* src, BYTE op=50)
{
    BLENDFUNCTION bf;
    ZeroMemory(&bf, sizeof(bf));
    bf.BlendOp = AC_SRC_OVER;
    bf.SourceConstantAlpha = MulDiv(op, 255, 100);
    AlphaBlend(dst->Canvas->Handle, x, y, src->Width, src->Height,
        src->Canvas->Handle, 0, 0, src->Width, src->Height, bf);
}

Y la forma de usarla teniendo en cuenta tu ejemplo:
Código:
SemiTransparent(b, 20, 20, Rectangulo, 50);


De todas formas si aun con eso te sigue fallando y para localizar mejor el problema si quieres pásame un par de imágenes con las que te falle y el código que usas para cargarlas etc..

leosoftware ARROBA gmail PUNTO com
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

hola!

Gracias, tenias razón, era problema de tamaño, y gracias también por la nueva función, que es la que voy a utilizar, ya que voy a copiar las imagenes completas.


Si quiero poner texto SemiTransparente, como puedo utilizar esta misma función. Existe esa posibilidad?
Yo pego texto con borde de la siguiente manera, y me gustaria hacerlo dándole un nivel de transparencia:
Código:
SetBkMode(b->Canvas->Handle, TransparentColor);
  SetTextAlign(b->Canvas->Handle, TA_BASELINE);

  b->Canvas->Font = FontDialog1->Font;
  b->Canvas->Font->Size = 15;

  BeginPath(b->Canvas->Handle);
  b->Canvas->TextOut(100,100,Edit1->Text);
  EndPath(b->Canvas->Handle);

  b->Canvas->Brush->Color = clAqua;
  b->Canvas->Brush->Style = bsSolid;//bsDiagCross;   
  b->Canvas->Pen->Style   = psSolid;
  b->Canvas->Pen->Width   = 1;
  b->Canvas->Pen->Color   = clBlue;

  StrokeAndFillPath(b->Canvas->Handle);


Aviso a quien vaya a utilizar la función AlphaBlend:
si no os funciona hay que poner ::AlphaBlend
Y otra cosa, si tomais las imagenes de un TImage, este tiene que tener cargada un BMP, si no no funciona.

MUCHAS GRACIAS[/code]
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Podrías hacerlo usando la misma función, creas un bitmap en el que escribes el texto y lo vuelcas como con la anterior.. El único detalle diferente seria utilizar la posibilidad que nos da esta función para definir el nivel de transparencia de cada pixel individual, para así hacer totalmente invisible la parte exterior al texto...

A ver si te sirve esta función:
Código:
void SemiTransparentText(Graphics::TBitmap* dst, int x, int y,
        String text, String fontName, int fontSize, TColor color,
        BYTE op=50, int borderWidth=0, TColor borderColor=clNone)
{
    Graphics::TBitmap* bmp = new Graphics::TBitmap;
    bmp->PixelFormat = pf32bit;

    bmp->Canvas->Font->Name = fontName;
    bmp->Canvas->Font->Size = fontSize;
    bmp->Canvas->Brush->Color = color;
    bmp->Canvas->Pen->Width = borderWidth;
    bmp->Canvas->Pen->Color = borderColor;

    bmp->Width = bmp->Canvas->TextWidth(text);
    bmp->Height = bmp->Canvas->TextHeight(text);

    // Marcamos todo el fondo con un valor que nos sirve
    //  para saber los pixels que seran transparentes
    DWORD* ptr = (DWORD*)bmp->ScanLine[bmp->Height-1];
    for (int i=0; i <bmp>Height * bmp->Width; i++)
        ptr[i] = 0x11000000;

    BeginPath(bmp->Canvas->Handle);
    SetBkMode(bmp->Canvas->Handle, TRANSPARENT);
    bmp->Canvas->TextOut(0, 0, text);
    EndPath(bmp->Canvas->Handle);

    if (borderWidth)
        StrokeAndFillPath(bmp->Canvas->Handle);
    else
        FillPath(bmp->Canvas->Handle);

    // Modificamos el canal alfa del bitmap..
    ptr = (DWORD*)bmp->ScanLine[bmp->Height-1];
    for (int i=0; i <bmp>Height * bmp->Width; i++)
        ptr[i] = (ptr[i] & 0xFF000000) ? 0 : ptr[i] | 0xFF000000;

    // Volcamos el bitmap con el texto sobre el bitmap destino
    BLENDFUNCTION bf = {0, 0, MulDiv(op, 255, 100), AC_SRC_ALPHA};
    AlphaBlend(dst->Canvas->Handle, x, y, bmp->Width, bmp->Height,
        bmp->Canvas->Handle, 0, 0, bmp->Width, bmp->Height, bf);
}

Y unos ejemplos de uso:
- Con el borde blanco y el interior rojo:
Código:
SemiTransparentText(Image1->Picture->Bitmap, 10, 10,
    "Prueba", "Arial Black", 72, clRed, 50, 3, clWhite);

- De color azul y sin borde:
Código:
SemiTransparentText(Image1->Picture->Bitmap, 10, 10,
    "Prueba", "Arial Black", 72, clBlue, 50);

Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: MUCHAS GRACIAS Responder citando

Todo funciona de maravilla!

Solo me queda dar las gracias...


¡¡¡¡¡¡MUCHAS GRACIAS!!!!!
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Responder citando

Primero que nada saludos a ambos
Mi problemas es casi el mismo pero con dos componentes diferentes con el TWindowsMediaPlayer y un TFIleListBox, el contenedor seria el TWindowsMediaPlayer

Embarassed O y disculpen mi ignoracia me podrian decir como incluir la libreria "msimg32.lib"
Volver arriba
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor MSN Messenger
Mostrar mensajes de anteriores:   
Cambiar a:  
No puedes publicar temas nuevos en este foro
No puedes responder a temas en este foro
No puedes editar tus mensajes en este foro
No puedes borrar tus mensajes en este foro
No puedes votar en las encuestas de este foro


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.