Cascading Style Sheet (CSS) Color Negatizing Script
The Customer Scenario
I ran into an interesting situation recently - I host a website for a friend of mine, and he was shopping around for a new website template. He found one that he liked, but he didn't like the colors. In fact, he wanted the exact opposite of the colors in the website template, so he asked what I could do about it.
I looked at the website template, and thankfully it was using linked Cascading Style Sheets (CSS) files for all of the color definitions, so I told him that changing the colors would probably be a pretty easy thing to do. However, once I cracked open the CSS files from the website template, I found that they had hundreds of color definitions. Changing every color definition by hand would have taken hours, so I decided to write some Windows Script Host (WSH) code to do the work for me. ;-]
Negatizing a CSS File
With the above scenario in mind, here's the script that I wrote to negatize every color in a CSS file - all that you need to do is replace the paths to the input and output files and run the script to create the negatized version of the input CSS file.
Option Explicit
Const strInputFile = "c:\inetpub\wwwroot\style-dark.css"
Const strOutputFile = "c:\inetpub\wwwroot\style-light.css"
' ------------------------------------------------------------
Dim objFSO
Dim objInputFile
Dim objOutputFile
Dim strInputLine
Dim strLeft, strMid, strRight, strArray
Dim blnFound
' ------------------------------------------------------------
Const strTempRGB = "[|[TMPRGBSTR1NG]|]"
Const strTempHEX = "[|[TMPHEXSTR1NG]|]"
' ------------------------------------------------------------
Set objFSO = CreateObject("scripting.filesystemobject")
Set objInputFile = objFSO.OpenTextFile(strInputFile)
Set objOutputFile = objFSO.CreateTextFile(strOutputFile)
Do While Not objInputFile.AtEndOfStream
strInputLine = objInputFile.ReadLine
blnFound = True
Do While blnFound
If InStr(1,strInputLine,"rgb(",vbTextCompare) Then
strLeft = Left(strInputLine,InStr(1,strInputLine,"rgb(",vbTextCompare)-1)
strMid = Mid(strInputLine,InStr(1,strInputLine,"rgb(",vbTextCompare)+4)
strRight = Mid(strMid,InStr(strMid,")")+1)
strMid = Left(strMid,InStr(strMid,")")-1)
strArray = Split(strMid,",")
strMid = InvertOctet(CInt(strArray(0))) & _
"," & InvertOctet(CInt(strArray(1))) & _
"," & InvertOctet(CInt(strArray(2)))
strInputLine = strLeft & strTempRGB & "(" & strMid & ")" & strRight
Else
blnFound = False
End If
Loop
strInputLine = Replace(strInputLine,strTempRGB,"rgb")
blnFound = True
Do While blnFound
If InStr(strInputLine,"#") Then
strLeft = Left(strInputLine,InStr(strInputLine,"#")-1)
strMid = Mid(strInputLine,InStr(strInputLine,"#")+1)
If Len(strMid)>6 Then
strRight = Mid(strMid,7)
strMid = Left(strMid,6)
ElseIf Len(strMid)>3 Then
strRight = Mid(strMid,4)
strMid = Left(strMid,3)
Else
strRight = ""
End If
If IsHexString(strMid) Then
If Len(strMid) = 6 Then
strMid = Right("0" & Hex(InvertOctet(CInt("&h" & Left(strMid,2)))),2) & _
Right("0" & Hex(InvertOctet(CInt("&h" & Mid(strMid,3,2)))),2) & _
Right("0" & Hex(InvertOctet(CInt("&h" & Right(strMid,2)))),2)
Else
strMid = Hex(InvertByte(CInt("&h" & Left(strMid,2)))) & _
Hex(InvertByte(CInt("&h" & Mid(strMid,3,2)))) & _
Hex(InvertByte(CInt("&h" & Right(strMid,2))))
End If
End If
strInputLine = strLeft & strTempHEX & strMid & strRight
Else
blnFound = False
End If
Loop
strInputLine = Replace(strInputLine,strTempHEX,"#")
objOutputFile.WriteLine strInputLine
Loop
' ------------------------------------------------------------
Function IsHexString(ByVal tmpString)
Dim blnHexString, intHexCount, intHexByte
blnHexString = True
If Len(tmpString)<>3 and Len(tmpString)<>6 Then
blnHexString = False
Else
tmpString = UCase(tmpString)
For intHexCount = 1 To Len(tmpString)
intHexByte = Asc(Mid(tmpString,intHexCount,1))
If (intHexByte < 48 Or intHexByte > 57) And (intHexByte < 65 Or intHexByte > 70) Then
blnHexString = False
End If
Next
End If
IsHexString = blnHexString
End Function
' ------------------------------------------------------------
Function InvertByte(ByVal tmpByte)
tmpByte = tmpByte And 15
tmpByte = 15 - tmpByte
InvertByte = tmpByte
End Function
' ------------------------------------------------------------
Function InvertOctet(ByVal tmpOctet)
tmpOctet = tmpOctet And 255
tmpOctet = 255 - tmpOctet
InvertOctet = tmpOctet
End Function
' ------------------------------------------------------------
Negatizing a SharePoint 2007 Theme
After I wrote the above script, I found myself using it for a bunch of different websites that I manage for other people. One of the websites that I host is based on SharePoint 2007, so I wondered how difficult it would be negatize a SharePoint 2007 theme. As it turns out, it's pretty easy. The following steps will walk you through the steps that are required to create a negatized version of the built-in "Classic" SharePoint 2007 theme.
(NOTE: The steps in this section do not work with SharePoint 2010 or office 14; SharePoint 2010 and Office 14 store their themes in a different format, so these steps will not work.)
Copy the folder:
" %CommonProgramFiles% \Microsoft Shared\Web Server Extensions\12\TEMPLATE\THEMES\CLASSIC"
To the following folder:
" %CommonProgramFiles% \Microsoft Shared\Web Server Extensions\12\TEMPLATE\THEMES\CLASSICNEGATIVE"
Rename the file:
" %CommonProgramFiles% \Microsoft Shared\Web Server Extensions\12\TEMPLATE\THEMES\CLASSICNEGATIVE\CLASSIC.INF"
To the following:
" %CommonProgramFiles% \Microsoft Shared\Web Server Extensions\12\TEMPLATE\THEMES\CLASSICNEGATIVE\CLASSICNEGATIVE.INF"
Open the following file:
" %CommonProgramFiles% \Microsoft Shared\Web Server Extensions\12\TEMPLATE\THEMES\CLASSIC\CLASSICNEGATIVE.INF"
- Replace all instances of "Classic" with "Classic Negative".
- Save and close the INF file.
Open the following file:
" %CommonProgramFiles% \Microsoft Shared\Web Server Extensions\12\TEMPLATE\LAYOUTS\1033\SPTHEMES.XML"
Add the following entry to the
<``SPThemes``>
collection:<Templates> <TemplateID>classicnegative</TemplateID> <DisplayName>Classic Negative</DisplayName> <Description>Classic Negative</Description> <Thumbnail>images/thclassic.gif</Thumbnail> <Preview>images/thclassic.gif</Preview> </Templates>
Save and close the XML file.
Edit the color negatizing WSH script from earlier in this blog for each of the following files and run it:
theme.css
Input File:
" %CommonProgramFiles% \Microsoft Shared\Web Server Extensions\12\TEMPLATE\THEMES\CLASSIC\theme.css"
Output File:
" %CommonProgramFiles% \Microsoft Shared\Web Server Extensions\12\TEMPLATE\THEMES\CLASSICNEGATIVE\theme.css"
mossExtension.css
Input File:
" %CommonProgramFiles% \Microsoft Shared\Web Server Extensions\12\TEMPLATE\THEMES\CLASSIC\mossExtension.css"
Output File:
" %CommonProgramFiles% \Microsoft Shared\Web Server Extensions\12\TEMPLATE\THEMES\CLASSICNEGATIVE\mossExtension.css"
That's all it takes to negate the colors that are defined in the CSS files for a SharePoint 2007 theme. (NOTE: This does not modify the colors of the images in the SharePoint theme; you will need a graphics program to update the colors in the images.)
Closing Thought
Before I receive any comments, I am perfectly aware that "negatize" is not an actual word in the English language, but it seemed appropriate, and new words have to start somewhere. ;-]