Einzelne Bytes weglassen

Gast #4728945
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.
#4728967
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...
Gast #4728974
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.
Gast #4728993
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.
Gast #4729017
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
Gast #4729032
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.
Gast #4729052
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?
Gast #4729071
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.
#4729120
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.
Gast #4729155
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...
Gast #4729714
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
Gast #4729957
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.
#4730419
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.
Gast #4730431
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren