Ich verwechsel immer bei Pointer zwei Sachen... Mit
byte* Pix = (byte*)(void*)RGB;
Pix += 3;
geht man einen Bildpunkt weiter und mit
Pix[0]
wählt man den RGB-Wert. Richtig?
Wie müßte dann der Code aussehen um aus Pixelzeile 27 alle R-Werte zu mitteln, wenn ein Bild 300x100 Pixel groß ist?
Hallo digi333,
wenn es nicht um das allerletzte Quäntchen Performance geht, solltest du nicht mit Pointern arbeiten, sondern bmpdNew.Scan0 mit Marshal.Copy in ein byte-Array kopieren (und ggf. später wieder zurück).
Pro Zeile des Bildes sind dann bei einem 24bit Bild 3 * Width Bytes aufgerundet auf volle 4 Bytes in dem Array enthalten. Jedes Byte steht für ein Subpixel, drei Bytes bilden ein Pixel. Wenn aufgerundet wurde, stehen am Ende einer Zeile bis zu drei Füllbytes, deren Inhalt keine Bedeutung hat. Anschließe stehen die (Sub-)Pixelwerte der folgenden Bildzeile.
Bei 3 * 300 = 900 muss nicht aufgerundet werden. Eine Bildzeile ist 900 Bytes lang. Entsprechend beginnt die 27 Zeile bei Offset (27 - 1) * 900. An diesem Offset ist der R-Wert des ersten Pixels der Zeile. Alle weiteren R Werte stehen jeweils 3 Bytes weiter rechts.
herbivore
Performance spielt leider ne große Rolle... Sagen wir mal ich müßte weiter mit Pointer arbeiten (da der Codec mir Pointer liefert)... wie kann ich weiter arbeiten. Wie wär das Problem mit den R-Werten in Pointerschreibweise???
Hallo digi333,
das Prinzip ist - ob Array oder Pointer - das gleiche, also so wie ich beschrieben habe.
herbivore
for (int y = 0; y <= ((myframe.Height / 8) - 1) / 3; y++)
{
if (...)
for (int y1 = y*16; y1 < 16; y1++)
{
for (int x1 = 0; x1 < frameWidth; x1++)
{
RTemp += Pix[(y1*3) + (x1*3)];
Pix += 3;
}
}
Ausgabe von RTemp;
}
Also in dem oberen Code habe ich das Problem, dass alle Werte von RTemp gleich sind... sollten sie aber nicht. Läßt natürlich darauf schließen, dass nicht an die richtige Stelle im Bild springe, sondern immer die gleichen Zeilen ablaufe.
Wenn du mit einem Bytepointer auf deine Farbdaten zeigst...
byte* Pix = (byte*)(void*)RGB;
...kannst du per...
Pix += 3;
...zum nächsten Farbwert (R8G8B8 => 3 Byte / Pixel) springen, und per...
byte r = *pix;
byte g = *(pix+1);
byte b = *(pix+2);
...oder per []-Operator...
byte r = Pix[ 0 ];
byte g = Pix[ 1 ];
byte b = Pix[ 2 ];
...auf die aktuellen drei Farbkomponenten zugreifen (voraussetzung ist das die Farbkanäle wirklich in der Form R G B angeordnet sind).
Da du ein eindimensionalen Array hast kannst du über Pix[ 273003 ] zum ersten Farbwert der Scanline 27 springen (=> Pixel(x,y) = Pix[y*width+x]). Dann kannst du per Schleife durch die Farbwerte iterieren und jeweils die erste Komponente auslesen:
Ungetestet:
byte* p = &Pix[ 27*300*3 ];
float sum = 0;
for ( int i = 0; i < 100; i++, p += 3 )
{
sum += *p;
}
sum *= 0.01f; // p1+p2+p3+...+p100 / 100
Das is ja mal einer sehr ausführliche Hilfe. In deinen Erklärungen sind genau die zwei Hauptfragen drinne, die ich immer habe... ist Pix[3] das gleiche wie Pix[0] vom zweiten Pixel? und wie ist unterschied zwischen []-Operator und *Wert?
Trotzdem mach ich in meinem Code was falsch... wie gesagt, die Werte ändern sich nicht.
Original von digi333
die ich immer habe... ist Pix[3] das gleiche wie Pix[0] vom zweiten Pixel?
Genau! Der Aufbau des Arrays sieht ja folgend aus:
0 R
1 G
2 B
3 R
4 G
5 B
6 R
7 G
8 B
9 R
10 G
11 B
Je drei Byte entsprechen einen Pixel (drei Farbkanäle á 1 Byte pro Kanal). D.h. die Rotwerte der Pixel sind an den Indice 0, 3, 6, 9 zu finden.
Original von digi333
und wie ist unterschied zwischen []-Operator und *Wert?
In der Zeigerarithmetik bedeutet Beides, das der Zeiger dereferenziert wird (du bekommst den gezeigten Wert zurück). Beim []-Operator kannst du zusätzlich den Index angeben. Entsprechend wäre
p[ 0 ] => *( p+0 );
p[ 1 ] => *( p+1 );
p[ 2 ] => *( p+2 );
...
p[ n ] => *( p+n );
Gruß
Hallo digi333,
ist Pix[3] das gleiche wie Pix[0] vom zweiten Pixel?
ja
und wie ist unterschied zwischen []-Operator und *Wert?
p_ ist das gleiche wie *(p+i)
herbivore