Jump to content

cmiN

Active Members
  • Posts

    1609
  • Joined

  • Last visited

  • Days Won

    27

Everything posted by cmiN

  1. Tot .bmp salveaza, dar daca modificam extensia imi dadea bataie de cap fisierul, pentru ca daca avea extensie diferita trebuia sa sterg sursa si sa-l las pe asta nou, fiindca as fi avut 2 fisiere pe urma din cauza extensiei ce diferea. Oricum pe windows nu face galagie, iar pe slackware o sa testez dupa ce mi-l pun si eu, dar dupa comportament e clar ca da o eroare undeva. Aveti grija la versiunea de PIL sau cum e instalata ca pe unele distributii nu au decodere. M-am chinuit cu PIL pentru ceva mai multa compatiblitate si pentru un alt mod de scriere a bitilor fata de celelalte softuri de genul. Cand o sa lansez versiune finala o sa-l "inghet" pentru win intr-o arhiva. Multumesc tuturor .
  2. Pune-i extensia .py in caz de ai .pyw (ca sa-ti afiseze consola) si vezi daca da in output vreo eroare, eventual incearca sa faci mai intai setarile si apoi sa dai load ca sunt curios daca se comporta la fel. Pe win i-am testat comportamentul in toate felurile, logica e buna, dar pe alte platforme daca da vreo eroare din cauza vreounui pachet nu mai face anumite chestii.
  3. Screen Dupa cum spune si titlul, acest soft ascunde text in imagini, pentru mai multe detalii vezi comentariul sursei. L-am pus aici ca sa ramana mai mult timp "vizibil", daca e vreo problema il mut la stuff. In 3 zile, 300 linii de cod, m-am gandit sa ma rezolv cat de cat cu atestatul si cum iubesc sursa libera si impartasirea ei pun la dispozitie asta: http://codepad.org/hNzxFzFT #! /usr/bin/env python # Text In Image # 02.01.2012 cmiN # # This is a simple GUI script which can hide text in pictures # using least significant bit method. # Also the input text can be encrypted and the output can be decrypted too # with a symmetric key using AES. # Writing is done directly on input image so be careful with certain extensions # because the output will always have the BMP format. # # Contact: cmin764@yahoo/gmail.com from Tkinter import * # widgets's classes from tkFileDialog import askopenfilename # get file name from tkMessageBox import showerror, showinfo # user dialog from PIL import Image # image converting from Crypto.Cipher import AES # text cipher class Engine: """ Code for processing the image. Separated from GUI. """ def __init__(self): """ Initialize parameters. """ self.ext = "bmp" # save format self.name = None # save name self.path = None # save path self.im = None # image object, read and write self.generator = None # get locations to write/read bits self.useAES = None # use it or not self.aes = None # AES object self.data = None # data to be written to image self.width = None # image width self.height = None # image height self.tmp = None # last string, used when key changes def binary(self, nr, size): """ Get 1&0 representation. """ return bin(nr).replace("0b", "").zfill(size * 8) def path_name(self, path): """ Split a file path in path and name. """ ind = path.rfind("/") + 1 return (path[:ind], path[ind:]) def set_generator(self): """ Useful for resetting. """ self.generator = ((wp, hp, ch) for wp in xrange(self.width) # WxHxC for hp in xrange(self.height) for ch in xrange(3)) def load(self, path): """ Load image. """ self.im = Image.open(path) (self.width, self.height) = self.im.size (self.path, self.name) = self.path_name(path) return self.width * self.height * 3 # total useful bytes def parse_key(self, key): """ If key exists make an AES object from it. """ if not key: self.aes = None # empty key == no encryption return self.parse_string(self.tmp) # must return size (see the next return) key.decode() # test availability size = len(key) for padding in (16, 24, 32): # fixed key size if size <= padding: break key += chr(0) * (padding - size) self.aes = AES.new(key) return self.parse_string(self.tmp) # if key changes you must update string def parse_string(self, string): """ Convert to bitstring. """ if not string: # without string can't start the process self.tmp = None self.data = None return 0 string.decode() # test availability self.tmp = string if self.useAES and self.aes: # encrypt it string += chr(0) * ((16 - len(string) % 16) % 16) # multiple of 16 string string = self.aes.encrypt(string) string = str().join([self.binary(ord(x), 1) for x in string]) # convert every char in a set of 8 bits size = self.binary(len(string), 4) # get binary representation of string's length in 4 bytes self.data = size + string return len(self.data) def write(self): """ Write using LSB. """ self.set_generator() # rearm for bit in self.data: (wp, hp, ch) = self.generator.next() # get next position values = list(self.im.getpixel((wp, hp))) # retrieve its values tmp = self.binary(values[ch], 1) # convert one of them values[ch] = int(tmp[:7] + bit, 2) # alter that channel self.im.putpixel((wp, hp), tuple(values)) # put it back self.im.save(self.path + self.name, format=self.ext) # save the new output def read(self): """ Read from every LSB. """ self.set_generator() # rearm total = self.width * self.height * 3 if total < 32: raise Exception("Text not found.") size = chunk = string = str() i = 0 # for(i=0; true; ++i) while True: (wp, hp, ch) = self.generator.next() # i byte values = self.im.getpixel((wp, hp)) tmp = self.binary(values[ch], 1) if i < 32: # it's lame but I prefer string/bitset size += tmp[7] if i == 31: size = int(size, 2) if size < 1 or (size + 32) > total: raise Exception("Text not found.") elif i < size + 32: chunk += tmp[7] if len(chunk) == 8: string += chr(int(chunk, 2)) chunk = str() else: break i += 1 if self.useAES and self.aes: if len(string) % 16 != 0: raise Exception("Text not encrypted.") string = self.aes.decrypt(string).rstrip(chr(0)) string.decode() # raise an exception if invalid return string class GUI(Frame): """ Main window, inherited from Frame. Here we put our widgets and set their behavior. """ def __init__(self, master=None, margin=30): """ Same as Frame's constructor. """ Frame.__init__(self, master, padx=margin, pady=margin) self.grid() self.widgets() self.behavior() def widgets(self): """ Build and grid widgets. """ # ---- create variables ---- self.totalBytes = IntVar() # depends on image size self.usedBytes = IntVar() # how many of them are used self.textStatus = StringVar() # used per total bytes self.useEncryption = IntVar() # 0-plain 1-AES self.mode = IntVar() # 0-read 1-write self.textOpt = dict() # text last config self.keyOpt = dict() # key last config self.loaded = False # image loaded or not # ---- create widgets ---- self.label = Label(self, textvariable=self.textStatus) self.about = Label(self, text="About", fg="blue") self.text = Text(self, width=30, height=5, fg="grey") self.scrollbar = Scrollbar(self, orient="vertical", command=self.text.yview) self.loadButton = Button(self, text="Load", width=5, command=lambda: self.action("load")) self.readRadio = Radiobutton(self, text="Read", variable=self.mode, value=0, command=self.set_state) self.checkButton = Checkbutton(self, text="Use AES", variable=self.useEncryption, onvalue=1, offvalue=0, command=self.set_state) self.startButton = Button(self, text="Start", width=5, state="disabled", command=lambda: self.action("start")) self.writeRadio = Radiobutton(self, text="Write", variable=self.mode, value=1, command=self.set_state) self.keyEntry = Entry(self, width=10, fg="grey", show="*") # ---- show widgets ---- self.label.grid(row=0, column=0, columnspan=2, sticky="w") self.about.grid(row=0, column=2, sticky="e") self.text.grid(row=1, column=0, rowspan=3, columnspan=3) self.scrollbar.grid(row=1, column=3, rowspan=3, sticky="ns") self.loadButton.grid(row=4, column=0, sticky="w", pady=5) self.readRadio.grid(row=4, column=1) self.checkButton.grid(row=4, column=2, sticky="e") self.startButton.grid(row=5, column=0, sticky="w") self.writeRadio.grid(row=5, column=1) self.keyEntry.grid(row=5, column=2, sticky="e") def behavior(self): """ Customize widgets. """ self.text.config(yscrollcommand=self.scrollbar.set) self.text.insert(0.0, "Text here") self.keyEntry.insert(0, "Key here") self.text.bind("<Button>", self.handle_event) self.text.bind("<KeyRelease>", self.handle_event) self.keyEntry.bind("<Button>", self.handle_event) self.keyEntry.bind("<KeyRelease>", self.handle_event) self.textOpt = self.get_opt(self.text) self.keyOpt = self.get_opt(self.keyEntry) self.about.bind("<Button>", self.handle_event) self.set_state() def action(self, arg): """ What every button triggers. """ if arg == "load": fileTypes = [("BMP", "*.bmp"), ("JPEG", ("*.jpeg", "*.jpg")), ("PNG", "*.png"), ("All Files", "*.*")] path = askopenfilename(parent=self, title="Open image", filetypes=fileTypes) if path != "": try: self.totalBytes.set(app.load(path)) except IOError as msg: showerror("Error", str(msg).capitalize().strip(".") + ".") # some formatting else: self.loaded = True self.set_state() self.master.title("Text In Image - %s" % app.name) # update name in title elif arg == "start": if self.mode.get(): try: app.write() except Exception as msg: showerror("Error", str(msg).capitalize().strip(".") + ".") else: showinfo("Info", "Done.") else: try: string = app.read() except UnicodeError: showerror("Error", "Text not found or wrong key.") except Exception as msg: showerror("Error", str(msg).capitalize().strip(".") + ".") else: self.text.config(state="normal") self.textOpt["fg"] = "black" # touched self.text.delete(0.0, END) self.text.insert(0.0, string) self.text.config(state="disabled") self.usedBytes.set(app.parse_string(string)) self.set_status() showinfo("Info", "Done.") def set_status(self): """ Get used per total bytes. """ string = "%9.3f%s/%9.3f%s" unit1 = unit2 = "b" used = self.usedBytes.get() total = self.totalBytes.get() if used > total: self.label.config(fg="red") else: self.label.config(fg="black") if used > 999999: unit1 = "Mb" used /= 1000000.0 elif used > 999: unit1 = "Kb" used /= 1000.0 if total > 999999: unit2 = "Mb" total /= 1000000.0 elif total > 999: unit2 = "Kb" total /= 1000.0 self.textStatus.set(string % (used, unit1, total, unit2)) def get_opt(self, widget): """ Get some options from a widget then pack them. """ opt = dict() opt["state"] = widget["state"] opt["fg"] = widget["fg"] opt["bg"] = widget["bg"] return opt def set_state(self): """ Enable or disable a widget according to option selected. """ if self.mode.get(): # write self.text.config(**self.textOpt) else: self.text.config(state="disabled", bg="lightgrey", fg="darkgrey") if self.useEncryption.get(): # use AES self.keyEntry.config(**self.keyOpt) app.useAES = True else: self.keyEntry.config(state="disabled") app.useAES = False length = app.parse_string(app.tmp) self.usedBytes.set(length) self.set_status() if self.loaded: # a file is loaded if self.mode.get() == 0: # read mode ok = True elif app.data != None and self.usedBytes.get() <= self.totalBytes.get(): ok = True else: ok = False else: ok = False # no file loaded if ok: self.startButton.config(state="normal") else: self.startButton.config(state="disabled") def handle_event(self, event): """ Handle events for specific widgets. """ if event.widget is self.text and self.text["state"] == "normal": if self.text["fg"] == "grey": self.text.delete(0.0, END) self.textOpt["fg"] = self.text["fg"] = "black" string = self.text.get(0.0, END).strip() try: length = app.parse_string(string) except UnicodeError: showerror("Error", "Invalid text.") else: self.usedBytes.set(length) self.set_state() elif event.widget is self.keyEntry and self.keyEntry["state"] == "normal": if self.keyEntry["fg"] == "grey": self.keyEntry.delete(0, END) self.keyOpt["fg"] = self.keyEntry["fg"] = "black" key = self.keyEntry.get()[:32] # first 32 (max size is 32) try: length = app.parse_key(key) except UnicodeError: showerror("Error", "Invalid key.") else: self.usedBytes.set(length) self.set_state() elif event.widget is self.about: showinfo("About", "Hide text, which can be encrypted with AES, in pictures, preferably bitmaps. Coded by cmiN. Visit rstcenter.com") if __name__ == "__main__": app = Engine() # core root = Tk() # toplevel root.title("Text In Image") root.maxsize(350, 250) root.iconbitmap("tii.ico") # comment if you don't have one GUI(root) root.mainloop() Testat pe windows, fedora si slackware, merge perfect, dar sa cititi comentariul principal. Aveti nevoie de python 2.7, PIL si pycrypto. Pe linux de obicei sunt preinstalate. Versiune portabila: box gamefront Updated: 14.01.2012
  4. Sau poti spune ca evenimentele se pot aseza intr-un arbore binar perfect echilibrat si ca inaltimea lui este logN.
  5. De pe facebook.com de la careers poti ajunge pe pagina respectiva, deci e real .
  6. Mult asteptatele melodii care au mai rulat pe la statusul meu . music11.zip | Game Front music12.zip | Game Front MEGAUPLOAD - The leading online storage and file delivery service MEGAUPLOAD - The leading online storage and file delivery service Daca v-au placut spor si la celelalte.
  7. Belea, dar ce font e ala ? Stiu ca pe ubuntu era un fixed system dar e vreo versiune nativa si pe win ?
  8. Updated. Sunt cateva in lista aia noi care nu se regasesc si-n arhive ... oricum arhivele sunt independente si create dupa data downloadarii melodiei respective, deci pentru tot ce mai scot nou o sa fac o noua arhiva cand se strang destule si o postez ca update.
  9. Pai poate fi adaptat usor de la int la float, iar generarea drumului si mai simplu. Acolo in if-ul in care se seteaza maximul se adauga 2 paranteze acolada si pe langa setarea maximului se mai pune intr-un vector lantul respectiv, cu conditia ca lantul sa-si modifice semnificatia, adica mat[j][l] sa nu mai fie 1 (adica nod vizitat) ci un indice, tot un numar pozitiv care sa se incrementeze odata cu adaugarea de noi noduri. Algoritmul functioneaza foarte bine si da optimul pe diferite cazuri destul de suspecte, tinand cont de datele problemei, iar de la enuntul ei la necesitatea ta nu e deloc cale lunga .. ci cateva modificari la tipul de date si adaugarea unei linii de cod. Cu memoria scapi de probleme ... o aloci dinamic in java daca e, oricum totul depinde de o constanta. Cat despre if-ul ala de care ziceai tu cu referire la enuntul problemei ca fiecare muchie este optima e mai mult o pseudoeuristica pentru alte tipuri de abordari ale problemei. Eu am nevoie neaparat de if-ul ala (banuiesc ca te referi acolo cand verific timpul si suma de bani) ca sa decid daca actualizez cu noua valoare in matrice sau nu. Timpul se refera la depasirea limitei maxime, nu daca gasesc vreun timp mai bun, practic nici nu ma intereseaza ce timp am, ma intereseaza sa stiu daca incape in limita ca sa trec noul rezultat al noii sume de bani daca merita. Si cum nu pot alege intre o pereche timp_bun-suma_mica si timp_prost-suma_mare a iesit dinamica asta.
  10. Solutia naiva ar fi sa faci un backtracking pe parcurgeri in adancime si la depasirea timpului sa actualizezi maximul, oricum iese cu mult din timp. O solutie mai buna ar fi o dinamica in T*N unde D[j] pastreaza cele mai bune rezultate ale vecinilor lui j plecand de la momentul de timp i. Toate bune si frumoase pana a aparut problema in care trebuie sa-ti dai seama daca ai mai vizitat sau nu vecinul k al lui j in lantul i (corespunzator momentului de timp) si ca sa faci asta trebuie sa mai faci inca i-1 verificari ceea ce ducea la un timp T!*N si memorie T*N. Asa ca m-am gandit sa memorez fiecare configuratie/drum/lant in functie de fiecare moment de timp dependent de nodul cu pricina si ajungeam la un timp mai bun T*N^2 dar memoria ajungea si ea la fel, iar la datele din problema in cel mai rau caz la 600 de noduri se ocupau cam 5 gb in ram asa ca am limitat nodurile la 100 si avem memoria maxima de 200mb (cam mare) dar timpul maxim de 5 sutimi . Multumesc lui bylosul93 pentru inspiratie si acum codul: Ideone.com | Online C++ Compiler & Debugging Tool #include <cstdio> #include <iostream> #include <vector> using namespace std; const int T = 5001, N = 101; int maxMoney, startNode, nodes, edges, time, win[N], mat[T][N][N]; vector<vector<pair<int, int> > > adjacent; void parse_input() { cin >> nodes >> edges >> startNode >> time; for (int i = 1; i <= nodes; ++i) cin >> win[i]; // money gain for node i adjacent.resize(nodes + 1); for (int i = 0; i < edges; ++i) { int t, x, y; cin >> t >> x >> y; // t time between x and y adjacent[x].push_back(make_pair(y, t)); adjacent[y].push_back(make_pair(x, t)); } } void solve() { /** O(TN^2) */ maxMoney = win[startNode]; // atribuim maximului castigul de start mat[0][startNode][0] = maxMoney; // la momentul de timp t=0 initializam nodul de start mat[0][startNode][startNode] = 1; // marcam ca este vizitat in lantul curent for (int i = 0; i < time; ++i) { // pentru fiecare moment de timp for (int j = 1; j <= nodes; ++j) { // luam fiecare nod if (mat[i][j][0]) { // si daca s-a putut ajunge in el (avand suma strict pozitiva) for (int k = 0; k < adjacent[j].size(); ++k) { // luam fiecare vecin al lui int tmpTime = i + adjacent[j][k].second; // aflam noul timp pentru vizita vecinului int tmpMoney = mat[i][j][0]; // clonam suma de la care pornim vizita if (!mat[i][j][adjacent[j][k].first]) { // daca nu a mai fost vizitat acel vecin tmpMoney += win[adjacent[j][k].first]; // actualizam suma } // apoi daca vizita intra in timp si obtinem o suma mai buna de bani if (tmpTime <= time && tmpMoney > mat[tmpTime][adjacent[j][k].first][0]) { if (tmpMoney > maxMoney) maxMoney = tmpMoney; // actualizam maximul mat[tmpTime][adjacent[j][k].first][0] = tmpMoney; // evenimentul in matrice for (int l = 1; l <= nodes; ++l) { // dar si lantul de noduri vizitate mat[tmpTime][adjacent[j][k].first][l] = mat[i][j][l]; mat[tmpTime][adjacent[j][k].first][adjacent[j][k].first] = 1; } } } } } } } int main() { freopen("dp_graf.in", "rt", stdin); // switch input source parse_input(); solve(); cout << maxMoney; return 0; } Mai merge scazut si din T, oricum in implementarea ta nu cred ca folosesti dimensiuni asa mari.
  11. Eu am luat tricou lockerz si 50$ cu el, dar acum cred ca mai iau fix p*la.
  12. cmiN

    Fun stuff

    Voiam sa vad si eu un film si pac mi-am amintit de moneyball, dau repede pe filelist ma uit la screenuri si arata destul de ok, mi-a sarit in ochi si subtitrarea si am dat sa-l scot, am asteptat ceva vreme pentru dimensiunea care o are si cand sa dau play uitasem de comentarii: Oricum imi facusera ziua ^^.
  13. Cont cu 12k+ puncte fara niciun video vazut sau alte metode pentru puncte, acestea fiind obitnute doar din intrebari. Este destul de vechi si obtineti discounturi la jumatate cu el. Bani paypal/posta negociabil sau ceva kewl la schimb .
  14. cmiN

    Fun stuff

    Bune mai erau Intelliurile alea ... dar tot la mx518 raman.
  15. cmiN

    un Bug enervant

    A revenit o veche problema ... atunci cand scrii ceva pe mai multe linii uneori nu pune caracterul linie noua. Concateneaza tot.
  16. Dovada ca mai sunt si oameni pe forumul asta ce mai fac cate ceva, chiar daca reinventeaza roata (pentru altii putina mostenire si polimorfism pe list rezolva problema). Oricum gj .
  17. @TomxXx Nu toti gandesc ca tine, gandeste-te ce s-ar fi intamplat daca puneau mana pe asa ceva din prima toti copii, chiar daca pari (sau esti) la nivelul lor ca si "rank". Intotdeauna cel care face primul public ceva de genul, fara acordul tuturor autorilor, e de obicei un skiddie frustrat, asa ca era si normal sa posteze chestia asta mai intai la un loc cat de cat sigur si sa astepte momentul sa fie publicata in alta parte ca sa publice si el tutorialul. Oricum cu ce te supara ca ai aflat acum (de aici) despre asta, ori ai probleme din septembrie ?Oricum GJ ... SlicK 2 .
  18. Arata mult mai bine acum, iar temele Ambient si Brave sunt traznet, oricum merg modificate si actualizate la cea veche rst, in caz de nu se va pune la dispozitie si vechiul rst. Fundalul de la My Profile/User CP e alb si am impresia ca trebuia tot negru (la Ambient), icoanele si culorile arata bine, in schimb ca si la vechiul forum mi se par aiurea iconitele alea de la Yahoo, ICQ, etc care apar sub poza de sub nume la fiecare post, in rest e ok .
  19. In ziua de azi limbajele de programare sunt doar niste unelte, iar scopul scuza mijloacele. C++ invata oricine in 2-3 ani (oop, procedurala, librarii, apiuri, grafica) dar de asm nu pot zice acelasi lucru.
  20. Seamana cu taietura maxima sau cel mai mare dreptunghi, triunghi cuprins intre "gauri" ceva de genul.
  21. Mai simplu: >>> " ".join([str(ord(x)) for x in "test"]) '116 101 115 116'
  22. Asta e exact ca faza aia cu spirite, fantome si paranormal ... doar daca crezi incepe sa te afecteze. Asa si aici ... doar daca esti strans legat de internet si duci o viata mai mult virtuala incepi sa fii controlat de ei.
  23. Ma mir ca mai sunt pe forumul asta si persoane ca @dfani511@ @TruNkS@ care stiu ce sa asculte.
×
×
  • Create New...