{"id":119,"date":"2010-03-07T15:02:36","date_gmt":"2010-03-07T09:32:36","guid":{"rendered":"http:\/\/techtwaddle.net\/?p=119"},"modified":"2011-01-26T15:02:53","modified_gmt":"2011-01-26T09:32:53","slug":"transparency-and-alphablending-update-with-source-code","status":"publish","type":"post","link":"https:\/\/techtwaddle.co.in\/blog\/2010\/03\/07\/transparency-and-alphablending-update-with-source-code\/","title":{"rendered":"Transparency and AlphaBlending (Update: with source code)"},"content":{"rendered":"<p style=\"text-align: justify;\">In this post we&#8217;ll look at the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa911228.aspx\">AlphaBlend()<\/a> api and how it can be used for semi-transparent blitting. <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa911228.aspx\">AlphaBlend()<\/a> takes a source device context and a destination device context (DC) and combines the bits in such a way that it gives a transparent effect. Follow the links for the msdn documentation.<\/p>\n<p>So lets take a image like,<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" width=\"240\" height=\"100\" alt=\"\" src=\"\/images\/geekswithblogs_net\/TechTwaddle\/AlphaBlend%20-%20No%20Flicker\/normal_image_1.jpg\" \/><\/p>\n<p style=\"text-align: justify;\">and AlphaBlend() it on our window. The code to do so is below, (under the <span style=\"font-family: Verdana;\">WM_PAINT<\/span> message of <span style=\"font-family: Verdana;\">WndProc<\/span>)<\/p>\n<p><span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">HBITMAP hBitmap=NULL, hBitmapOld=NULL;<br \/>\nHDC&nbsp;hMemDC=NULL;<br \/>\nBLENDFUNCTION bf;<\/p>\n<p>hdc = BeginPaint(hWnd, &amp;ps);<\/p>\n<p>hMemDC = CreateCompatibleDC(hdc);<\/p>\n<p>hBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP1));<br \/>\nhBitmapOld = SelectObject(hMemDC, hBitmap);<\/p>\n<p>bf.BlendOp = AC_SRC_OVER;<br \/>\nbf.BlendFlags = 0;<br \/>\nbf.SourceConstantAlpha = 80; <span style=\"color: rgb(51, 153, 102);\">\/\/transparency value between 0-255<\/span><br \/>\nbf.AlphaFormat = 0;&nbsp;&nbsp;&nbsp; <\/p>\n<p><strong><span style=\"color: rgb(0, 0, 128);\">AlphaBlend<\/span><\/strong><span style=\"color: rgb(0, 0, 128);\">(hdc, 0, 25, 240, 100, hMemDC, 0, 0, 240, 100, bf);<\/span><strong><span style=\"color: rgb(0, 0, 128);\"><br \/>\n<\/span><\/strong><br \/>\nSelectObject(hMemDC, hBitmapOld);<\/p>\n<p>DeleteDC(hMemDC);<br \/>\nDeleteObject(hBitmap);<\/p>\n<p>EndPaint(hWnd, &amp;ps);<\/span><\/span><br \/>\n&nbsp;<\/p>\n<p style=\"text-align: justify;\">The code above creates a memory DC (<span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hMemDC<\/span><\/span>) using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa922550.aspx\">CreateCompatibleDC()<\/a>, loads a bitmap onto the memory DC&nbsp;and AlphaBlends it on the device DC (<span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hdc<\/span><\/span>), with a transparency value of 80. The result is:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" width=\"279\" height=\"451\" alt=\"\" src=\"\/images\/geekswithblogs_net\/TechTwaddle\/AlphaBlend%20-%20No%20Flicker\/trnsparent_image_1.jpg\" \/><\/p>\n<p style=\"text-align: justify;\">Pretty simple till now. Now lets try to do something a little more exciting. Lets get two images involved, each overlapping the other, giving a better demonstration of transparency. I am also going to add a few buttons so that the user can increase or decrease the transparency by clicking on the buttons. Since this is the first time I played around with GDI apis, I ran into something that everybody runs into sometime or the other, flickering. When clicking the buttons the images would flicker a lot, I figured out why and used something called double buffering to avoid flickering. We will look at both my first implementation and the second implementation just to give the concept a little more depth and perspective.<\/p>\n<p style=\"text-align: justify;\">A few pre-conditions before I dive into the code:<\/p>\n<p>&#8211; <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hBitmap<\/span><\/span> and <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hBitmap2<\/span><\/span> are handles to the two images obtained using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa928198.aspx\">LoadBitmap()<\/a>, these variables are global and are initialized under <span style=\"font-family: Verdana;\">WM_CREATE<br \/>\n<\/span><br \/>\n&#8211; The two buttons in the application are labeled <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">Opaque++<\/span><\/span> (make more opaque, less transparent) and <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">Opaque&#8211;<\/span><\/span> (make less opaque, more transparent)<\/p>\n<p>&#8211; <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">DrawPics(HWND&nbsp;hWnd, int step=0);<\/span><\/span> is the function called to draw the images on the screen. This is called from under <span style=\"font-family: Verdana;\">WM_PAINT<\/span> and also when the buttons are clicked. When <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">Opaque++<\/span><\/span> is clicked the &#8216;<span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">step<\/span><\/span>&#8216; value passed to DrawPics() is +20 and when <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">Opaque&#8211;<\/span><\/span> is clicked the &#8216;<span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">step<\/span><\/span>&#8216; value is -20. The default value of &#8216;<span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">step<\/span><\/span>&#8216; is 0. The value of &#8216;<span style=\"color: rgb(0, 0, 128);\">step<\/span>&#8216; specifies the amount by which you want to change the transparency.<\/p>\n<p style=\"text-align: justify;\">Now lets take a look at my first implementation:<\/p>\n<p><span style=\"color: rgb(51, 153, 102);\"><span style=\"font-family: Verdana;\">\/\/this funciton causes flicker, cos it draws directly to screen several times<\/span><\/span><span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\"><br \/>\nvoid DrawPics(HWND hWnd, int step)<br \/>\n{<br \/>\n&nbsp;&nbsp;&nbsp; HDC hdc=NULL, hMemDC=NULL;<br \/>\n&nbsp;&nbsp;&nbsp; BLENDFUNCTION bf;<br \/>\n&nbsp;&nbsp;&nbsp; static UINT32 transparency = 100;<\/p>\n<p>&nbsp;&nbsp;&nbsp; <span style=\"color: rgb(51, 153, 102);\">\/\/no point in drawing when transparency is 0 and user clicks Opaque&#8211;<\/span><br \/>\n&nbsp;&nbsp;&nbsp; if (transparency == 0 &amp;&amp; step &lt; 0)<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<\/p>\n<p>&nbsp;&nbsp;&nbsp; <span style=\"color: rgb(51, 153, 102);\">\/\/no point in drawing when transparency is 240 (opaque) and user clicks Opaque++<\/span><br \/>\n&nbsp;&nbsp;&nbsp; if (transparency == 240 &amp;&amp; step &gt; 0)<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br \/>\n&nbsp;&nbsp;&nbsp; <br \/>\n&nbsp;&nbsp;&nbsp; hdc = GetDC(hWnd);<\/p>\n<p><\/span><\/span><span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">&nbsp;&nbsp;&nbsp; <span style=\"color: rgb(51, 153, 102);\">\/\/create a memory DC<\/span><br \/>\n&nbsp;&nbsp;&nbsp; hMemDC = CreateCompatibleDC(hdc);<\/p>\n<p>&nbsp;&nbsp;&nbsp; <span style=\"color: rgb(51, 153, 102);\">\/\/while increasing transparency, clear the contents of screen<\/span><br \/>\n&nbsp;&nbsp;&nbsp; if (step &lt; 0)<br \/>\n&nbsp;&nbsp;&nbsp; {<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RECT rect = {0, 0, 240, 200};<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; FillRect(hdc, &amp;rect, (HBRUSH)GetStockObject(WHITE_BRUSH));<br \/>\n&nbsp;&nbsp;&nbsp; }<\/p>\n<p>&nbsp;&nbsp;&nbsp; SelectObject(hMemDC, hBitmap2);<\/p>\n<p>&nbsp;&nbsp;&nbsp; BitBlt(hdc, 0, 25, 240, 100, hMemDC, 0, 0, SRCCOPY);<br \/>\n&nbsp;&nbsp;&nbsp; <br \/>\n&nbsp;&nbsp;&nbsp; SelectObject(hMemDC, hBitmap);<\/p>\n<p>&nbsp;&nbsp;&nbsp; transparency += step;<\/p>\n<p>&nbsp;&nbsp;&nbsp; if (transparency &gt;= 240)<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; transparency = 240;<\/p>\n<p>&nbsp;&nbsp;&nbsp; if (transparency &lt;= 0)<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; transparency = 0;<\/p>\n<p>\n&nbsp;&nbsp;&nbsp; bf.BlendOp = AC_SRC_OVER;<br \/>\n&nbsp;&nbsp;&nbsp; bf.BlendFlags = 0;<br \/>\n&nbsp;&nbsp;&nbsp; bf.SourceConstantAlpha = transparency;<br \/>\n&nbsp;&nbsp;&nbsp; bf.AlphaFormat = 0;&nbsp;&nbsp;&nbsp; <br \/>\n&nbsp;&nbsp;&nbsp; <br \/>\n&nbsp;&nbsp;&nbsp; AlphaBlend(hdc, 0, 75, 240, 100, hMemDC, 0, 0, 240, 100, bf);<\/p>\n<p>&nbsp;&nbsp;&nbsp; DeleteDC(hMemDC);<br \/>\n&nbsp;&nbsp;&nbsp; ReleaseDC(hWnd, hdc);<br \/>\n}<\/span><\/span><br \/>\n&nbsp;<\/p>\n<p style=\"text-align: justify;\">In the code above, we first get the window DC&nbsp;using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa921543.aspx\">GetDC()<\/a> and create a memory DC using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa922550.aspx\">CreateCompatibleDC()<\/a>. Then we select <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hBitmap2<\/span><\/span> onto the memory DC and Blt it on the window DC&nbsp;(<span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hdc<\/span><\/span>). Next, we select the other image, <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hBitmap,<\/span><\/span> onto memory DC and <span style=\"font-family: Verdana;\">AlphaBlend()<\/span> it over window DC. As I told you before, this implementation causes flickering because it draws directly on the screen (<span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hdc<\/span><\/span>) several times. The video below shows what happens when the buttons were clicked rapidly:<\/p>\n<p style=\"text-align: justify;\">Well, the video recording tool I use captures only 15 frames per second and so the flickering is not visible in the video. So you&#8217;re gonna have to trust me on this, it flickers (;<\/p>\n<p style=\"text-align: justify;\">To solve this problem we make sure that the drawing to the screen happens only once and to do that we create an additional memory DC, <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hTempDC<\/span><\/span>. We perform all our drawing on this memory DC and finally when it is ready we Blt <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hTempDC<\/span><\/span> on <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hdc<\/span><\/span>, and the images are displayed in one go. Here is the code for our new <span style=\"font-family: Verdana;\">DrawPics()<\/span> function:<\/p>\n<p><span style=\"color: rgb(51, 153, 102);\"><span style=\"font-family: Verdana;\">\/\/no flicker<\/span><\/span><span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\"><br \/>\nvoid DrawPics(HWND hWnd, int step)<br \/>\n{<br \/>\n&nbsp;&nbsp;&nbsp; HDC hdc=NULL, hMemDC=NULL, hTempDC=NULL;<br \/>\n&nbsp;&nbsp;&nbsp; BLENDFUNCTION bf;<br \/>\n&nbsp;&nbsp;&nbsp; HBITMAP hBitmapTemp=NULL, hBitmapOld=NULL;<br \/>\n&nbsp;&nbsp;&nbsp; static UINT32 transparency = 100;<\/p>\n<p>&nbsp;&nbsp;&nbsp; <span style=\"color: rgb(51, 153, 102);\">\/\/no point in drawing when transparency is 0 and user clicks Opaque&#8211;<\/span><br \/>\n&nbsp;&nbsp;&nbsp; if (transparency == 0 &amp;&amp; step &lt; 0)<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<\/p>\n<p>&nbsp;&nbsp;&nbsp; <span style=\"color: rgb(51, 153, 102);\">\/\/no point in drawing when transparency is 240 (opaque) and user clicks Opaque++<\/span><br \/>\n&nbsp;&nbsp;&nbsp; if (transparency == 240 &amp;&amp; step &gt; 0)<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br \/>\n&nbsp;&nbsp;&nbsp; <br \/>\n&nbsp;&nbsp;&nbsp; hdc = GetDC(hWnd);<\/p>\n<p>&nbsp;&nbsp;&nbsp; hMemDC = CreateCompatibleDC(hdc);<br \/>\n&nbsp;&nbsp;&nbsp; hTempDC = CreateCompatibleDC(hdc);<\/p>\n<p>&nbsp;&nbsp;&nbsp; hBitmapTemp = CreateCompatibleBitmap(hdc, 240, 150);<br \/>\n&nbsp;&nbsp;&nbsp; hBitmapOld = (HBITMAP)SelectObject(hTempDC, hBitmapTemp);<\/p>\n<p>&nbsp;&nbsp;&nbsp; <span style=\"color: rgb(51, 153, 102);\">\/\/while increasing transparency, clear the contents<\/span><br \/>\n&nbsp;&nbsp;&nbsp; if (step &lt; 0)<br \/>\n&nbsp;&nbsp;&nbsp; {<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RECT rect = {0, 0, 240, 150};<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; FillRect(hTempDC, &amp;rect, (HBRUSH)GetStockObject(WHITE_BRUSH));<br \/>\n&nbsp;&nbsp;&nbsp; }<\/p>\n<p>&nbsp;&nbsp;&nbsp; SelectObject(hMemDC, hBitmap2);<\/p>\n<p>&nbsp;&nbsp;&nbsp; <span style=\"color: rgb(51, 153, 102);\">\/\/Blt hBitmap2 directly to hTempDC<\/span><br \/>\n&nbsp;&nbsp;&nbsp; BitBlt(hTempDC, 0, 0, 240, 100, hMemDC, 0, 0, SRCCOPY);<br \/>\n&nbsp;&nbsp;&nbsp; <br \/>\n&nbsp;&nbsp;&nbsp; SelectObject(hMemDC, hBitmap);<\/p>\n<p>&nbsp;&nbsp;&nbsp; transparency += step;<\/p>\n<p>&nbsp;&nbsp;&nbsp; if (transparency &gt;= 240)<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; transparency = 240;<\/p>\n<p>&nbsp;&nbsp;&nbsp; if (transparency &lt;= 0)<br \/>\n&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; transparency = 0;<\/p>\n<p>\n&nbsp;&nbsp;&nbsp; bf.BlendOp = AC_SRC_OVER;<br \/>\n&nbsp;&nbsp;&nbsp; bf.BlendFlags = 0;<br \/>\n&nbsp;&nbsp;&nbsp; bf.SourceConstantAlpha = transparency;<br \/>\n&nbsp;&nbsp;&nbsp; bf.AlphaFormat = 0;&nbsp;&nbsp;&nbsp; <br \/>\n&nbsp;&nbsp;&nbsp; <br \/>\n&nbsp;&nbsp;&nbsp; AlphaBlend(hTempDC, 0, 50, 240, 100, hMemDC, 0, 0, 240, 100, bf);<\/p>\n<p>&nbsp;&nbsp;&nbsp; <span style=\"color: rgb(51, 153, 102);\">\/\/now hTempDC is ready, blt it directly on hdc<\/span><br \/>\n&nbsp;&nbsp;&nbsp; BitBlt(hdc, 0, 25, 240, 150, hTempDC, 0, 0, SRCCOPY);<\/p>\n<p>&nbsp;&nbsp;&nbsp; SelectObject(hTempDC, hBitmapOld);<\/p>\n<p>&nbsp;&nbsp;&nbsp; DeleteObject(hBitmapTemp);<br \/>\n&nbsp;&nbsp;&nbsp; DeleteDC(hMemDC);<br \/>\n&nbsp;&nbsp;&nbsp; DeleteDC(hTempDC);<\/p>\n<p>&nbsp;&nbsp;&nbsp; ReleaseDC(hWnd, hdc);<br \/>\n}<\/span><\/span><br \/>\n&nbsp;<\/p>\n<p style=\"text-align: justify;\">This function is very similar to the first version, except for the use of <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hTempDC<\/span><\/span>. Another point to note is the use of <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa922174.aspx\">CreateCompatibleBitmap()<\/a>. When a memory device context is created using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa922550.aspx\">CreateCompatibleDC()<\/a>, the context is exactly one monochrome pixel high and one monochrome pixel wide. So in order for us to draw anything onto <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hTempDC<\/span><\/span>, we first have to set a bitmap on it. We use <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa922174.aspx\">CreateCompatibleBitmap()<\/a> to create a bitmap of required dimension (240&#215;150 above), and then select this bitmap onto <span style=\"color: rgb(0, 0, 128);\"><span style=\"font-family: Verdana;\">hTempDC<\/span><\/span>. Think of it as utilizing an extra canvas, drawing everything on the canvas and finally transferring the contents to the display in one scoop. And with this version the flickering is gone, video follows:<\/p>\n<p><object width=\"425\" height=\"344\"><param name=\"movie\" value=\"http:\/\/www.youtube.com\/v\/sm-0xLPDDzE&amp;hl=en_US&amp;fs=1&amp;color1=0x3a3a3a&amp;color2=0x999999\" \/><param name=\"allowFullScreen\" value=\"true\" \/><param name=\"allowscriptaccess\" value=\"always\" \/><\/object><\/p>\n<p style=\"text-align: justify;\">&nbsp;<\/p>\n<p style=\"text-align: justify;\">If you want the entire solutions source code then leave a message, I will share the code over SkyDrive.<\/p>\n<p style=\"text-align: justify;\"><strong>Update:<\/strong> I have shared the source code of this application on SkyDrive. The solution was created using Visual Studio 2008 and has been tested on Windows Mobile 6 Professional&nbsp;Emulator. The link follows,<\/p>\n<p>Source Code: <a href=\"http:\/\/cid-65187cfbc4ac6ad2.skydrive.live.com\/self.aspx\/.Public\/SourceCode\/AlphaBlending.zip\">AlphaBlending.zip<\/a><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post we&#8217;ll look at the AlphaBlend() api and how it can be used for semi-transparent blitting. AlphaBlend() takes a source device context and a destination device context (DC) and combines the bits in such a way that it gives a transparent effect. Follow the links for the msdn documentation. So lets take a &hellip; <a href=\"https:\/\/techtwaddle.co.in\/blog\/2010\/03\/07\/transparency-and-alphablending-update-with-source-code\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Transparency and AlphaBlending (Update: with source code)<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false},"categories":[1],"tags":[],"jetpack_featured_media_url":"","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p1ktFF-1V","_links":{"self":[{"href":"https:\/\/techtwaddle.co.in\/blog\/wp-json\/wp\/v2\/posts\/119"}],"collection":[{"href":"https:\/\/techtwaddle.co.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/techtwaddle.co.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/techtwaddle.co.in\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/techtwaddle.co.in\/blog\/wp-json\/wp\/v2\/comments?post=119"}],"version-history":[{"count":1,"href":"https:\/\/techtwaddle.co.in\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions"}],"predecessor-version":[{"id":120,"href":"https:\/\/techtwaddle.co.in\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions\/120"}],"wp:attachment":[{"href":"https:\/\/techtwaddle.co.in\/blog\/wp-json\/wp\/v2\/media?parent=119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/techtwaddle.co.in\/blog\/wp-json\/wp\/v2\/categories?post=119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/techtwaddle.co.in\/blog\/wp-json\/wp\/v2\/tags?post=119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}