Forum: Mikrocontroller und Digitale Elektronik Einzelne Bytes weglassen


von Hier nicht angemeldet (Gast)


Lesenswert?

Hallo Formmitglieder und Besucher,

ich habe folgendes Problem, bitte fragt nicht, warum ich das brauche. 
Bin noch am Probieren.

Ich habe eine Variable mit Länge 100
uint16_t (Bild) [100] = {....};

In möchte je nach externer Voraussetzung einige "short" (damit meine ich 
die 2x char, da Variable 16 bit lang ist) weglassen.
Der Trick dabei ist, die weg gelassenen Daten sollen über die ganze 
(100) Länge möglichst gleichmäßig verteilt werden.

Beispiel:
Möchte ich nur die Hälfte haben, nehme ich jeden 2. uint16_t.
Möchte ich 25% haben, nehme ich jeden 4. uint16_t.

Was muss ich machen, damit ich beispielsweise 42% bekomme?
die ersten 42 uint16 weg zu machen geht nicht. Die müssen gleichmäßig 
auf die ganze "Datei" verteilt sein.

Vielen Dank im Voraus für konstruktive Ideen.

von Sebastian S. (amateur)


Lesenswert?

In einem Array ...[100] kann man zwar Werte uninitialisiert lassen, aber 
nicht auslassen.

Irgendetwas steht immer in den Zellen. Ob Dir der jeweilige Wert gefällt 
ist eine andere Sache.

Was für ein Unsinn entsteht, wenn nicht zusammenpassende Teiler 
vorkommen, kannst Du selber sehr einfach feststellen: Zähle einfach an 
den Fingern bis 4 und dann nochmal und dann (beim 3. Mal) musst Du Dir 
wenigstens zwei Finger borgen...

von Hier nicht angemeldet (Gast)


Lesenswert?

>Irgendetwas steht immer in den Zellen. Ob Dir der jeweilige Wert gefällt
>ist eine andere Sache.
Ganz klar.
Ich möchte ein Bild langsam unsichtbar machen.

Das bedeutet die Bilddateien, die zum Display geschickt werden sind 
zuerst komplett da.
Danach möchte ich langsam Schritt für Schritt immer mehr Pixel 
weglassen.
  ++++++++++
  ++++++++++
  ++++++++++
  ++++++++++
  ++++++++++
  ++++++++++
  ++++++++++

^^ komplettes Bild

  ++ ++++ ++
  +++ ++ +++
  + +++++ ++
  +++ +++++
  + ++++++++
  ++++++ +++
  ++++ +++++
^^ Bild mit weniger Pixeln, bzw anders gesagt, die Pixel werden durch 
weiße Farbe ersetzt.

Ich möchte nun ausrechnen, wo die weißen Pixel sein sollen damit die 
möglichst gleichmäßig im Bild verteilt sind.

von Frank K. (fchk)


Lesenswert?

Hier nicht angemeldet schrieb:

> Was muss ich machen, damit ich beispielsweise 42% bekomme?
> die ersten 42 uint16 weg zu machen geht nicht. Die müssen gleichmäßig
> auf die ganze "Datei" verteilt sein.

Stichwort Bresenham Algorithmus. Wird auch zum Linienzeichnen in 
beliebigen Winkeln verwendet.

fchk

von Hier nicht angemeldet (Gast)


Lesenswert?

man kann doch unmöglich das komplette Gerät beschreiben.
Ich versuche das vereinfacht:
Eine Bilddatei (Firmenlogo) liegt im EEPROM und chillt dort, bis ich 
damit was machen möchte.
Die Datei ist paar KB groß.

Beim Ausschalten des Gerätes soll das Logo angezeigt werden, in dem die 
Daten aus der eeprom Adresse für Adresse ausgelesen werden und zum 
Display geschickt werden.
Zuerst erscheint im Display das komplette Bild.
Danach sollen immer mehr Pixel durch schwarze Pixel ersetzt werden, bis 
das Bild verschwunden ist.
Das Ganze soll etwa 1,5 sekunden dauert (<- wobei das schon komplett 
egal ist ist).
Der Plan war, das Bild immer wieder zum Display zu schicken, wo immer 
mehr schwarze Pixeln drin sind.

Die Daten werden aus dem eeprom gelesen und gleich zum Display 
geschickt.
Also muss ich bereits beim Auslesen wissen, ob ich den Wert aus der 
aktuellen eepromadresse durch schwarzen Pixel ersetzen soll.

Anderer Ansatz wäre, viele Bilder an PC zu erstellen, wo immer mehr 
Pixel schwarz sind, aber das ist Platzverschwendung im eeprom.

Ich hoffe, es ist nun verständlich, was ich meine.

von spess53 (Gast)


Lesenswert?

Hi

>Eine Bilddatei (Firmenlogo) liegt im EEPROM und chillt dort, bis ich
>damit was machen möchte.
>Die Datei ist paar KB groß.

An welcher Hilfsschule hast du Programmieren 'gelernt'? So etwas mache 
ich in Assembler.

Außerdem fehelen wichtige Informationen. Z.B. ist das Display lesbar?

MfG Spess

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Da wuerd' ich mir eine Pseudonoisefolge generieren und damit dann die zu 
schwaerzenden Pixel "herausfinden". Dadurch, dass es "Pseudo" Noise ist, 
kannst du sicherstellen, dass nach X Schritten das gesamte Bild schwarz 
ist.

Gruss
WK

von Hier nicht angemeldet (Gast)


Lesenswert?

spess53 schrieb:
> Außerdem fehelen wichtige Informationen. Z.B. ist das Display lesbar?

Das Display ist nicht lesbar.
Wie das Display genau funktioniert weiß ich gar nicht so richtig.
Um das Display kümmert sich ein anderes Team.
Wir haben einfach die Schnittstelle abgesprochen.
Welche Befehle was mit dem Display machen.

Das Display bekommt eine eigene Platine, um die sich eine andere Gruppe 
der Menschen kümmert.
Eigentlich gar nicht nötig, aber es sollten mehrere Teams gebildet 
werden.

von Flo85 (Gast)


Lesenswert?

Hier nicht angemeldet schrieb:

> Der Plan war, das Bild immer wieder zum Display zu schicken, wo immer
> mehr schwarze Pixeln drin sind.

Warum so kompliziert? Kann man auf diesem LCD keine einzelnen Pixel 
setzen? Selbst wenn nur immer einen gewissen Bereich schreiben kann, 8 
Pixel zB, wäre es doch viel einfacher immer einen gewissen Bereich zu 
lesen, ein Pixel zu ändern und dann nur diese 8 wieder zu senden.

Welches LCD verwendest du?

von Flo85 (Gast)


Lesenswert?

Hier nicht angemeldet schrieb:

> Um das Display kümmert sich ein anderes Team.
> Wir haben einfach die Schnittstelle abgesprochen.

Und was läst diese Schnittstelle alles zu? Ja doch hoffentlich nicht nur 
ein ganzes Bild zu senden.

von Schlechter Programmierer (Gast)


Lesenswert?

Flo85 schrieb:
> Und was läst diese Schnittstelle alles zu? Ja doch hoffentlich nicht nur
> ein ganzes Bild zu senden.

Da wir alle Anfänger sind, leider ja.
Es gibt ein Befehl für den Text, dann zum Display löschen und halt für 
die Grafik.
Grafik ist einfach als Datenstrom definiert.
Das heißt alle Bilddateien von Anfang bis Ende. Die Displayplatine macht 
den Rest.
Welches Display das genau ist, kann ich leider nicht sagen, ist nicht 
mein Part.
Ist das wirklich nicht mit einer "for schleife und zweidimensionalem 
Array" zu lösen?
Das ist nicht der Kern des Projektes, daraus sollte keine Doktorarbeit 
gemacht werden.
Quick and dirty, etwas Spielerei für Auge.

von Hier nicht angemeldet (Gast)


Lesenswert?

Danke
So ist das.

von Rolf M. (rmagnus)


Lesenswert?

spess53 schrieb:
>>Eine Bilddatei (Firmenlogo) liegt im EEPROM und chillt dort, bis ich
>>damit was machen möchte.
>>Die Datei ist paar KB groß.
>
> An welcher Hilfsschule hast du Programmieren 'gelernt'?

Wie kommst du darauf, dass er es gelernt hat und nicht gerade dabei ist, 
es zu lernen?

> So etwas mache ich in Assembler.

Er hat nicht nach einer Sprache gefragt, sondern nach einem Algorithmus.

> Außerdem fehelen wichtige Informationen. Z.B. ist das Display lesbar?

Hä? Warum sollte die wichtig sein für die Frage, wie man am besten eine 
einigermaßen gleichmäßige Verteilung der "weggelassenen" Pixel erreicht?

Die einzige bisher sinnvolle Antwort:

Frank K. schrieb:
> Stichwort Bresenham Algorithmus. Wird auch zum Linienzeichnen in
> beliebigen Winkeln verwendet.

Hier nicht angemeldet schrieb:
> Was muss ich machen, damit ich beispielsweise 42% bekomme?

Du legst eine Zählvariable an. Dann gehst du durch dein Array Element 
für Element durch. Für jedes Element addierst du 42 zu der Zählvariable. 
Danach machst du einen Vergleich: Wenn die Variable kleiner als 100 ist, 
nimmst du den Pixel und machst weiter. Wenn sie dagegen 100 oder größer 
ist, ziehst du 100 von ihr ab und läßt den Pixel weg. So gehst du durch 
dein ganzes Array durch. Am Ende hast du auf diese Weise 42% der Pixel 
in so regelmäßigen Abständen, wie es geht, weggelassen.

von Mimin I. (kahlenberg)


Lesenswert?

Zufällige Adressen für Display-Punkten generieren und einfach 0 senden 
für schwarze Farbe.

von Hier nicht angemeldet (Gast)


Lesenswert?

@ Rolf
Danke, du hast das richtig verstanden!
Ich werde das morgen genauer lesen und versuchen um zu setzen.
Klingt komplett logisch und machbar so.

von Jalob (Gast)


Lesenswert?

Das Logo hat N Pixel, nimm eine Primzahl P < N.

for ( x = 0, i = 0; i < N, i++ )
{   Pixel(x) = SCHWARZ;
    x = (x + P) % N;
}

von Jalob (Gast)


Lesenswert?

Upps,
um halbwegs C-konform zu bleiben, muss es natürlich heißen:

    Pixel[x] = SCHWARZ;

Ansonsten ist es mehr als Algorithmus-Vorschlag gedacht, weil
von so einem Pixel natürlich alle Farbkanäle (oft 3 Byte) auf
den SCHWARZ-Wert gesetzt werden müssen...

von Alex (Gast)


Lesenswert?

Jalob schrieb:
> Das Logo hat N Pixel, nimm eine Primzahl P < N.
>
> for ( x = 0, i = 0; i < N, i++ )
> {   Pixel[x] = SCHWARZ;
>     x = (x + P) % N;
> }

Hallo Jalob,

kannst du das für mich bitte erklären?
Wo ist in der Gleichung die Menge als Variable, die weg gelassen werden 
soll?
Der TE wollte Beispielsweise 42% weg haben.
Nur so, weil ich die Logik verstehen will.

Gruß Alex

von Hier nicht angemeldet (Gast)


Lesenswert?

@ Rolf Magnus
Vielen Dank nochmals!
Wir haben das so umgesetzt und es hast gleich beim ersten Mal 
funktioniert.

von Jalob (Gast)


Lesenswert?

Hey Alex, ich dachte, das erkennt man "mit bloßem Auge".
Also dann:

Das Logo hat N Pixel, nimm eine Primzahl P < N
und einen Endwert E = N * 0,42.

for ( x = 0, i = 0; i < E, i++ )
{   Pixel[x] = SCHWARZ;
    x = (x + P) % N;
}

Die Primzahlgeschichte sieht nicht aufregend "zufällig" aus,
hat aber den Vorteil, dass jedes Mal ein neues Pixel
getroffen wird, so dass nach N Schritten wirklich alles
weg ist. Und nach N/2 Schritten genau die Hälfte...

Mit echten (und auch fast immer bei Pseudo-)Zufallszahlen
wird die Trefferrate für nicht schon vorher geschwärzte Pixel
mit dem Ablauf immer kleiner. -> Schwer vorhersagbar, wann 42%
getroffen wurden.

Es gibt aber schöne Ausnahmen:
Die Anzahl der Pixel N lässt sich als 2^n (n ist eine positive
Ganzzahl) darstellen. Z.B. 256, 512, ... 16384.

Ein LFSR mit der Lauflänge L = N - 1 würde auch mit jedem
Schritt genau ein Pixel löschen, die optische Wirkung ist von
Zufall kaum zu unterscheiden!

Klitzekleiner Nachteil: Die NULL ist verboten, Pixel[0]
muss also irgendwann "von Hand" gelöscht werden.

Ist die Lauflänge L größer, als die Pixelzahl, funktioniert
das auch noch recht gut. Allerdings darf man NICHT Löschen, wenn
x >= N ist!!!

42% erreichst du ZIEMLICH GENAU, wenn i bis 42% von L zählt.
100% (außer der NULL) sind erreicht, wenn i bis L-1 gezählt hat.

von Bülent C. (mirki)


Lesenswert?


von Jobst Q. (joquis)


Lesenswert?

Die Frage ist, ob geänderte Pixel so bleiben sollen oder nicht. Ob das 
Bild beim Verschwinden flimmern soll/darf oder nicht.

Wenn es nicht flimmern soll, braucht man eine feste Reihenfolge, in der 
die Pixel auftauchen oder verschwinden sollen. Dafür ist es dabei 
unwesentlich, ob im Zustand 42 oder anderen die Pixel haargenau optimal 
verteilt sind, da das Auge sowieso nicht so schnell hinterher kommt.

Das erste Pixel wäre zB das in der Mitte. Das zweite das in der Mitte 
der ersten Hälfte, das dritte in der Mitte der zweiten Hälfte. Im 
Zustand 2 wäre die Verteilung nicht ausgeglichen, sondern asymmetrisch. 
Das macht aber nichts, da unmittelbar darauf der ausgeglichene Zustand 3 
folgt.

Ich habe das mal mit Kreisen gemacht. Eine Tabelle der Pixel angelegt, 
sortiert nach der Entfernung von einem Mittelpunkt. Dann die Pixel 
allmählich nach dieser Tabelle gesetzt. Der Effekt war verblüffend. 
Obwohl das Display ziemlich pixelig war, schien der Kreis ganz 
kontiuierlich zu wachsen.

von chris_ (Gast)


Lesenswert?

Bei Bildern verwendet man für so etwas eher "Dithering":

https://de.wikipedia.org/wiki/Dithering_(Bildbearbeitung)

Das bei den Displays mit geringer Pixelzahl oder Schwarz-Weiß-Displays, 
die Graustufen darstellen sollten, recht üblich.
Wenn Du in Google "Bild Dithering" eingibst, kannst Du Dir in der 
Bildersuche die Wirkung anschauen.
Ich vermute, dass ein gleichmäßiges Muster keine schöne Wirkung haben 
wird.

Es gibt gut beschriebene Algorithmen dafür:
https://de.wikipedia.org/wiki/Floyd-Steinberg-Algorithmus

Du könntest Dein Schwarz-Weiß Bild als Graustufenbild betrachten und 
dann einfach schrittweise die Helligkeit verringern und per Dithering 
neu zeichnen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.