質問

I need your assistance with converting the code into Visual Basic 6.0, I transformed all the code from visual C# 2008 however, the resulting picture is not a true colored image, the image should be brighter than before.

The VB 6.0 Code:

Public Sub White(bmp As PictureBox)
Dim levelR(256) As Double
Dim levelG(256) As Double
Dim levelB(256) As Double
Dim color As Pixel
'claculates levels
For y = 0 To bmp.ScaleHeight - 1
        For x = 0 To bmp.ScaleWidth - 1
            color = LongToPix(GetPixel(bmp.hdc, x, y))
            levelR(color.Red) = levelR(color.Red) + 1
            levelG(color.Green) = levelG(color.Green) + 1
            levelB(color.Blue) = levelB(color.Blue) + 1
        Next x
Next y
'calculates probibality
Dim pixelsCount As Double
Dim pR_level(256) As Double
Dim pG_level(256) As Double
Dim pB_level(256) As Double

pixelsCount = bmp.ScaleWidth * bmp.ScaleHeight

For I = 0 To 256
pR_level(I) = levelR(I) / pixelsCount
pG_level(I) = levelG(I) / pixelsCount
pB_level(I) = levelB(I) / pixelsCount
Next I

'compute cumulative probabilities
Dim pR_total(256) As Double
Dim pG_total(256) As Double
Dim pB_total(256) As Double
pR_total(0) = pR_level(0)
pG_total(0) = pG_level(0)
pB_total(0) = pB_level(0)
'compute reference black and white levels
    For m = 1 To 256
                pR_total(m) = pR_total(m - 1) + pR_level(m)
                pG_total(m) = pG_total(m - 1) + pG_level(m)
                pB_total(m) = pB_total(m - 1) + pB_level(m)
    Next m
    Dim K As Integer
Dim refBR As Integer
Dim refWR As Integer
Dim refBG As Integer
Dim refWG As Integer
Dim refBB As Integer
Dim refWB As Integer
            refBR = -1
            refWR = -1
            refBG = -1
            refWG = -1
            refBB = -1
            refWB = -1
                For K = 0 To 256
                If refBR = -1 And pR_total(K) > 0.05 Then
                    refBR = K
                End If
                If refWR = -1 And pR_total(K) > 0.95 Then
                    refWR = K
                    End If
                If refBG = -1 And pG_total(K) > 0.05 Then
                    refBG = K
                    End If
                If refWG = -1 And pG_total(K) > 0.95 Then
                    refWG = K
                    End If
                If refBB = -1 And pB_total(K) > 0.05 Then
                    refBB = K
                    End If
                If refWB = -1 And pB_total(K) > 0.95 Then
                    refWB = K
                    End If
                Next K
'calculation level stretching table
Dim gR(256) As Byte
Dim gG(256) As Byte
Dim gB(256) As Byte
Dim J As Integer
For J = 0 To 256
gR(J) = transformLevel(J, refBR, refWR)
gG(J) = transformLevel(J, refBG, refWG)
gB(J) = transformLevel(J, refBB, refWB)
Next J
'transform components of source pixels according to the stretching table
For y = 0 To bmp.ScaleHeight - 1
      For x = 0 To bmp.ScaleWidth - 1
            color = LongToPix(GetPixel(bmp.hdc, x, y))
        'SetPixel Form1.WhitePic.hdc, x, y, RGB(gR(color.Red), gG(color.Green), gB(color.Blue))
        Form1.WhitePic.PSet (x, y), RGB(gR(color.Red), gG(color.Green), gB(color.Blue))
        Next x
Next y



End Sub
Private Function transformLevel(f As Integer, refB As Integer, refW As Integer) As Byte
If f <= refB Then
    transformLevel = 0
    Exit Function
    End If

            '// Math.Log(refW) will produce 0 in denominator if refW <= 1, so check
If f >= refW Or refW <= 1 Then
    transformLevel = 255
    Exit Function
End If
If refB > 0 Then lnRefB = Log(refB) Else G = (Log(f) - lnRefB) / (Log(refW) - lnRefB)
transformLevel = 255 * G
Exit Function
End Function

The C# code I converted from is :

public static Bitmap White(Bitmap sourceBitmap)
{
    var bitmap = new Bitmap(sourceBitmap);
    // Step2: calculate levels
    int[] levelR = new int[256];
    int[] levelG = new int[256];
    int[] levelB = new int[256];
    for (int y = 0; y < bitmap.Height; ++y)
    {
        for (int x = 0; x < bitmap.Width; ++x)
        {
            Color c = bitmap.GetPixel(x, y);
            ++levelR[c.R];
            ++levelG[c.G];
            ++levelB[c.B];
        }
    }

    // Step3: calculate probabilities
    int pixelsCount = bitmap.Width * bitmap.Height;
    double[] pR_level = new double[256];
    double[] pG_level = new double[256];
    double[] pB_level = new double[256];
    for (int i = 0; i < 256; ++i)
    {
        pR_level[i] = levelR[i] / (double)pixelsCount;
        pG_level[i] = levelG[i] / (double)pixelsCount;
        pB_level[i] = levelB[i] / (double)pixelsCount;
    }

    // Step4: compute cumulative probabilities
    double[] pR_total = new double[256];
    double[] pG_total = new double[256];
    double[] pB_total = new double[256];
    pR_total[0] = pR_level[0];
    pG_total[0] = pG_level[0];
    pB_total[0] = pB_level[0];
    for (int i = 1; i < 256; ++i)
    {
        pR_total[i] = pR_total[i - 1] + pR_level[i];
        pG_total[i] = pG_total[i - 1] + pG_level[i];
        pB_total[i] = pB_total[i - 1] + pB_level[i];
    }

    // Step5: compute reference black and white levels
    int refBR = -1;
    int refWR = -1;
    int refBG = -1;
    int refWG = -1;
    int refBB = -1;
    int refWB = -1;
    for (int i = 0; i < 256; ++i)
    {
        if (refBR == -1 && pR_total[i] > 0.05)
            refBR = i;
        if (refWR == -1 && pR_total[i] > 0.95)
            refWR = i;
        if (refBG == -1 && pG_total[i] > 0.05)
            refBG = i;
        if (refWG == -1 && pG_total[i] > 0.95)
            refWG = i;
        if (refBB == -1 && pB_total[i] > 0.05)
            refBB = i;
        if (refWB == -1 && pB_total[i] > 0.95)
            refWB = i;
    }

    // Step6.1: calculation level stretching table
    byte[] gR = new byte[256];
    byte[] gG = new byte[256];
    byte[] gB = new byte[256];
    for (int i = 0; i < 256; ++i)
    {
        gR[i] = transformLevel(i, refBR, refWR);
        gG[i] = transformLevel(i, refBG, refWG);
        gB[i] = transformLevel(i, refBB, refWB);
    }
    // Step6.2: transform components of source pixels according to the stretching table
    for (int y = 0; y < bitmap.Height; ++y)
    {
        for (int x = 0; x < bitmap.Width; ++x)
        {
            Color c = bitmap.GetPixel(x, y);
            bitmap.SetPixel(x, y, Color.FromArgb(gR[c.R], gG[c.G], gB[c.B]));
        }
    }
    return bitmap;
}
private static byte transformLevel(int f, int refB, int refW)
{
    if (f <= refB)
        return 0;
    // Math.Log(refW) will produce 0 in denominator if refW <= 1, so check 
    if (f >= refW || refW <= 1)
        return 255;
    double lnRefB = refB > 0 ? Math.Log(refB) : 0;
    double g = (Math.Log(f) - lnRefB) / (Math.Log(refW) - lnRefB);
    return (Byte)(255 * g);
}
役に立ちましたか?

解決

There are two main problems with your code:

  • Array bounds - In VB6 the number in brackets when you declare an array is the top boundary, not the number of elements. The lower boundary is going to be 0 or 1 by default, depending on the Option Base setting. It is a good practice to always provide both lower and upper bounds.
  • Image size - you are using ScaleWidth of the picturebox which you should not.
    First, it is the width of the control, which may not be equal to the width of the contained image.
    Second, the ScaleWidth property depends on the parent's ScaleMode whereas you want it to always give the result in pixels. So you should be using bmp.ScaleX(bmp.Image.Width, vbHimetric, vbPixels) instead, which will always give correct width in correct units.

Also, I bet you have not set AutoRedraw to True for your picture box - you must, otherwise the below code will do nothing.

Private Declare Function GetPixel Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function SetPixel Lib "gdi32.dll" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long) As Long

Private Type ColorRefComponents
  Red As Byte
  Green As Byte
  Blue As Byte
  Alpha As Byte
End Type

Private Type ColorRefSolid
  Color As Long
End Type


Public Sub White(ByVal bmp As PictureBox)
  Dim levelR(0 To 255) As Double
  Dim levelG(0 To 255) As Double
  Dim levelB(0 To 255) As Double

  Dim Color As ColorRefComponents
  Dim ColorSolid As ColorRefSolid

  Dim WidthInPixels As Long
  Dim HeightInPixels As Long
  WidthInPixels = bmp.ScaleX(bmp.Image.Width, vbHimetric, vbPixels)
  HeightInPixels = bmp.ScaleY(bmp.Image.Height, vbHimetric, vbPixels)

  'claculates levels
  Dim x As Long, y As Long
  For y = 0 To HeightInPixels - 1
    For x = 0 To WidthInPixels - 1
      ColorSolid.Color = GetPixel(bmp.hdc, x, y)
      LSet Color = ColorSolid

      levelR(Color.Red) = levelR(Color.Red) + 1
      levelG(Color.Green) = levelG(Color.Green) + 1
      levelB(Color.Blue) = levelB(Color.Blue) + 1
    Next
  Next

  'calculates probibality
  Dim pixelsCount As Double
  Dim pR_level(0 To 255) As Double
  Dim pG_level(0 To 255) As Double
  Dim pB_level(0 To 255) As Double

  pixelsCount = WidthInPixels * HeightInPixels

  Dim i As Long
  For i = 0 To 255
    pR_level(i) = levelR(i) / pixelsCount
    pG_level(i) = levelG(i) / pixelsCount
    pB_level(i) = levelB(i) / pixelsCount
  Next

  'compute cumulative probabilities
  Dim pR_total(0 To 255) As Double
  Dim pG_total(0 To 255) As Double
  Dim pB_total(0 To 255) As Double
  pR_total(0) = pR_level(0)
  pG_total(0) = pG_level(0)
  pB_total(0) = pB_level(0)

  'compute reference black and white levels
  For i = 1 To 255
    pR_total(i) = pR_total(i - 1) + pR_level(i)
    pG_total(i) = pG_total(i - 1) + pG_level(i)
    pB_total(i) = pB_total(i - 1) + pB_level(i)
  Next

  Dim refBR As Long
  Dim refWR As Long
  Dim refBG As Long
  Dim refWG As Long
  Dim refBB As Long
  Dim refWB As Long
  refBR = -1
  refWR = -1
  refBG = -1
  refWG = -1
  refBB = -1
  refWB = -1

  For i = 0 To 255
    If refBR = -1 And pR_total(i) > 0.05 Then refBR = i
    If refWR = -1 And pR_total(i) > 0.95 Then refWR = i
    If refBG = -1 And pG_total(i) > 0.05 Then refBG = i
    If refWG = -1 And pG_total(i) > 0.95 Then refWG = i
    If refBB = -1 And pB_total(i) > 0.05 Then refBB = i
    If refWB = -1 And pB_total(i) > 0.95 Then refWB = i
  Next

  'calculation level stretching table
  Dim gR(0 To 255) As Byte
  Dim gG(0 To 255) As Byte
  Dim gB(0 To 255) As Byte
  For i = 0 To 255
    gR(i) = transformLevel(i, refBR, refWR)
    gG(i) = transformLevel(i, refBG, refWG)
    gB(i) = transformLevel(i, refBB, refWB)
  Next

  'transform components of source pixels according to the stretching table
  For y = 0 To HeightInPixels - 1
    For x = 0 To WidthInPixels - 1
      ColorSolid.Color = GetPixel(bmp.hdc, x, y)
      LSet Color = ColorSolid

      Color.Red = gR(Color.Red)
      Color.Green = gG(Color.Green)
      Color.Blue = gB(Color.Blue)

      LSet ColorSolid = Color

      SetPixel bmp.hdc, x, y, ColorSolid.Color
    Next
  Next

  bmp.Refresh
End Sub
Private Function transformLevel(ByVal f As Long, ByVal refB As Long, ByVal refW As Long) As Byte
  Select Case True
  Case f <= refB
    transformLevel = 0
  Case f >= refW Or refW <= 1
    transformLevel = 255
  Case Else
    'Math.Log(refW) will produce 0 in denominator if refW <= 1, so check
    Dim lnRefB As Double
    If refB > 0 Then lnRefB = Log(refB) Else lnRefB = 0

    Dim G As Double
    G = (Log(f) - lnRefB) / (Log(refW) - lnRefB)

    transformLevel = 255 * G
  End Select
End Function

他のヒント

I can't say if it is the answer (do not have VB around to test)

But C#: for (int i = 1; i < 256; ++i)

Is in VB: For i = 1 To 255

Where as in your code (For m and For K) you go up to 256

I am a bit foggy-headed right now but there are some important things to pay attention to:

declaring arrays in C# and VB6 is different. The following code will produce the same array:

C#

int[] numbers = new int[5];

VB6

Dim numbers(4) As Integer

Are you a VB6 programmer or a C# programmer ?

Pay attention to the difference between y++ and ++y in C# in your loops as it might perform the calculation on different elements than you expect, and exit the loop sooner or later than you expect.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top