Skip to content

Commit 6833c19

Browse files
committed
add pgm, ppm image formats support
1 parent 448bdbd commit 6833c19

4 files changed

Lines changed: 257 additions & 2 deletions

File tree

projects/jfpaint/src/MainPanel.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,8 @@ public void openTab() {
10851085
chooser.addChoosableFileFilter(new FileNameExtensionFilter("PNG", "png"));
10861086
chooser.addChoosableFileFilter(new FileNameExtensionFilter("BMP", "bmp"));
10871087
chooser.addChoosableFileFilter(new FileNameExtensionFilter("TIFF", "tiff"));
1088+
chooser.addChoosableFileFilter(new FileNameExtensionFilter("PGM", "pgm"));
1089+
chooser.addChoosableFileFilter(new FileNameExtensionFilter("PPM", "ppm"));
10881090
chooser.addChoosableFileFilter(new FileNameExtensionFilter("XPM", "xpm"));
10891091
chooser.setMultiSelectionEnabled(false);
10901092
chooser.setCurrentDirectory(new File(currentPath));
@@ -1239,12 +1241,16 @@ else if (format.equals("svg")) {
12391241
if (!size.accepted) return false;
12401242
if (size.w <= 0 || size.h <= 0) return false;
12411243
result = img.loadSVG(filename, size.w, size.h);
1242-
} else if (format.equals("jpg"))
1244+
} else if (format.equals("jpg") || format.equals("jpeg"))
12431245
result = img.loadJPG(filename);
12441246
else if (format.equals("xpm"))
12451247
result = img.loadXPM(filename);
12461248
else if (format.equals("tiff"))
12471249
result = img.loadTIFF(filename);
1250+
else if (format.equals("pgm"))
1251+
result = img.loadPGM(filename);
1252+
else if (format.equals("ppm"))
1253+
result = img.loadPPM(filename);
12481254
else
12491255
result = img.load(filename);
12501256
if (result && !multi) {
@@ -1382,10 +1388,15 @@ public boolean saveTab() {
13821388
saved = img.saveBMP(filename);
13831389
else if (format.equals("svg"))
13841390
saved = img.saveSVG(filename);
1385-
else if (format.equals("jpg"))
1391+
else if (format.equals("jpg") || format.equals("jpeg"))
13861392
saved = img.saveJPG(filename);
13871393
else if (format.equals("tiff"))
13881394
saved = img.saveTIFF(filename);
1395+
else if (format.equals("pgm"))
1396+
saved = img.savePGM(filename);
1397+
else if (format.equals("ppm"))
1398+
saved = img.savePPM(filename);
1399+
//XPM.save() not supported
13891400
else
13901401
saved = img.save(filename, format);
13911402
if (!saved) {
@@ -1406,6 +1417,8 @@ public boolean saveAs() {
14061417
chooser.addChoosableFileFilter(new FileNameExtensionFilter("PNG", "png"));
14071418
chooser.addChoosableFileFilter(new FileNameExtensionFilter("TIFF", "tiff"));
14081419
chooser.addChoosableFileFilter(new FileNameExtensionFilter("BMP", "bmp"));
1420+
chooser.addChoosableFileFilter(new FileNameExtensionFilter("PGM", "pgm"));
1421+
chooser.addChoosableFileFilter(new FileNameExtensionFilter("PPM", "ppm"));
14091422
chooser.addChoosableFileFilter(new FileNameExtensionFilter("SVG", "svg"));
14101423
chooser.setMultiSelectionEnabled(false);
14111424
chooser.setCurrentDirectory(new File(currentPath));
@@ -1461,6 +1474,8 @@ private String getFormat(String filename) {
14611474
if (format.equals("jpg")) return "jpg";
14621475
if (format.equals("jpeg")) return "jpg";
14631476
if (format.equals("svg")) return "svg";
1477+
if (format.equals("pgm")) return "pgm";
1478+
if (format.equals("ppm")) return "ppm";
14641479
if (format.equals("xpm")) return "xpm";
14651480
if (format.equals("tiff")) return "tiff";
14661481
System.out.println("Unsupported format:" + format);

src/javaforce/awt/JFImage.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,96 @@ public static boolean saveTIFFs(OutputStream out, JFImage[] imgs) {
601601
return savemulti(out, imgs, "tiff");
602602
}
603603

604+
//PGM support (8bit gray scale)
605+
606+
public boolean loadPGM(String filename) {
607+
try {
608+
return loadPGM(new FileInputStream(filename));
609+
} catch (Exception e) {
610+
e.printStackTrace();
611+
return false;
612+
}
613+
}
614+
615+
public boolean savePGM(String filename) {
616+
try {
617+
return savePGM(new FileOutputStream(filename));
618+
} catch (Exception e) {
619+
e.printStackTrace();
620+
return false;
621+
}
622+
}
623+
624+
public boolean loadPGM(InputStream in) {
625+
int[] buf;
626+
javaforce.ui.Dimension size = new javaforce.ui.Dimension(0, 0);
627+
buf = pnm.load(in, size);
628+
try {in.close();} catch (Exception e) {e.printStackTrace();}
629+
if (buf == null) {
630+
JFLog.log("loadPGM() failed! null returned");
631+
return false;
632+
}
633+
if (size.width == 0 || size.height == 0) {
634+
JFLog.log("loadPGM() failed! image size zero");
635+
return false;
636+
}
637+
setImageSize(size.width, size.height);
638+
putPixels(buf, 0, 0, size.width, size.height, 0);
639+
return true;
640+
}
641+
642+
public boolean savePGM(OutputStream out) {
643+
int[] pixels;
644+
pixels = getPixels(0, 0, getWidth(), getHeight());
645+
javaforce.ui.Dimension size = new javaforce.ui.Dimension(getWidth(), getHeight());
646+
return pnm.save(out, pixels, size, pnm.TYPE_GRAY_BIN);
647+
}
648+
649+
//PPM support (24bit color)
650+
651+
public boolean loadPPM(String filename) {
652+
try {
653+
return loadPPM(new FileInputStream(filename));
654+
} catch (Exception e) {
655+
e.printStackTrace();
656+
return false;
657+
}
658+
}
659+
660+
public boolean savePPM(String filename) {
661+
try {
662+
return savePPM(new FileOutputStream(filename));
663+
} catch (Exception e) {
664+
e.printStackTrace();
665+
return false;
666+
}
667+
}
668+
669+
public boolean loadPPM(InputStream in) {
670+
int[] buf;
671+
javaforce.ui.Dimension size = new javaforce.ui.Dimension(0, 0);
672+
buf = pnm.load(in, size);
673+
try {in.close();} catch (Exception e) {e.printStackTrace();}
674+
if (buf == null) {
675+
JFLog.log("loadPPM() failed! null returned");
676+
return false;
677+
}
678+
if (size.width == 0 || size.height == 0) {
679+
JFLog.log("loadPPM() failed! image size zero");
680+
return false;
681+
}
682+
setImageSize(size.width, size.height);
683+
putPixels(buf, 0, 0, size.width, size.height, 0);
684+
return true;
685+
}
686+
687+
public boolean savePPM(OutputStream out) {
688+
int[] pixels;
689+
pixels = getPixels(0, 0, getWidth(), getHeight());
690+
javaforce.ui.Dimension size = new javaforce.ui.Dimension(getWidth(), getHeight());
691+
return pnm.save(out, pixels, size, pnm.TYPE_COLOR_BIN);
692+
}
693+
604694
/** Puts pixels . */
605695
public void putJFImage(JFImage img, int x, int y) {
606696
int[] px = img.getPixels();

src/javaforce/awt/priv/pnm.java

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package javaforce.awt.priv;
2+
3+
/** pgm, ppm images.
4+
*
5+
* Only supports 8bit binary gray scale or color images (P5, P6).
6+
*
7+
* @author pquiring
8+
*/
9+
10+
import java.io.*;
11+
12+
import javaforce.*;
13+
import javaforce.ui.*;
14+
15+
public class pnm {
16+
17+
//file format = P{type}\n{width} {height}\nmax_value\n[...pixels...]
18+
19+
public static final int TYPE_BIT_ASCII = 1;
20+
public static final int TYPE_GRAY_ASCII = 2;
21+
public static final int TYPE_COLOR_ASCII = 3;
22+
23+
public static final int TYPE_BIT_BIN = 4;
24+
public static final int TYPE_GRAY_BIN = 5;
25+
public static final int TYPE_COLOR_BIN = 6;
26+
27+
public static int[] load(InputStream is, javaforce.ui.Dimension size) {
28+
byte[] data;
29+
int pos = 0;
30+
int type = -1; //image type
31+
try {
32+
data = is.readAllBytes();
33+
if (data == null || data.length < 9) throw new Exception("pgm:header too small");
34+
if (data[0] != 'P' || data[2] != '\n') throw new Exception("pgm:invalid header");
35+
switch (data[1]) {
36+
case '1': type = TYPE_BIT_ASCII; break;
37+
case '2': type = TYPE_GRAY_ASCII; break;
38+
case '3': type = TYPE_COLOR_ASCII; break;
39+
case '4': type = TYPE_BIT_BIN; break;
40+
case '5': type = TYPE_GRAY_BIN; break;
41+
case '6': type = TYPE_COLOR_BIN; break;
42+
default: throw new Exception("pgm:unknown image type");
43+
}
44+
if (type == TYPE_BIT_ASCII || type == TYPE_BIT_BIN) throw new Exception("pmg:bit format not supported");
45+
if (type < TYPE_GRAY_BIN) throw new Exception("pmg:ascii format not supported");
46+
pos += 3;
47+
if (data[pos] == '#') {
48+
//skip comment
49+
while (data[pos] != '\n') {
50+
pos++;
51+
}
52+
pos++; //skip \n
53+
}
54+
int start = pos;
55+
int strlen = 0;
56+
while (data[pos] != ' ') {
57+
pos++;
58+
strlen++;
59+
}
60+
pos++; //skip space
61+
int width = Integer.valueOf(new String(data, start, strlen));
62+
start = pos;
63+
strlen = 0;
64+
while (data[pos] != '\n') {
65+
pos++;
66+
strlen++;
67+
}
68+
pos++; //skip \n
69+
int height = Integer.valueOf(new String(data, start, strlen));
70+
start = pos;
71+
strlen = 0;
72+
while (data[pos] != '\n') {
73+
pos++;
74+
strlen++;
75+
}
76+
pos++; //skip \n
77+
int max_value = Integer.valueOf(new String(data, start, strlen));
78+
if (max_value != 255) throw new Exception("pgm:max value not supported");
79+
//now read pixels
80+
int pxs = width * height;
81+
int[] px = new int[pxs];
82+
int off = 0;
83+
switch (type) {
84+
case TYPE_GRAY_BIN: {
85+
for(int a=0;a<pxs;a++) {
86+
int val = data[pos++];
87+
val = (val + (val << 8) + (val << 16)) + Color.OPAQUE; //gray scale
88+
px[off++] = val;
89+
}
90+
break;
91+
}
92+
case TYPE_COLOR_BIN: {
93+
for(int a=0;a<pxs;a++) {
94+
int r = data[pos++];
95+
int g = data[pos++];
96+
int b = data[pos++];
97+
int val = (b + (g << 8) + (r << 16)) + Color.OPAQUE;
98+
px[off++] = val;
99+
}
100+
break;
101+
}
102+
}
103+
size.width = width;
104+
size.height = height;
105+
return px;
106+
} catch (Exception e) {
107+
JFLog.log(e);
108+
}
109+
return null;
110+
}
111+
112+
public static boolean save(OutputStream os, int[] px, javaforce.ui.Dimension size, int type) {
113+
int pxs = size.width * size.height;
114+
int bytes = pxs;
115+
if (type == TYPE_COLOR_BIN) bytes *= 3;
116+
byte[] px8 = new byte[bytes];
117+
try {
118+
if (type == TYPE_BIT_ASCII || type == TYPE_BIT_BIN) throw new Exception("pgm:bit format not supported");
119+
if (type < TYPE_GRAY_BIN) throw new Exception("pgm:ascii format not supported");
120+
os.write(("P" + type + "\n").getBytes()); //header
121+
os.write(String.format("%d %d\n", size.width, size.height).getBytes()); //width height
122+
os.write("255\n".getBytes()); //max value (8 bit)
123+
switch (type) {
124+
case TYPE_GRAY_BIN:
125+
for(int a=0;a<pxs;a++) {
126+
px8[a] = (byte)(px[a] & Color.MASK_BLUE);
127+
}
128+
break;
129+
case TYPE_COLOR_BIN:
130+
int off = 0;
131+
for(int a=0;a<pxs;a++) {
132+
int val = px[a];
133+
px8[off++] = (byte)((val & Color.MASK_RED) >> Color.SHIFT_RED);
134+
px8[off++] = (byte)((val & Color.MASK_GREEN) >> Color.SHIFT_GREEN);
135+
px8[off++] = (byte)((val & Color.MASK_BLUE) >> Color.SHIFT_BLUE);
136+
}
137+
break;
138+
}
139+
os.write(px8);
140+
return true;
141+
} catch (Exception e) {
142+
JFLog.log(e);
143+
}
144+
return false;
145+
}
146+
}

src/javaforce/ui/Color.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ public class Color {
1515
public static int MASK_GREEN = 0x0000ff00;
1616
public static int MASK_BLUE = 0x000000ff;
1717

18+
public static int SHIFT_RED = 16;
19+
public static int SHIFT_GREEN = 8;
20+
public static int SHIFT_BLUE = 0;
21+
1822
public static int black = 0x000000;
1923
public static int light_red = 0xee9090;
2024
public static int dark_red = 0x770000;

0 commit comments

Comments
 (0)