Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Графика, звук, анимация, игры > Наложение полупрозрачного текста на Jpeg


Автор: C800H 06.06.11, 00:23
Наложение полупрозрачного текста на Jpeg
Несколько раз уж требовалась внятная функция, для наложения полу-прозрачного текста на jpg. Очень досадно, что в DRKB информации по теме нет. На сей раз перелопатив несколько исходников(в инэте бродит с внесёнными порожняками), сварганил работающий вариант. Мне хватает, надеюсь и другим поможет.
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    {
    ================================================================================
                     Наложение полу-прозрачного текста на Jpg
    --------------------------------------------------------------------------------
      требования: Uses jpeg;
    размещать выше процедуры, из которой будет вызываться TextToBitmap.
      вызов:
    TextToBitmap('Текст', jpg, 70, rgb(255,255,255), 30, alLeft,alTop, 0, 0);
                          |     |   |                |   |       |     |  |
                          1     2   3                4   5.1     5.2  6.1 6.2
    1: Изображение, на которое будет нанесён текст
    2: Размер шрифта
    3: Цвет шрифта
    4: Прозрачность текста (0 - невидимый, 255 - непрозрачный)
    5: Выравнивание по 1.горизонтали 2.вертикали
       примечание: alClient - центровка;
       +работающие значения: alRight, alBottom - любые другие = alNone.
    6: Смешение текста 1.вправо 2.вниз
     
    Пример вызова:
    Uses jpeg;
    .....
    var jpg: TJPEGImage;
    begin
      jpg:=TJPEGImage.Create;
      jpg.LoadFromFile('c:\windows\web\wallpaper\Тюльпаны.jpg');
      TextToBitmap('Текст', jpg, 90, rgb(255,255,255), 30, alLeft,alTop, 50, 50);
      Form1.canvas.StretchDraw(Rect(0,0,jpg.Width,jpg.Height),jpg);
      jpg.Free;
     
    Васильев Владимир Викторович aka C800H. г.Евпатория. uin(icq): 300011169
    }
     
    //создать канал прозрачности (типа того)
    procedure BuildTextBmp(var b_rgb,b_mask,b_out:TBitmap);
    const MaxPixelCountA = MaxInt div SizeOf(TRGBQuad);
    type PRGBAArray=^TRGBAArray;
         TRGBAArray=array[0..MaxPixelCountA-1] of TRGBQuad;
    var x,y: Integer;
        rrgb,rmask,RowOut: PRGBAArray;
    begin
      for y:=0 to b_rgb.Height-1 do
      begin
        RowOut:=b_out.ScanLine[y];
        rrgb:=b_rgb.ScanLine[y];
        rmask:=b_mask.ScanLine[y];
        for x:=0 to b_rgb.Width-1 do
        begin
          RowOut[x].rgbReserved:=rmask[x].rgbRed;
          RowOut[x].rgbRed:=rrgb[x].rgbRed;
          RowOut[x].rgbGreen:=rrgb[x].rgbGreen;
          RowOut[x].rgbBlue:=rrgb[x].rgbBlue;
        end;
      end;
    end;
    //BmpText - входящий битмап с прозрачностью(BmpText) - накладывается на CanvasOut.
    procedure BlendBitmap_GDI(CanvasOut:TCanvas; BmpText:TBitmap; TextPosX,TextPosY:integer);
    const MaxPixelCountA=(MaxInt div SizeOf(TRGBQuad))-1;
    type TRGBAArray=array[0..MaxPixelCountA] of TRGBQuad;
         PRGBAArray=^TRGBAArray;
    var TextW,TextH,DstW,DstH: Integer;
       BmpBuff:TBitmap;
       x,y,lti:Integer;
       PSource,PDest:PRGBAArray;
       trans:double;
    begin
      if (TextPosX<0) or (TextPosY<0) or (BmpText.PixelFormat<>pf32bit) then Exit;
     
      TextW:=BmpText.Width;
      TextH:=BmpText.Height;
      if (TextW<1) or (TextH<1) then exit; //нет текста - выход
     
      DstW:=CanvasOut.ClipRect.Right-CanvasOut.ClipRect.Left;
      DstH:=CanvasOut.ClipRect.Bottom-CanvasOut.ClipRect.Top;
      if (DstW<TextW+TextPosX) or (DstH<TextH+TextPosY) then Exit;//текст "не влазит" - выход
     
      BmpBuff:=TBitmap.Create;
      BmpBuff.Width:=TextW;
      BmpBuff.Height:=TextH;
      BmpBuff.PixelFormat:=pf32bit;
     
      try
        BmpBuff.Canvas.CopyRect(Rect(0,0,BmpBuff.Width,BmpBuff.Height), CanvasOut, Rect(TextPosX,TextPosY,TextPosX+TextW,TextPosY+TextH));
        for y:=0 to TextH-1 do
        begin
          PSource:=BmpText.ScanLine[y];
          PDest:=BmpBuff.ScanLine[y];
          for x:=0 to TextW-1 do
          begin
            //прозрачность
            if PSource[x].rgbReserved>0 then
              trans:=0.004*PSource[x].rgbReserved else trans:=0;
     
            lti:=round(PDest[x].rgbRed+(PSource[x].rgbRed-PDest[x].rgbRed)*trans);
            if lti>255 then lti:=255 else if lti<0 then lti:=0;
            PDest[x].rgbRed:=lti;
     
            lti:=round(PDest[x].rgbGreen+(PSource[x].rgbGreen-PDest[x].rgbGreen)*trans);
            if lti>255 then lti:=255 else if lti<0 then lti:=0;
            PDest[x].rgbGreen:=lti;
     
            lti:=round(PDest[x].rgbBlue+(PSource[x].rgbBlue-PDest[x].rgbBlue)*trans);
            if lti>255 then lti:=255 else if lti<0 then lti:=0;
            PDest[x].rgbBlue:=lti;
          end;
        end;
        //выхлоп - полупрозрачный текст наложен на Bitmap
        CanvasOut.CopyRect(Rect(TextPosX,TextPosY,TextPosX+TextW,TextPosY+TextH), BmpBuff.canvas, Rect(0,0,BmpBuff.Width,BmpBuff.Height));
      finally
        BmpBuff.Free;
      end;
    end;
     
     //----------------------------------------------------------
    // Наложить полу-прозрачный текст на Jpeg - центр управления
    procedure TextToBitmap(Text:String; JpgInOut:TJPEGImage; FontSize:Byte; TextColor:TColor; Transparency:Byte; TextAlign,TextValign:TAlign; TextLeft,TextTop:Integer);
    var BmpToFinish, BmpText, bmp_text_rgb: TBitmap;
    begin
      BmpToFinish:=TBitmap.Create;
      BmpText:=TBitmap.Create;
      bmp_text_rgb:=TBitmap.Create;
      try
     
        //jpg2bmp
        BmpToFinish.Width:=JpgInOut.Width;
        BmpToFinish.Height:=JpgInOut.Height;
        BmpToFinish.Canvas.StretchDraw(BmpToFinish.Canvas.Cliprect, JpgInOut);
     
        BmpToFinish.PixelFormat:=pf32bit;
        BmpText.PixelFormat:=pf32bit;
        bmp_text_rgb.PixelFormat:=pf32bit;
     
        //настройка шрифта
        BmpText.Canvas.Font.Size:=FontSize;//размер шрифта
        BmpText.Canvas.Font.Color:=rgb(Transparency,Transparency,Transparency); //прозрачность текста 0 - полная прозрачность
        BmpText.Canvas.Font.Name:='Arial';
     
        BmpText.Width:=BmpText.Canvas.TextWidth(Text)+4;//отступы текста - 2 px
        BmpText.Height:=BmpText.Canvas.TextHeight(Text)+4;//отступы текста - 2 px
        bmp_text_rgb.Width:=BmpText.Width;
        bmp_text_rgb.Height:=BmpText.Height;
     
        bmp_text_rgb.Canvas.Brush.Color:=TextColor; //цвет текста
        bmp_text_rgb.Canvas.FillRect(bmp_text_rgb.Canvas.ClipRect);
     
        BmpText.Canvas.Brush.Color:=clBlack;
        BmpText.Canvas.FillRect(BmpText.Canvas.ClipRect);
     
    //    BmpText.Canvas.Brush.Color:=clWhite; //- invert - пример :)
     
        //наложить текст
        BmpText.Canvas.TextOut(2,2,Text);//отступы текста - 2 px
        //создать канал прозрачности тексту
        BuildTextBmp(bmp_text_rgb,BmpText,BmpText);
     
        //подготовка выравнивания текста alRight, alBottom, alClient=center.//знаю, не дело так юзать alClient - сделай правильней! :)
        case TextValign of
          alBottom: TextTop:=BmpToFinish.Height-BmpText.Height+TextTop;
          alClient: TextTop:=(BmpToFinish.Height div 2)-(BmpText.Height div 2)+TextTop;
        end;
        case TextAlign of
          alRight: TextLeft:=BmpToFinish.Width-BmpText.Width;
          alClient: TextLeft:=(BmpToFinish.Width div 2)-(BmpText.Width div 2)+TextLeft;
        end;
     
        //смешать bmp_текст с фоном
        BlendBitmap_GDI(BmpToFinish.Canvas,BmpText,TextLeft,TextTop);
     
        //конвертировать готовый микс из bmp_in в jpg
        JpgInOut.Assign(BmpToFinish);
        JpgInOut.CompressionQuality:=100;
        JpgInOut.Compress;
     
      finally
       BmpToFinish.Free;
       BmpText.Free;
       bmp_text_rgb.Free;
      end;
    end;
     
    //
    // Наложение полу-прозрачного текста на Jpg
    //==============================================================================

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)