Code archives/Graphics/Curved Text routine and RLE vector functions (part 1)
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
These RLE vector functions allow you to wrap text or images around a circle. The functions are: getImg() - scans an area on screen and stores in RLE image format in the vec() array. You must store your image in RLE format before using any of the other functions. rotateImg() - rotates an image at 0, 90, 180, and 270 degrees and displays rotated image on screen maskImg() - makes any single color of an RLE image transparent replaceColor() - replace any single color of an RLE image with a different color maskAndReplace() - mask a single color and replace a different single color with a new color magnify() - enlarges and rotates an RLE image curveImg() - wraps an RLE image around an arc segment. Similar to MS Word Art or Photoshop text curving. Parameters for the curveImg function: centerX%, centerY% - the center of the imaginary circle that you're wrapping around radius% - radius of the imaginary circle. Start at a radius of 50 pixels (100 pixel diameter) and adjust to suit. startAngle# - defines the start point of your RLE on the imaginary circle arcSegment# - number of degrees to plot after the startAngle. If you start at 180 degrees and wrap an arc segment of 180 degrees, your image will start wrapping at 180 degrees, and plot to 360 degrees on the imaginary circle. imgWidth% - width in pixels of your RLE image imgHeight% = height in pixels of your RLE image penSize% = use this to fill in the voids that are left when the math is more precise than the screen resolution. Start with a penSize of 1, increase penSize by 1 until there are no more voids. (Made changes so 16 bit graphic cards can display properly) (Another update: new vector storage format uses less memory, now can be used to load images from data statements) | |||||
; Title: Blitz RLE Vector Image Demo ;Programmer: Andy Amaya ; Date: 2004.03.25 ; Version: 1.08-Added dat2curv2buf() function ; Update: 1.07-Added data2buffer() function ; Update: 1.06-Added makeData() and getImgData() functions ; as a result, a new vector storage method is used. ; Update: 1.05-Lock & UnLock buffer to use ReadPixelFast (does NOT work in B2D) ; Update: 1.04-Added constants to support use with 16 bit color cards ; Update: 1.03-Added curveImg Routine ; Update: 1.01-Added maskImg, replaceColor, maskAndReplace routines ; Update: 1.00-Original RLE image routine AppTitle "Blitz Run Length Encoded Vector Images" Global sw% = 800 Global sh% = 600 Global cd% = 32 ;<--------------- Color depth Graphics sw, sh , cd, 2 SetBuffer BackBuffer() Dim vecs(1) ;vector array (true dimension size in image data) Dim pal%(1) ;Color palette array (true dimension size in image data) ;========== masking constants for 32 bit color ========= Global maskRed% = 16711680 Global maskGrn% = 65280 Global maskBlu% = 255 ;======================================================= ;========= masking constants for 16 bit (5-6-5) ======== ; Global maskRed% = 16252928 ; Global maskGrn% = 64512 ;change to 63488 for (5-5-5) ; Global maskBlu% = 248 ;======================================================= Arial40bi% = LoadFont("Arial",40,True,True) Arial18b% = LoadFont("Arial",18,True) Cls Color 0,128,255 Rect 0, 0,sw-1, sh-1,True SetFont Arial40bi msg$ = "Rotate text" msgWide% = StringWidth(msg$) msgHigh% = StringHeight(msg$) Color 255,0,0 center% = (sw-msgWide) Shr 1 Rect center, 0,msgWide,msgHigh,True Color 255,255,255 Text center,0,msg$ SetFont arial18b Text 350,46,"(Original Image)" getImg(center, 0, msgWide, msgHigh) rotateImg( 0, 10, 100, msgWide, msgHigh) rotateImg( 90, 10+msgWide, 100+msgHigh, msgWide, msgHigh) rotateImg(180, 10+msgWide, 100+msgWide+msgHigh*2, msgWide, msgHigh) rotateImg(270, 10, 100+msgWide+msgHigh, msgWide, msgHigh) maskImg( 0, 210, 100, msgWide, msgHigh, 255, 0, 0) maskImg( 90, 210+msgWide, 100+msgHigh, msgWide, msgHigh, 255, 0, 0) maskImg(180, 210+msgWide, 100+msgWide+msgHigh*2, msgWide, msgHigh, 255, 0, 0) maskImg(270, 210, 100+msgWide+msgHigh, msgWide, msgHigh, 255, 0, 0) replaceColor( 0, 410, 100, msgWide, msgHigh, 255, 255, 255, 255, 255, 0) replaceColor( 90, 410+msgWide, 100+msgHigh, msgWide, msgHigh, 255, 255, 255, 255, 255, 0) replaceColor(180, 410+msgWide, 100+msgWide+msgHigh*2, msgWide, msgHigh, 255, 255, 255, 255, 255, 0) replaceColor(270, 410, 100+msgWide+msgHigh, msgWide, msgHigh, 255, 255, 255, 255, 255, 0) maskAndReplace( 0, 610, 100, msgWide, msgHigh, 255, 0, 0, 255, 255, 255, 255, 255, 32) maskAndReplace( 90, 610+msgWide,100+msgHigh, msgWide, msgHigh, 255, 0, 0, 255, 255, 255, 255, 192, 32) maskAndReplace(180, 610+msgWide,100+msgWide+msgHigh*2, msgWide, msgHigh, 255, 0, 0, 255, 255, 255, 200, 224, 64) maskAndReplace(270, 610, 100+msgWide+msgHigh, msgWide, msgHigh, 255, 0, 0, 255, 255, 255, 192, 255, 32) Color 255,255,255 SetFont Arial18b Text 20,365,"Example of rotated text" Text 220,365,"Example of masking" Text 220,388,"the red from image" Text 420,365,"Example of replacing" Text 420,388,"white with yellow" Text 620,365,"Example of masking" Text 620,388,"red and replacing" Text 620,411,"the white" Text 10,570,"click to continue" Flip WaitMouse() FlushMouse() SetFont Arial40bi Color 0,128,255 Rect 0, 0, sw-1, sh-1, True msg$ = "Zoom 1x-32x" msgWide% = StringWidth(msg$) msgHigh% = StringHeight(msg$) Color 255,0,0 center% = (sw-msgWide) Shr 1 Rect 0, 0,msgWide,msgHigh,True Color 255,255,255 Text 0,0,msg$ SetFont arial18b Text 40,46,"(Original Image)" getImg(0, 0, msgWide, msgHigh) magnify( 0, center, 0, msgWide, msgHigh, 2) magnify( 90, center+msgWide*2-2,msgHigh*2, msgWide, msgHigh, 2) magnify(180, center+msgWide*2, msgWide*2+msgHigh*4-2, msgWide, msgHigh, 2) magnify(270, center, msgWide*2+msgHigh*2, msgWide, msgHigh, 2) SetFont Arial18b Color 255,255,255 Text center+175,289,"(this is 2x)" Text 10,570,"click to continue" Flip WaitMouse() FlushMouse() Color 0, 128, 255 Rect 0, 0, sw-1, sh-1, True SetFont Arial40bi msg$ = "Curved Text Example " msgWide% = StringWidth(msg$)-5 msgHigh% = StringHeight(msg$) center% = (sw-msgWide) Shr 1 Color 255,0,0 Rect center, 0,msgWide,msgHigh,True Color 255,255,255 Text center,0,msg$ SetFont Arial18b Text 100,0,"(Original Image)" Text 10,570,"click to exit" getImg(center, 0, msgWide, msgHigh) curveImg(400, 320, 275, 180.0, 360.0, msgWide, msgHigh, 5) curveImg(400, 320, 225, 270.0, 270.0, msgWide, msgHigh, 4) curveImg(400, 320, 175, 0.0, 225.0, msgWide, msgHigh, 4) curveImg(400, 320, 125, 90.0, 270.0, msgWide, msgHigh, 3) curveImg(400, 320, 75, 112.0, 315.0, msgWide, msgHigh, 2) Flip WaitMouse() FreeFont Arial40bi FreeFont Arial18b End Function getImg(x%, y%, imgWidth%, imgHeight%) ;Allocate enough memory for worst case scenario Dim vecs(imgWidth*imgHeight*2) ;================ LockBuffer ;================ vCount% = -2 cCount% = -1 lastColor% = -1 For j% = y To y + imgHeight-1 pixCount = 0 For i% = x To x+imgWidth-1 ;Get pixel color from current screen coords pixColor% = ReadPixelFast(i, j) ;============== 16 bit (5-6-5)================================ ; modify pixel color values for 16bit color ;============================================================= If cd = 16 Then pixColor = pixColor And 16317688 ;use 16253176 for (5-5-5) End If ;============================================================= ;Keep track of how many pixels of current color pixCount% = pixCount% + 1 ;If at start of a raster line OR there's a change in color ;Then keep track of how many pixels for current color If (i = x) Or (pixColor <> lastColor) Then ;remember pixel color as the last color encountered in bitmap lastColor = pixColor vecLen% = 1 vCount = vCount + 2 ;even numbered elements hold length values cCount = cCount + 2 ;odd numbered elements hold color values ;Update vector array: evenNumber element = number of same color pixels vecs(vCount) = vecLen ;Update vector array: oddNumber element = new pixel color to store vecs(cCount) = pixColor Else ;Otherwise just add to the number of same colored pixels vecLen = vecLen + 1 vecs(vCount) = vecLen End If Next Next ;================== UnlockBuffer ;================== End Function Function rotateImg(angle%, x%, y%, imgWidth%, imgHeight%) If angle = 0 Or angle = 90 Or angle = 180 Or angle = 270 Then angle2% = angle + 90 vCount% = 0 For i% = 1 To imgHeight p# = Cos(angle2)*(i-1)+x q# = Sin(angle2)*(i-1)+y lineLen% = 0 While lineLen < imgWidth vecLen = vecs(vCount) lineLen = linelen + vecLen red% = (vecs(vCount + 1) And maskRed) Shr 16 grn% = (vecs(vCount + 1) And maskGrn) Shr 8 blu% = vecs(vCount + 1) And maskBlu ;=========================================================== If cd = 16 Then red = red Shr 3 Shl 3 grn = grn Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) blu = blu Shr 3 Shl 3 End If ;=========================================================== Color red,grn,blu r# = Cos(angle)*vecLen+p s# = Sin(angle)*vecLen+q Line p,q,r,s vCount = vCount+2 p=r q=s Wend Next End If End Function Function maskImg(angle%, x%, y%, imgWidth%, imgHeight%, r1%, g1%, b1%) If angle = 0 Or angle = 90 Or angle = 180 Or angle = 270 Then ;===16 bit (5-6-5)============================ ; modify parameter values for 16bit color ;============================================= If cd = 16 Then r1 = r1 Shr 3 Shl 3 g1 = g1 Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) b1 = b1 Shr 3 Shl 3 End If ;============================================= angle2% = angle + 90 vCount% = 0 For i% = 1 To imgHeight p# = Cos(angle2)*(i-1)+x q# = Sin(angle2)*(i-1)+y lineLen% = 0 While lineLen < imgWidth vecLen = vecs(vCount) lineLen = linelen + vecLen red% = (vecs(vCount + 1) And maskRed) Shr 16 grn% = (vecs(vCount + 1) And maskGrn) Shr 8 blu% = vecs(vCount + 1) And maskBlu ;============== 16 bit (5-6-5)============================== ; modify parameter values for 16bit color ;=========================================================== If cd = 16 Then red = red Shr 3 Shl 3 grn = grn Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) blu = blu Shr 3 Shl 3 End If ;=========================================================== Color red,grn,blu r# = Cos(angle)*vecLen+p s# = Sin(angle)*vecLen+q If r1=red And g1=grn And b1=blu Then vCount = vCount+2 Else Line p,q,r,s vCount = vCount+2 End If p=r q=s Wend Next End If End Function Function replaceColor(angle%, x%, y%, imgWidth%, imgHeight%, r1%, g1%, b1%, r2%, g2%, b2%) If angle = 0 Or angle = 90 Or angle = 180 Or angle = 270 Then ;===16 bit (5-6-5)======================================== ; modify parameter values for 16bit color ;========================================================= If cd = 16 Then r1 = r1 Shr 3 Shl 3 g1 = g1 Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) b1 = b1 Shr 3 Shl 3 r2 = r2 Shr 3 Shl 3 g2 = g2 Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) b2 = b2 Shr 3 Shl 3 End If ;========================================================= angle2% = angle + 90 vCount% = 0 For i% = 1 To imgHeight p# = Cos(angle2)*(i-1)+x q# = Sin(angle2)*(i-1)+y lineLen% = 0 While lineLen < imgWidth vecLen = vecs(vCount) lineLen = linelen + vecLen red = (vecs(vCount + 1) And maskRed) Shr 16 grn = (vecs(vCount + 1) And maskGrn) Shr 8 blu = vecs(vCount + 1) And maskBlu ;============== 16 bit (5-6-5)============================== ; modify parameter values for 16bit color ;=========================================================== If cd = 16 Then red = red Shr 3 Shl 3 grn = grn Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) blu = blu Shr 3 Shl 3 End If ;=========================================================== Color red,grn,blu r# = Cos(angle)*vecLen+p s# = Sin(angle)*vecLen+q If r1=red And g1=grn And b1=blu Then Color r2,g2,b2 End If Line p,q,r,s vCount = vCount+2 p=r q=s Wend Next End If End Function Function maskAndReplace(angle%, x%, y%, imgWidth%, imgHeight%, r1%, g1%, b1%, r2%, g2%, b2%, r3%, g3%, b3%) If angle = 0 Or angle = 90 Or angle = 180 Or angle = 270 Then ;===16 bit (5-6-5)======================================== ; modify parameter values for 16bit color ;========================================================= If cd = 16 Then r1 = r1 Shr 3 Shl 3 g1 = g1 Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) b1 = b1 Shr 3 Shl 3 r2 = r2 Shr 3 Shl 3 g2 = g2 Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) b2 = b2 Shr 3 Shl 3 r3 = r3 Shr 3 Shl 3 g3 = g3 Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) b3 = b3 Shr 3 Shl 3 End If ;========================================================= angle2% = angle + 90 vCount% = 0 For i% = 1 To imgHeight p# = Cos(angle2)*(i-1)+x q# = Sin(angle2)*(i-1)+y lineLen% = 0 While lineLen < imgWidth vecLen = vecs(vCount) lineLen = linelen + vecLen red = (vecs(vCount + 1) And maskRed) Shr 16 grn = (vecs(vCount + 1) And maskGrn) Shr 8 blu = vecs(vCount + 1) And maskBlu ;============== 16 bit (5-6-5)============================== ; modify parameter values for 16bit color ;=========================================================== If cd = 16 Then red = red Shr 3 Shl 3 grn = grn Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) blu = blu Shr 3 Shl 3 End If ;=========================================================== Color red,grn,blu r# = Cos(angle)*vecLen+p s# = Sin(angle)*vecLen+q If r2=red And g2=grn And b2=blu Then Color r3,g3,b3 Line p,q,r,s vCount = vCount+2 Else If r1=red And g1=grn And b1=blu Then vCount = vCount+2 Else Line p,q,r,s vCount = vCount+2 End If End If p=r q=s Wend Next End If End Function Function magnify(angle%, x%, y%, imgWidth%, imgHeight%, magLevel%) If angle = 0 Or angle = 90 Or angle = 180 Or angle = 270 Then If magLevel > 0 And magLevel < 33 Then angle2% = angle + 90 vCount% = 0 i% = 1 While i < imgHeight*magLevel p# = Cos(angle2)*(i-1)+x q# = Sin(angle2)*(i-1)+y lineLen% = 0 While lineLen < imgWidth vecLen = vecs(vCount) lineLen = linelen + vecLen red = (vecs(vCount + 1) And maskRed) Shr 16 grn = (vecs(vCount + 1) And maskGrn) Shr 8 blu = vecs(vCount + 1) And maskBlu ;============== 16 bit (5-6-5)============================== ; modify parameter values for 16bit color ;=========================================================== If cd = 16 Then red = red Shr 3 Shl 3 grn = grn Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) blu = blu Shr 3 Shl 3 End If ;=========================================================== Color red,grn,blu Select angle Case 0 boxWide% = magLevel * vecLen boxHigh% = magLevel Rect p, q, boxWide, boxHigh, True p = p + boxWide Case 90 boxWide% = magLevel boxHigh% = magLevel * vecLen Rect p, q, boxWide, boxHigh, True q = q + boxHigh Case 180 p = p - magLevel * vecLen boxWide = magLevel * vecLen boxHigh = magLevel Rect p, q, boxWide, boxHigh, True Case 270 q = q - magLevel*vecLen boxWide = magLevel boxHigh = magLevel * vecLen Rect p, q, boxWide, boxHigh, True End Select vCount = vCount + 2 Wend i = i + magLevel Wend End If End If End Function Function curveImg(centerX%, centerY%, radius%, startAngle#, arcSegment#, imgWidth%, imgHeight%, penSize%) If penSize > 1 Then penOffset# = penSize/2 stepSize# = arcSegment/imgWidth vCount% = 0 For i% = 1 To imgHeight lineLen% = 0 arc# = startAngle While lineLen < imgWidth arcLen = vecs(vCount) lineLen = lineLen + arcLen red = (vecs(vCount + 1) And maskRed) Shr 16 grn = (vecs(vCount + 1) And maskGrn) Shr 8 blu = vecs(vCount + 1) And maskBlu ;============== 16 bit (5-6-5)============================== ; modify parameter values for 16bit color ;=========================================================== If cd = 16 Then red = red Shr 3 Shl 3 grn = grn Shr 2 Shl 2 ;change to Shr 3 Shl 3 for (5-5-5) blu = blu Shr 3 Shl 3 End If ;=========================================================== Color red, grn, blu arcInc# = arcLen*stepSize c# = arc# While c <= arc+arcInc x = Cos(c)*radius+centerX y = Sin(c)*radius+centerY If penSize > 1 Then Rect x-penOffset, y-penOffset, penSize, penSize, True Else Plot x,y End If c = c+stepSize Wend arc = arc+arcInc vCount = vCount+2 Wend radius = radius - 1 Next End Function |
Comments
| ||
Neat demo but on the first screen there's no difference in the rotated text examples - they're all white text on red background. |
| ||
Thanks for the comment. I downloaded the code from here, and it ran fine on my machine. The white text on a red background was used for contrast. The first rectangle should be made up of "Rotate Text" rotated at 0, 90, 180, 270 degrees. The second rectangle should be "Rotate Text" without the red background. The third rectangle should be yellow text on red background. The last rectangle should be four different shades of yellow without the red background. If your screen is different, it's probably because I only coded for 32 bit colors, though 16 bit color should be an easy tweak. |
| ||
big10p, Made changes to code to allow for 16 bit color cards. Change: Graphics 800,600,32,2 to Graphics 800,600,16,2 Comment Out 32bit color masks and un-comment 16bit color masks Then un-comment 16 bit variable assignments in rest of code. They are all sectioned off with comments, so they're easy to spot. That should do it! |
| ||
OK, it's fixed, forgot to make the color depth variable global. Change cd from 32 to 16 Comment 32bit color masks and un-comment 16bit mask values Have tested at 16bit (5-6-5) and it works. |
| ||
OK, it works now. ;) |
| ||
Glad to hear it worked for you, I did test it by resetting my graphics to 16bit and it worked, but it's good to hear it worked on a different system. Currently working on a file packing system, kind of like the one Terrabit made. Using the RLE compression with some more logic should make it feasible to include small images inside the source code of a project. I converted a 1.7Mb file using RLE to 85K. That works out to a 20:1 compression ratio. Another file I converted went from 30K to 20K, only 33 percent less. RLE doesn't work well with images that have lots of color gradients, but for simple graphics like sprites, it should be OK. |
Code Archives Forum