Java, jpeg, exception

Az egyik publikus képfeltöltő szervlet kapcsán jeleztek egy hibát, hogy valamiféle csodaképeket egyszerűen nem lehet feltölteni. A naplófájlok elemzése után látszott is a hiba:

java.lang.IllegalArgumentException: Numbers of source Raster bands and source color space components do not match
 at java.awt.image.ColorConvertOp.filter(ColorConvertOp.java:460)
 at com.sun.imageio.plugins.jpeg.JPEGImageReader.acceptPixels(JPEGImageReader.java:1114)
 at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method)
 at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1082)
 at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:897)
 at javax.imageio.ImageIO.read(ImageIO.java:1422)
 at javax.imageio.ImageIO.read(ImageIO.java:1282)

A hiba viszonylag könnyen reprodukálható volt, tehát volt egy jó képem, és egy rossz. A gimp semmi extrát nem mondott a képről, és a rossz kép az ismételt elmentés után is rossz maradt.

Kis keresgélés után rátaláltam az exiftool nevű alkalmazásra:

exiftool -a -G ./JUT430-1.jpg

Látszott is, hogy a kép adatai között mindenféle furcsaság található:

[JFIF] JFIF Version : 1.01
 [JFIF] Resolution Unit : inches
 [JFIF] X Resolution : 300
 [JFIF] Y Resolution : 300
 [ICC_Profile] Profile CMM Type : HDM
 [ICC_Profile] Profile Version : 2.4.0
 [ICC_Profile] Profile Class : Output Device Profile
 [ICC_Profile] Color Space Data : CMYK
 [ICC_Profile] Profile Connection Space : Lab
 ...
[ICC_Profile] Profile Description : ISO Coated v2 (ECI)
 [ICC_Profile] Char Target : (Binary data 126677 bytes, use -b option to extract)
 [EXIF] Modify Date : 2012:08:21 09:56:35
 [EXIF] Compression : JPEG (old-style)
 [EXIF] Thumbnail Offset : 1829717
 [EXIF] Thumbnail Length : 5947

Ekkor gyanús lett a dolog, az én képeimen nem volt ennyi szemét. Letöröltem az összes exif adatot:

exiftool -all= ./JUT430-1.jpg

A dolog működött, a kép megnyitható java-ban. Innen már azt hittem egyszerű a dolog, már csak meg kellene oldani, hogy az exif adatokat a java is le tudja kapni feldolgozás előtt.

Erre találtam is egy ígéretes projektet az Apache common’s Sanselan-t. Az mondjuk furcsa volt, hogy még incubator-os, béta, és 3 éve senki nem nyúlt hozzá, de abból indultam ki, hogy biztosan azért mert annyira jó… 🙂

Természetesen a dolog nem működött. A forráskód tanulmányozása során feltűnt, hogy az általam használt kódból mintha hiányzott volna az érdemi rész…

</pre>
public void removeExifMetadata(ByteSource byteSource, OutputStream os)
 throws ImageReadException, IOException, ImageWriteException
 {
 JFIFPieces jfifPieces = analyzeJFIF(byteSource);
 List pieces = jfifPieces.pieces;

//Debug.debug("pieces", pieces);

//pieces.removeAll(jfifPieces.exifPieces);

//Debug.debug("pieces", pieces);

writeSegmentsReplacingExif(os, pieces, null);
 }
<pre>

Gondoltam ez így nem a legjobb, ezért visszacommenteztem (nyílt forráskód rulz) a removeAll-t. Sajnos ez még önmagában nem jelentett megoldást, ugyanis nem minden addicionális adat EXIF adat, és pont azok az adatok maradtak a képen, amik a problémát okozták.

Minden JFIFPieceSegment eltávolítása nem minősült kimondottan jó taktikának, de egy kis wikipedia-s utánaolvasás után megvolt, hogy mik az egyéb adatok marker bit-jei, amikre nekem semmi szükségem, innen már csak pár sor választott el a sikertől…


public void removeExifAndAllMetadata(ByteSource byteSource, OutputStream os)
 throws ImageReadException, IOException, ImageWriteException
 {
 JFIFPieces jfifPieces = analyzeJFIF(byteSource);
 List pieces = jfifPieces.pieces;

//Debug.debug("pieces", pieces);

 Iterator it = pieces.iterator();

 while (it.hasNext()) {
   Object object = (Object) it.next();
   if (object instanceof JFIFPieceSegment ) {
     JFIFPieceSegment iffdat=(JFIFPieceSegment)object;
     if (iffdat.marker>= 0xFFE0 && iffdat.marker<=0xFFEF) {
        it.remove();
     }
   }
 }

 pieces.removeAll(jfifPieces.exifPieces);

//Debug.debug("pieces", pieces);

writeSegmentsReplacingExif(os, pieces, null);
 }

A végeredmény valami ilyesmi lett:

public static void main(String[] args) {
 try {
String fileName="c:/JUT430-1.jpg";
File f=new File(fileName);
ExifRewriterAdv eRewriter=new ExifRewriterAdv();
FileInputStream fis=new FileInputStream(f);
ByteSourceInputStream bis=new ByteSourceInputStream(fis, null);
ByteArrayOutputStream bout=new ByteArrayOutputStream ();
eRewriter.removeExifAndAllMetadata(bis, bout);
ByteArrayInputStream iobis=new ByteArrayInputStream(bout.toByteArray());
ImageIO.read(iobis);
 } catch (Exception e) {
e.printStackTrace();
 }
 }

Hangerő állítás billentyűzetről

Elég sokat hallgatok zenét, és nem minden fülhallgatón van tekergetős hangerő állító (a jobbakon nincs). Mivel a sok helyről sok minőségben, sok minden szól, az ember elég gyakran állítgatja a hangerőt, és ha valaki nem “media” billentyűzettel rendelkezik, akkor egy idő után komoly stressz faktor emelkedéshez vezethet a hangerő ikon folyamatos nyomkodása, és a windows 3.1-ből fennmaradó felület használata.

A megoldást az AutoHotkey jelentheti, amiben tetszőleges billentyűkombinációkhoz scripteket rendelhetünk.

A hangerőállításhoz az alábbit kell tenni (ezúton is köszönet a post-ért dan hersam-nak):

http://dan.hersam.com/2010/05/06/mute-and-adjust-volume-with-keyboard-hotkeys/

Time Attack (MTA) a Pannónia Ringen

Nem célom (és nem is volt) nagyon versenyezni, ezt a luxust meghagyom azoknak, akik már tudnak vezetni. Szabadedzési lehetőséget kerestem a Pannónia Ringen (amin volt szerencsém előzőleg már 1 napot eltölteni), így keveredtem a Time Attackba. Nem bántam meg, az esemény nagyon jól szervezett, és legalább ilyen jó hangulatú volt (a time attack résztvevők sokkal kellemesebb pályatársaság mint az osztrákok, akik igen meredek dolgokat művelnek néha). Mint megtudtam, több helyen is lehetett jelentkezni, természetesen én rossz helyen jelentkeztem, ebből volt egy kis kavar, de nem okozott problémát az adminisztráció. Kimondottan az se, hogy beírtak a pro kategóriába, (bár mint megtudtam, az a race kategória fölött van), de az időm alapján utolsó lettem minden kategóriában, szóval nem hiszem, hogy számítana ez bármit is 😉

Az időről: Az autómmal hozzáértő vezető (alatta Halaska Lászlót kell érteni, akiről azért el lehet hinni, hogy tényleg ért hozzá) ment már 2:30-at, lazázva, ha szeretett volna szerintem 2:25 körül simán ment volna, de igen valószínű, hogy ha szeretett volna, akkor az alatt is tudott volna csinálni pár kört… Én amikor tanultam a pályát akkor mentem 2:40 körül, most 2:37-et. Tehát saját magamhoz viszonyítva nem is utolsó vagyok, hanem  első (javultam 3 másodpercet). További jó hír, hogy a leglassabb mért köröm is gyorsabb, mint a múltkori leggyorsabb (ha a kicsúszásokat nem számolom, amiből volt pár).  Timeattack időket amúgy sem érdemes nagyon egymáshoz hasonlítani, hiszen mindenki más teljesítményű, és építésű autókkal indul, itt mindenki magával versenyez. Én legalább úgy érzem, nem állítottam megdönthetetlen rekordot magam elé. Az viszont megnyugtató, hogy egyre többször találtam rá az ideális ívre, és a racechrono szerint 2:34-et is össze lehetett volna rakni az időimből.

A cél a 2:30 lett volna, de valószínű a tapasztalatlanságom mellett közrejátszott az is, hogy az új, szuper keréknyomásmérőmmel variáltam egy kicsit. Valamiért arra emlékeztem, hogy 2.1 bar ideális keréknyomás a pályára (melegen)… Utólag kiderült, hogy csak egy félreértésről lehet szó, ugyanis a gyári érték 2.4 bar, és 2.3 az ideális érték (talán elől 2.2). Nem tudom ez számít e, és mennyit, de kanyarban mintha most sokkal instabilabb lett volna autó mint az előző alkalommal. Ez mondjuk nem zavart, elvégre az a cél, hogy a határon menjen az autó, és a határ az mindig az instabil állapot alatt van, amit érzésre megközelítettem, és párszor át is léptem… Csak mintha ez a határ valahogy kisebb sebességnél lett volna most (persze az is lehet, hogy csak nem volt eléggé egyensúlyba az autó, majd elválik legközelebb)…

Hungaroring nyílt nap csütörtökön 😉

Nyomtatni szeretnék…

A ma estém elmondom mivel telt: 1 oldal nyomtatásával. Nem tűnik bonyolultnak. Nyomtató bedug, driver telepít, nyomtat, örül.

Nálam ez így nézett ki ma: (a bedug, telepít után)

Ubuntu linux  alatt a samba, es a cups, össze vissza indulnak el, ezért néha nem látszik a megosztott  nyomtató… persze egy idő után rájöttem, hogy samba restart után mindig látszik, de mivel a samba restartot rendszerint a konfigurációs fájlok túrása előzte meg (mondván biztos én bénázok), volt pár iteráció mire ez ebben a formában kikristályosodott (konfig írás, már jó, restart, mégse, újra konfig írás,  na most már, mégse, újra… stb.).

A megoldás:

nano  /etc/init/smbd.conf

és itt a “pre-start script” első sora legyen ez: sleep 10

Ezután gondoltam már csak egy drivert kell telepíteni a windows alá… mi se egyszerűbb ennél… kiválasztom a listából… a listából mit is?

A laserjet 4 ami nekem van, windows 7 alatt már nincs alapból a listában (xp alatt még ott volt). Újabb keresgetés, 1 óra mindenféle fórum olvasás,  mire eljutottam ide:  http://catalog.update.microsoft.com

Tegye fel a kezét, aki ismerte ezt az oldalt eddig. Na mindegy. A download driver túl egyszerű lett volna, van itt kosár, csoda letöltő, minden ami kell. Egy dolog nincs: az a lehetőség, hogy operációs rendszerre, esetleg architektúrára lehessen szűrni. Beírtam hp laserjet 4… jött 12 találat, semmiről semmi írva. Letöltöttem egyet, az eredmény egy cab file lett, ez a neve: X86-all-4189_1228a7cf7b1aac21346b20cb6e21db409dde9e72.cab

van benne egy x86, és már villogott is a képzeletbeli nem nyert felirat. A vége az lett, hogy letöltöttem minden drivert amit csak kidobott a kereső, és a végén a letöltöttből kiválasztottam az egyet ami kellett file szinten.

Kellett, de mire is? Ez egy cab file, amivel semmit nem lehet kezdeni. Újabb fórum olvasás (pörögnek az órák) és kiderült, hogy ki kell tömöríteni, és telepíteni a pnputil.exe -vel (újabb érdekes dolog, szintén jelentkezzen aki ezt tudta, hogy ilyen van)… csakhogy olyan windows 7 alatt nincs. Pedig a windows része… wtf… a parancs csak akkor látszik a cmd-ből, ha adminisztrátorként  indítjuk… tadamm…

pnputil.exe -a prnhp001.Inf

És láss csodát…

Bónusz:

Miután 3 órát ezzel szívtam, csak kíváncsiságból rányomtam, mi lenne, ha lokálisan szeretnék felvenni egy ilyen nyomtatót… Ott volt egy windows update gomb, és le lehetett tölteni a drivert a netről pár klikkel. Úgy látszik ezt a gombot valaki lefelejtette a hálózati nyomtató esetén feljövő választó dialógusablakról (ami egyébként egy nem méretezhető dialógus, és jó kicsi is, hogy kiférjen 640×480-ba is, és nem kevés nyomtató van benne)…