Notifications
Clear all

[Closed] Copy red channel to another bitmap

 PEN

Other then using get and set pixels which is really slow what method do you think is out there that I could use to get the red channel of one bitmap and paste it into another?

20 Replies

What about the new Color Correct (use this to extract the needed channels) + Composite Map (use this to combine the different maps R+G+B maps should generate what you need)?

-Eric

 PEN

I need to do this in script, it will be working in a modifier.

I’m thinking this is faster… python with the pil module…

SplitRGB.py

import Image
   import sys
   
   im = Image.open(sys.argv[1])
   (r,g,b) = im.split()
   r.save(sys.argv[1])

Save image to temp, doscommand line this py with the filename, reload the image.
You could make it pretty with a second argument to select r,g, or b…

Edit: just saw your post… yeah… this isn’t gonna work for you… time to bust out the C skills and write a function…

I would think there’s something in .net to do this… Might take you longer to find it than write your own…

 PEN

So know way with dotNet? Been digging at that and not comming up with anything.

I can’t image it’s faster… but you can try it…

Example of pixel handling in dotnet…

http://msdn.microsoft.com/en-us/library/system.drawing.image.pixelformat.aspx

 PEN

Thanks, I know of that one as well but I wouldn’t think that it is faster either, I haven’t tried it how ever. I’ll keep digging. Has to be some way to get the red channel.

Can u use the renderer? Maybe a quick scan line render. Plane, Camera, standard mat 100% lum with colormapping enabled and knock out the blue and green with the colormapping. A real hacky way to get there and it’ll degrade the image too…

how big are the images you are processing paul? how quick do you need it to be? keith’s link is a good snippet of code for this. It might be possible to do it quicker with some custom image handling classes using the lockbits method, but you would be burdened with an assembly to load in.

Try this:


--******************************************************************************
--*
--*  extractBitmapChannel
--*  by Ofer Zelichover (c) 
--*  Started: 2008/08/20
--*   http://www.oferz.com   ; maxscripts@oferz.com
--*
--******************************************************************************

(
   -- This function uses the dotNet graphics object with color matrix to extract
   -- a specific channel from a bitmap.
   -- Valid chan values: #Red, #Green, #Blue, #R, #G, #B
   fn extractBitmapChannel bm chan =
   (
	   -- Validate chan value:
	   chan = (chan as string) as name
	   local fullChanNames = #(#Red, #Green, #Blue)
	   local shortChanNames = #(#R, #G, #B)
	   local n = findItem fullChanNames chan
	   if n > 0 then
		   chan = shortChanNames[n]
	   if findItem shortChanNames chan == 0 then
		   return undefined
	   
	   -- Copy the bitmap to the clipboard to pass it to dotNet
	   setClipboardBitmap  bm
	   -- Create a dotNet clipboard object.
	   local clipboardObj = dotNetClass "System.Windows.Forms.Clipboard"
	   -- Get the image from the clipboard into a dotNet image object.
	   local imgObj = clipboardObj.GetImage()
	   -- Create a dotNet colorMatrix object.
	   local colorMatArray = #( \
		   #(if chan == #R then 1 else 0, 0, 0, 0, 0), \
		   #(0, if chan == #G then 1 else 0, 0, 0, 0), \
		   #(0, 0, if chan == #B then 1 else 0, 0, 0), \
		   #(0, 0, 0, 1, 0), \
		   #(0, 0, 0, 0, 1) 
	   )
	   local colorMatrixObj = dotNetObject "System.Drawing.Imaging.ColorMatrix" colorMatArray
	   -- Create a dotNet ImageAttributes object to assign the color matrix to the image.
	   local imageAttrsObj = dotNetObject "System.Drawing.Imaging.ImageAttributes"
	   imageAttrsObj.SetColorMatrix colorMatrixObj (dotNetClass "System.Drawing.Imaging.ColorMatrixFlag").Default (dotNetClass "System.Drawing.Imaging.ColorAdjustType").Default
	   -- Create a dotNet graphics object. This will be used to render the image using the color matrix.
	   local graphicsObj = (dotNetClass "System.Drawing.Graphics").FromImage(imgObj)
	   -- Render the image using the color matrix:
	   local rect = dotNetObject "System.Drawing.Rectangle" 0 0 imgObj.Width imgObj.Height
	   local graphicsUnit = (dotNetClass "System.Drawing.GraphicsUnit").Pixel
	   graphicsObj.DrawImage imgObj rect 0 0 imgObj.Width imgObj.Height graphicsUnit imageAttrsObj
	   -- copy the rendered image into the clipboard.
	   clipboardObj.setImage(imgObj)
	   -- Get the image from the clipboard back into maxscript
	   local newBm = getClipboardBitmap()
	   
	   --Clean up
	   clipboardObj = undefined
	   graphicsObj.Dispose(); graphicsObj = undefined
	   rect = undefined
	   graphicsUnit = undefined
	   imgObj.Dispose(); imgObj = undefined
	   imageAttrsObj.Dispose(); imageAttrsObj = undefined
	   colorMatrixObj = undefined
	   -- You may wish to comment out the GC command if it's too slow.
	   gc light:true
	   -- Return the new bitmap
	   newBM
   )
   
   -- Sample Use:
   local tex = Dent color1:red color2:blue size:5
   local bm = bitmap 200 200
   renderMap tex into:bm
   display(extractBitmapChannel bm #Red)

)

Cheers,
o

4 Replies
(@drdubosc)
Joined: 11 months ago

Posts: 0

… but I’m curious about why you choose to go via the clipboard?

(@ofer_z)
Joined: 11 months ago

Posts: 0

Because I think it’s faster than saving to a temp image and loading it again.

 PEN
(@pen)
Joined: 11 months ago

Posts: 0

Yes this is something that I didn’t want to do as I knew it would be slower to read and write.

(@drdubosc)
Joined: 11 months ago

Posts: 0

Thanks for the reply. That’s interesting. I’m still trying to get my head around where things actully reside, when they are being chucked around between a script and .net.

Page 1 / 2