Welcome Guest Search | Active Topics | Members

HOWTO: How to apply a threshold like Photoshop Options
CGbitmap
Posted: Friday, October 03, 2008 1:51:54 PM
Rank: Newbie
Groups: Member

Joined: 10/3/2008
Posts: 3
Points: 9
Hello,

I am using Graphics Mill version 4.

My problem is I need to clamp all the data in CMYK channels to either 0 or 100%. So I copy the channel bitmap data to another bitmap object, do a levels color reduction, then copy the bitmap data into the appropriate channel in the CMYK image.

Code:

Dim channelData As New Aurigma.GraphicsMill.BitMap

channelData = image.Channels(Aurigma.GraphicsMill.ColorChannel.Black)
channelData.ColorAdjustment.Levels( _
    0.0, 1.0, 0.499999, 5.0, 0.500001, Aurigma.GraphicsMill.HistogramMode.Luminosity)
image.Channels(Aurigma.GraphicsMill.ColorChannel.Black) = channelData

channelData = image.Channels(Aurigma.GraphicsMill.ColorChannel.Yellow)
channelData.ColorAdjustment.Levels( _
    0.0, 1.0, 0.499999, 5.0, 0.500001, Aurigma.GraphicsMill.HistogramMode.Luminosity)
image.Channels(Aurigma.GraphicsMill.ColorChannel.Yellow) = channelData

channelData = image.Channels(Aurigma.GraphicsMill.ColorChannel.Magenta)
channelData.ColorAdjustment.Levels( _
    0.0, 1.0, 0.499999, 5.0, 0.500001, Aurigma.GraphicsMill.HistogramMode.Luminosity)
image.Channels(Aurigma.GraphicsMill.ColorChannel.Magenta) = channelData

channelData = image.Channels(Aurigma.GraphicsMill.ColorChannel.Cyan)
channelData.ColorAdjustment.Levels( _
    0.0, 1.0, 0.499999, 5.0, 0.500001, Aurigma.GraphicsMill.HistogramMode.Luminosity)
image.Channels(Aurigma.GraphicsMill.ColorChannel.Cyan) = channelData


This works pretty good, but the Levels ColorAdjustment *always* applies a FloydSteinberg dither, which gives little stray pixels across the image that wouldn't be there it I normally just clamp all the pixel values based on 0 <= .5 > 1.0

A simple Threshold filter will give me what I am looking for.

Is this possible in version 4 without iterating through all the pixel data manually?

Thanks for your response.
Dmitry
Posted: Monday, October 06, 2008 10:52:56 PM
Rank: Advanced Member
Groups: Administration , Member

Joined: 8/3/2003
Posts: 607
Points: 651
Hello,

This functionality is not available in Graphics Mill but you can easily implement it. All you need is to copy pixels from on bitmap into another one applying threshold. The article Accessing Pixel Data will help you to implement this functionality.

Sincerely yours,
Dmitry Sevostyanov.
CGbitmap
Posted: Tuesday, October 07, 2008 12:13:38 PM
Rank: Newbie
Groups: Member

Joined: 10/3/2008
Posts: 3
Points: 9
Thank you for the tip. This works much better than I had originally guessed it would perform.
CGbitmap
Posted: Wednesday, October 08, 2008 7:00:17 PM
Rank: Newbie
Groups: Member

Joined: 10/3/2008
Posts: 3
Points: 9
In the interest of giving back to the forum, here is the subroutine that I made to do a threshold filter per your suggestion. Note that this subroutine assumes a 8bppGrayScale bitmap. I did it this way because I am processing individual CMYK channels. With a bit of work, this threshold subroutine could be modified to work on any bitmap.

Code:
    Public Sub ApplyThreshold(ByRef bitmap As Aurigma.GraphicsMill.Bitmap, ByVal threshold As Integer)

        ' Get and lock the raw data for the bitmap
        Dim data As Aurigma.GraphicsMill.BitmapData = bitmap.LockBits()

        ' How many bytes one pixel occupies
        Dim pixelSize As Integer = data.BitsPerPixel / 8

        ' Number of bytes in a row
        Dim stride As Integer = data.Stride

        ' Number of rows
        Dim height As Integer = data.Height

        ' Pointer to the beginning of the pixel data region
        Dim pointer As IntPtr = data.Scan0

        ' Array to represent a single pixel
        Dim pixel(pixelSize - 1) As Byte

        Dim i, j As Integer
        For i = 0 To height - 1
            j = 0
            Do While j < stride
                ' Read a single pixel
                Marshal.Copy(pointer, pixel, 0, pixelSize)
                ' Now modify the pixel, in this case clamp to 0 or max based on the threshold value
                If pixel(0) > threshold Then
                    pixel(0) = 255
                Else
                    pixel(0) = 0
                End If

                ' Write back the pixel data
                Marshal.Copy(pixel, 0, pointer, pixelSize)

                ' Compute the memory location of the next pixel
                pointer = IntPtr.op_Explicit(pointer.ToInt32 + pixelSize)
                j = j + pixelSize
            Loop
        Next i

        bitmap.UnlockBits(data)

    End Sub
Dmitry
Posted: Thursday, October 09, 2008 6:13:01 AM
Rank: Advanced Member
Groups: Administration , Member

Joined: 8/3/2003
Posts: 607
Points: 651
Thank you very much for your sample. I move this post to Knowledge base.

Sincerely yours,
Dmitry Sevostyanov.
Users browsing this topic
Guest


Forum Jump
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Main Forum RSS : RSS

YAFVision Theme Created by Jaben Cargman (Tiny Gecko)
Yet Another Forum.net version 1.9.1.6 running under Cuyahoga.
Copyright © 2003-2006 Yet Another Forum.net. All rights reserved.