Niewłaściwy wydruk grafiki.

0

Witam,
W moim programie odrabiam grafikę i dodaję tekst własną czcionką. Czcionkę własną zdefiniowałem w ImageList, a funkcja Litera określa który numer bitmapy odpowiada wybranemu znakowi. Reszta zmiennych odpowiada za wykreślenie bitmapy odpowiedniej wielkości we właściwym miejscu niezależnie od rozdzielczości płótna. O ile nie ma problemów z drukowaniem na ekranie i na zwykłych drukarkach, to na kopiarce używając sterowników PostScript zamiast liter mam czarne prostokąty. Wszystkie inne grafiki nanoszone są bez problemu. Niestety muszę drukować w wysokiej rozdzielczości na kopiarce i raczej muszę użyć własnej czcionki. Proszę o pomoc w rozwiązaniu problemu.
Oto fragment kodu dodający tekst litera po literze na płótno (gdzie):


          for n:=0 to 10 do begin
              B2:=TBitmap.Create;
              B2.Pixelformat:=pf24bit;
              Czcionki.GetBitmap(Litera(s[n+1]),B2);
              x1:=round(ox+n*litX*prX);y1:=round(oy+prY);
              x2:=round(ox+(n+1)*litX*prX);y2:=round(oy+4*prY);
              R1:=Bounds(0,0,B2.Width,B2.Height);
              R2:=Rect(x1,y1,x2,y2);
              gdzie.BrushCopy(R2,B2,R1,clWhite);
              B2.Free;
           end;

PS. Dodam że na wirtualnej drukarce Microsoft XPS jest OK, lecz na Adobe PDF jest tak samo jak na kopiarce. Poza tym, dotąd na PCL6 było dobrze, lecz z powodu błędów na trybie PostScript zainstalowałem najnowsze sterowniki (z maja) PS i PCL6. Na PS nic się nie zmieniło, a na PCL przestało drukować kolorowe grafiki (pozostały tylko czarne teksty i moje czcionki). Odinstalowanie najnowszych sterowników i zainstalowanie starych nie przyniosło żadnego efektu.

0

Brak deklaracji używanych zmiennych; Nie były by potrzebne, gdyby nie głupie identyfikatory typu B1, B2, x1 itd.; Pozmieniaj to i sformatuj normalnie kod, a będzie więcej wiadomo; Jeśli o sam font i własny mechanizm malowania liter chodzi, to źle się do tego zabierasz;

Sam używam czegoś podobnego, tyle że nie marnuję czasu procesora i pamięci na jakieś ImageList; Kompletny zbiór znaków znajduje się w jednym pliku PNG (patrz załącznik [ea] normal.png), a oprócz grafiki ze zbiorem znaków, są także dodatkowe informacje o wszystkich znakach, takie jak:

  • offset znaku od lewej,
  • szerokość znaku,
  • margines z lewej,
  • margines z prawej;
    Wszystko liczone w pikselach; Dzięki tym dodatkowym danym, każdy znak można odpowiednio dosunąć jeśli odstęp przed literką jest zbyt duży, lub odsunąć, jeżeli jest zbyt mały; To i tak nie jest idealne rozwiązanie, dlatego że mechanizm malowania tekstu z jakichkolwiek literek to algorytm bardzo złożony, a do tego musi być bardzo wydajny;

Aby namalować tekst takimi literkami, należy przygotować sobie funkcję, która dla każdego znaku pobierze jego kod, przetłumaczy na kod wewnętrzny, za jego pomocą pobierze offset od lewej oraz szerokość znaku, a następnie według lewego marginesu namaluje znak w zadanym miejscu; Namalowanie jednego znaku z całej matrycy to wywołanie TCanvas.CopyRect, według informacji na temat danego znaku; Brzmi kosmicznie, ale wcale nie jest to takie skomplikowane, jak może się wydawać;

Spróbuj pójść w tę stronę;


Przy okazji - obstawiam, że problemem jest ten kod:

Czcionki.GetBitmap(Litera(s[n+1]),B2);

Jeśli do obiektu B2 po prostu przepisujesz referencję innego obiektu, a potem wywołujesz metodę Free, to po pierwsze powodujesz zwolnienie oryginalnego obiektu z pamięci, a po drugie - powodujesz wyciek pamięci w każdej iteracji pętli; Najpierw tworzysz obiekt, a potem nadpisujesz wskaźnik B2 referencją do innego obiektu, przez co tracisz uchwyt do tego tworzonego;

Jak chcesz pobrać do lokalnej zmiennej wskazanie na istniejący obiekt to nie twórz go; A jeśli potrzebujesz skopiować jego zawartość to go utwórz, a następnie wywołaj metodę Assign, podając w parametrze oryginalny obiekt, na koniec zwolnij obiekt z pamięci, jak już go użyjesz.

0

Deklaracje zmiennych są, tylko ich nie przytoczyłem, po prostu R1,R2:Rect; B1,B2:TBitmap; n:byte; x1,x2,y1,y2:longint;
Może i głupie nazwy, ale proste bitmapa pierwsza, bitmapa druga, współrzędne, wielkości, offsety.
Co do pierwszej części to pewnie masz rację. Mam prawie identyczny plik, tylko że .bmp i wczytałem go do ImageList. Funkcja Litera zwraca po prostu numer znaku. Litera('A') daje 1 a Litera('Z') daje 26. Zmienię to zgodnie z Twoją radą.
Co do drugie części to raczej się mylisz. Free jest wywołane po umieszczeniu bitmapy na płótnie. Wcześniej miałem Create przed a Free za pętlą i był ten sam wynik. Zacząłem zmieniać już na głupiego, aby zobaczyć czy będzie jakaś zmiana. Raczej nie tracę obiektów, bo na ekranie i kilku innych drukarkach wszystko jest w porządku. Problem jest tylko gdy drukarka używa sterowników PostScript. Zauważyłem w ustawieniach, że Adobe PDF też używa PostScript. Próbowałem już z kilku bitmap z literami stworzyć jedną, a następnie tą ostatnią nanieść na główną grafikę. Efekt ten sam, czarny prostokąt. Dlaczego na sterownikach od zwykłych, domowych drukarek jest OK, a na profesjonalnej drukarce która używa tylko PCL/PostScript są błędy?

Może żeby uprościć: W programie mam przygotowaną grafikę, złożoną przez program z kilku innych i naniesione napisy, w wybranych kolorach i krojach. Operacje te robię wprost na płótnie, wszystko musi być w odpowiedniej wielkości niezależnie od wybranego rozmiaru papieru i rozdzielczości druku. Do tego momentu wszystko jest OK. Teraz muszę nanieść 2 nietypowe napisy. Pierwszy czcionką niestosowaną w systemie. Drugi jest negatywowy z tym, że zamiast liter widać tło graficzne (litery "wycięte" jak szablon) a tło napisu jest w wybranym kolorze. Po drugie owe tło ma zerowy margines ze wszystkich czterech stron napisu: grafika jest tuż poniżej napisu, tuż powyżej niego, po bokach i pod spodem tekstu. Stosując czcionkę systemową nie udało mi się usunąć tego marginesu u góry i u dołu. Przykład dodałem w załączniku.
Jeżeli jest na to sposób, to proszę o pomoc.

1

Co do drugie części to raczej się mylisz.

Mogę się mylić, bo kodu podałeś tyle co pies napłakał; Nie pokazałeś defeinicji metody Czcionki.GetBitmap, więc nie mam punktu zaczepienia; A z tego co podałeś właśnie wynika, że zwalniasz z pamięci obiekt, którego w tej pętli wcale nie utworzyłeś;

Free jest wywołane po umieszczeniu bitmapy na płótnie.

A co to ma do rzeczy? Najpierw malujesz bitmapę, potem ją zwalniasz - to jest dziwne w połączeniu z tym GetBitmap;

Zacząłem zmieniać już na głupiego, aby zobaczyć czy będzie jakaś zmiana. Raczej nie tracę obiektów, bo na ekranie i kilku innych drukarkach wszystko jest w porządku. Problem jest tylko gdy drukarka używa sterowników PostScript. Zauważyłem w ustawieniach, że Adobe PDF też używa PostScript. Próbowałem już z kilku bitmap z literami stworzyć jedną, a następnie tą ostatnią nanieść na główną grafikę. Efekt ten sam, czarny prostokąt. Dlaczego na sterownikach od zwykłych, domowych drukarek jest OK, a na profesjonalnej drukarce która używa tylko PCL/PostScript są błędy?

Z tego akurat wynika, że masz problem z drukarką (sterownikami), a nie z kodem;

Stosując czcionkę systemową nie udało mi się usunąć tego marginesu u góry i u dołu. Przykład dodałem w załączniku.

A czy po zastosowaniu standardowych fontów, obraz na każdej drukarce drukowany jest prawidłowo?

Jeżeli jest na to sposób, to proszę o pomoc.

Na wszystko jest sposób, jednak to by było obchodzenie systemowych mechanizmów malowania napisów, co było by dość dziwne; Namalować tekst na pomocniczej bitmapie, potem ScanLine i sprawdzenie ile całych wierszy u góry jest pustych (według Twojego załącznika kolorem niebieskim); Następnie to samo wykonać dla dołu obrazu; Potem przesunąć środkowy fragment obrazu w górę oraz zmienić rozmiar całej grafiki o tyle linii, ile zliczono wcześniej; Tyle - na koniec namalować pomocniczą bitmapę na docelowym płótnie (nie wiem czym ono jest);

Napisałem że będzie to dziwne, ale nie niemożliwe; Przy czym ramki też są po bokach, których też należałoby się pozbyć (chyba że te mają zostać, bo to nie będzie przeszkadzać).

0

Przy fontach systemowych, na każdej drukarce jest wydruk prawidłowy.
Skoro to problem sterowników to spróbuję go obejść stosując font systemowy, tak jak zasugerowałeś w ostatniej wypowiedzi.
Dziękuję za pomoc.
Pozdrawiam.

0

@Klakierus - aby potwierdzić, że kod faktycznie nie jest wadliwy, zawsze możesz po nieudanym wydrukowaniu obrazu sprawdzić efekt działania kodu, eksportując grafikę do pliku dyskowego; Jeśli wygenerowany plik graficzny będzie prawidłowy, a pomimo tego drukarka nie wydrukuje go właściwie - kod programu nie jest niczemu winien;

PS: Zapomniałem dodać... Jak masz zamiar kombinować z ucinaniem marginesów, to wystarczy zliczyć linie, a później namalować fragment pomocniczej bitmapy z pominięciem tych marginesów; Nie jest potrzebne końcowe przycinanie grafiki, skoro jest ona tylko pomocnicza; W dalszym ciągu ten problem jest dziwny, skoro dla systemowych fontów działa prawidłowo.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0