Skip to content

Commit f344a16

Browse files
committed
Simplify pixel indexing
1 parent 81dabb3 commit f344a16

7 files changed

Lines changed: 96 additions & 93 deletions

File tree

library/src/androidTest/java/com/tom_roush/pdfbox/multipdf/PDFMergerUtilityTest.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@
1919
import android.graphics.Bitmap;
2020
import android.support.test.InstrumentationRegistry;
2121

22+
import java.io.File;
23+
import java.io.IOException;
24+
2225
import com.tom_roush.pdfbox.pdmodel.PDDocument;
2326
import com.tom_roush.pdfbox.rendering.PDFRenderer;
2427
import com.tom_roush.pdfbox.util.PDFBoxResourceLoader;
2528

2629
import org.junit.Before;
2730
import org.junit.Test;
2831

29-
import java.io.File;
30-
import java.io.IOException;
31-
3232
import static org.junit.Assert.assertEquals;
3333

3434
/**
@@ -160,12 +160,9 @@ private void checkImagesIdentical(Bitmap bim1, Bitmap bim2)
160160
bim1.getPixels(bim1Pixels, 0, w, 0, 0, w, h);
161161
int[] bim2Pixels = new int[w * h];
162162
bim2.getPixels(bim2Pixels, 0, w, 0, 0, w, h);
163-
for (int i = 0; i < w; ++i)
163+
for (int pixelIdx = 0; pixelIdx < w * h; pixelIdx++)
164164
{
165-
for (int j = 0; j < h; ++j)
166-
{
167-
assertEquals(bim1Pixels[i + w * j], bim2Pixels[i + w * j]);
168-
}
165+
assertEquals(bim1Pixels[pixelIdx], bim2Pixels[pixelIdx]);
169166
}
170167
}
171168
}

library/src/androidTest/java/com/tom_roush/pdfbox/pdmodel/graphics/image/ValidateXImage.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,19 @@
1717

1818
import android.graphics.Bitmap;
1919

20+
import java.io.ByteArrayOutputStream;
21+
import java.io.File;
22+
import java.io.IOException;
23+
import java.util.HashSet;
24+
import java.util.Set;
25+
2026
import com.tom_roush.pdfbox.cos.COSName;
2127
import com.tom_roush.pdfbox.cos.COSStream;
2228
import com.tom_roush.pdfbox.pdmodel.PDDocument;
2329
import com.tom_roush.pdfbox.pdmodel.PDPage;
2430
import com.tom_roush.pdfbox.pdmodel.PDPageContentStream;
2531
import com.tom_roush.pdfbox.rendering.PDFRenderer;
2632

27-
import java.io.ByteArrayOutputStream;
28-
import java.io.File;
29-
import java.io.IOException;
30-
import java.util.HashSet;
31-
import java.util.Set;
32-
3333
import static org.junit.Assert.assertEquals;
3434
import static org.junit.Assert.assertNotNull;
3535
import static org.junit.Assert.assertTrue;
@@ -96,12 +96,9 @@ static int colorCount(Bitmap bim)
9696

9797
int[] bimPixels = new int[w * h];
9898
bim.getPixels(bimPixels, 0, w, 0, 0, w, h);
99-
for (int y = 0; y < h; y++)
99+
for (int pixel : bimPixels)
100100
{
101-
for (int x = 0; x < w; x++)
102-
{
103-
colors.add(bimPixels[x + w * y]);
104-
}
101+
colors.add(pixel);
105102
}
106103
return colors.size();
107104
}

library/src/main/java/com/tom_roush/pdfbox/cos/COSStream.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,6 @@
1616
*/
1717
package com.tom_roush.pdfbox.cos;
1818

19-
import com.tom_roush.pdfbox.filter.Filter;
20-
import com.tom_roush.pdfbox.filter.FilterFactory;
21-
import com.tom_roush.pdfbox.io.IOUtils;
22-
import com.tom_roush.pdfbox.io.RandomAccess;
23-
import com.tom_roush.pdfbox.io.RandomAccessBuffer;
24-
import com.tom_roush.pdfbox.io.RandomAccessInputStream;
25-
import com.tom_roush.pdfbox.io.RandomAccessOutputStream;
26-
import com.tom_roush.pdfbox.io.ScratchFile;
27-
2819
import java.io.ByteArrayOutputStream;
2920
import java.io.Closeable;
3021
import java.io.FilterOutputStream;
@@ -34,6 +25,15 @@
3425
import java.util.ArrayList;
3526
import java.util.List;
3627

28+
import com.tom_roush.pdfbox.filter.Filter;
29+
import com.tom_roush.pdfbox.filter.FilterFactory;
30+
import com.tom_roush.pdfbox.io.IOUtils;
31+
import com.tom_roush.pdfbox.io.RandomAccess;
32+
import com.tom_roush.pdfbox.io.RandomAccessBuffer;
33+
import com.tom_roush.pdfbox.io.RandomAccessInputStream;
34+
import com.tom_roush.pdfbox.io.RandomAccessOutputStream;
35+
import com.tom_roush.pdfbox.io.ScratchFile;
36+
3737
/**
3838
* This class represents a stream object in a PDF document.
3939
*
@@ -210,6 +210,12 @@ public OutputStream createOutputStream(COSBase filters) throws IOException
210210
isWriting = true;
211211
return new FilterOutputStream(cosOut)
212212
{
213+
@Override
214+
public void write(byte[] b, int off, int len) throws IOException
215+
{
216+
this.out.write(b, off, len);
217+
}
218+
213219
@Override
214220
public void close() throws IOException
215221
{
@@ -253,6 +259,12 @@ public OutputStream createRawOutputStream() throws IOException
253259
isWriting = true;
254260
return new FilterOutputStream(out)
255261
{
262+
@Override
263+
public void write(byte[] b, int off, int len) throws IOException
264+
{
265+
this.out.write(b, off, len);
266+
}
267+
256268
@Override
257269
public void close() throws IOException
258270
{

library/src/main/java/com/tom_roush/pdfbox/pdmodel/graphics/color/PDDeviceGray.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,10 @@ public Bitmap toRGBImage(Bitmap raster) throws IOException
9191

9292
int[] rgb = new int[width * height];
9393
image.getPixels(rgb, 0, width, 0, 0, width, height);
94-
for (int y = 0; y < height; y++)
94+
for (int pixelIdx = 0; pixelIdx < width * height; pixelIdx++)
9595
{
96-
for (int x = 0; x < width; x++)
97-
{
98-
int idx = x + width * y;
99-
int value = gray[idx];
100-
rgb[idx] = Color.argb(255, value, value, value);
101-
}
96+
int value = gray[pixelIdx];
97+
rgb[pixelIdx] = Color.argb(255, value, value, value);
10298
}
10399
image.setPixels(rgb, 0, width, 0, 0, width, height);
104100
return image;

library/src/main/java/com/tom_roush/pdfbox/pdmodel/graphics/image/LosslessFactory.java

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
import android.graphics.Bitmap;
1919
import android.graphics.Color;
2020

21-
import com.tom_roush.harmony.awt.AWTColor;
21+
import java.io.ByteArrayInputStream;
22+
import java.io.ByteArrayOutputStream;
23+
import java.io.IOException;
24+
2225
import com.tom_roush.harmony.javax.imageio.stream.MemoryCacheImageOutputStream;
2326
import com.tom_roush.pdfbox.cos.COSDictionary;
2427
import com.tom_roush.pdfbox.cos.COSName;
@@ -30,10 +33,6 @@
3033
import com.tom_roush.pdfbox.pdmodel.graphics.color.PDDeviceGray;
3134
import com.tom_roush.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
3235

33-
import java.io.ByteArrayInputStream;
34-
import java.io.ByteArrayOutputStream;
35-
import java.io.IOException;
36-
3736
/**
3837
* Factory for creating a PDImageXObject containing a lossless compressed image.
3938
*
@@ -59,58 +58,62 @@ public static PDImageXObject createFromImage(PDDocument document, Bitmap image)
5958
int bpc;
6059
PDDeviceColorSpace deviceColorSpace;
6160

62-
ByteArrayOutputStream bos = new ByteArrayOutputStream();
6361
int height = image.getHeight();
6462
int width = image.getWidth();
63+
byte[] imageData;
6564

6665
if (image.getConfig() == Bitmap.Config.ALPHA_8)
6766
// if ((image.getType() == BufferedImage.TYPE_BYTE_GRAY && image.getColorModel().getPixelSize() <= 8)
6867
// || (image.getType() == BufferedImage.TYPE_BYTE_BINARY && image.getColorModel().getPixelSize() == 1))
6968
{
70-
MemoryCacheImageOutputStream mcios = new MemoryCacheImageOutputStream(bos);
71-
7269
// grayscale images need one color per sample
7370
// bpc = image.getColorModel().getPixelSize();
7471
bpc = 8;
7572
deviceColorSpace = PDDeviceGray.INSTANCE;
7673

74+
ByteArrayOutputStream bos = new ByteArrayOutputStream(
75+
(width * bpc / 8) + (width * bpc % 8 != 0 ? 1 : 0) * height);
76+
MemoryCacheImageOutputStream mcios = new MemoryCacheImageOutputStream(bos);
77+
7778
int[] imagePixels = new int[width * height];
7879
image.getPixels(imagePixels, 0, width, 0, 0, width, height);
7980
for (int y = 0; y < height; ++y)
8081
{
81-
for (int x = 0; x < width; ++x)
82+
for (int pixelIdx = width * y; pixelIdx < (y + 1) * width; ++pixelIdx)
8283
{
83-
mcios.writeBits(imagePixels[x + width * y] & 0xFF, bpc);
84+
mcios.writeBits(imagePixels[pixelIdx] & 0xFF, bpc);
8485
}
85-
while (mcios.getBitOffset() != 0)
86+
87+
int bitOffset = mcios.getBitOffset();
88+
if (bitOffset != 0)
8689
{
87-
mcios.writeBit(0);
90+
mcios.writeBits(0, 8 - bitOffset);
8891
}
8992
}
9093
mcios.flush();
9194
mcios.close();
95+
96+
imageData = bos.toByteArray();
9297
}
9398
else
9499
{
95100
// RGB
96101
bpc = 8;
97102
deviceColorSpace = PDDeviceRGB.INSTANCE;
103+
imageData = new byte[width * height * 3];
104+
int byteIdx = 0;
98105

99106
int[] imagePixels = new int[width * height];
100107
image.getPixels(imagePixels, 0, width, 0, 0, width, height);
101-
for (int y = 0; y < height; ++y)
108+
for (int pixel : imagePixels)
102109
{
103-
for (int x = 0; x < width; ++x)
104-
{
105-
AWTColor color = new AWTColor(imagePixels[x + width * y]);
106-
bos.write(color.getRed());
107-
bos.write(color.getGreen());
108-
bos.write(color.getBlue());
109-
}
110+
imageData[byteIdx++] = (byte)((pixel >> 16) & 0xFF);
111+
imageData[byteIdx++] = (byte)((pixel >> 8) & 0xFF);
112+
imageData[byteIdx++] = (byte)(pixel & 0xFF);
110113
}
111114
}
112115

113-
PDImageXObject pdImage = prepareImageXObject(document, bos.toByteArray(),
116+
PDImageXObject pdImage = prepareImageXObject(document, imageData,
114117
image.getWidth(), image.getHeight(), bpc, deviceColorSpace);
115118

116119
// alpha -> soft mask
@@ -259,7 +262,8 @@ private static PDImageXObject prepareImageXObject(PDDocument document,
259262
byte [] byteArray, int width, int height, int bitsPerComponent,
260263
PDColorSpace initColorSpace) throws IOException
261264
{
262-
ByteArrayOutputStream baos = new ByteArrayOutputStream();
265+
// Pre-size the output stream to half of the input
266+
ByteArrayOutputStream baos = new ByteArrayOutputStream(byteArray.length / 2);
263267

264268
Filter filter = FilterFactory.INSTANCE.getFilter(COSName.FLATE_DECODE);
265269
filter.encode(new ByteArrayInputStream(byteArray), baos, new COSDictionary(), 0);

library/src/main/java/com/tom_roush/pdfbox/pdmodel/graphics/image/PDImageXObject.java

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@
2222
import android.graphics.Paint;
2323
import android.util.Log;
2424

25+
import java.io.File;
26+
import java.io.FileInputStream;
27+
import java.io.IOException;
28+
import java.io.InputStream;
29+
import java.io.OutputStream;
30+
import java.lang.ref.SoftReference;
31+
import java.util.List;
32+
2533
import com.tom_roush.pdfbox.cos.COSArray;
2634
import com.tom_roush.pdfbox.cos.COSBase;
2735
import com.tom_roush.pdfbox.cos.COSInputStream;
@@ -36,14 +44,6 @@
3644
import com.tom_roush.pdfbox.pdmodel.graphics.color.PDColorSpace;
3745
import com.tom_roush.pdfbox.pdmodel.graphics.color.PDDeviceGray;
3846

39-
import java.io.File;
40-
import java.io.FileInputStream;
41-
import java.io.IOException;
42-
import java.io.InputStream;
43-
import java.io.OutputStream;
44-
import java.lang.ref.SoftReference;
45-
import java.util.List;
46-
4747
/**
4848
* An Image XObject.
4949
*
@@ -352,22 +352,19 @@ else if (mask.getWidth() > width || mask.getHeight() > height)
352352
mask.getPixels(maskPixels, 0, width, 0, 0, width, height);
353353

354354
int alphaPixel;
355-
for (int y = 0; y < height; y++)
355+
for (int pixelIdx = 0; pixelIdx < width * height; pixelIdx++)
356356
{
357-
for (int x = 0; x < width; x++)
357+
int color = imagePixels[pixelIdx];
358+
359+
// Greyscale, any rgb component should do
360+
alphaPixel = Color.red(maskPixels[pixelIdx]);
361+
if (!isSoft)
358362
{
359-
int color = imagePixels[x + width * y];
360-
361-
// Greyscale, any rgb component should do
362-
alphaPixel = Color.red(maskPixels[x + width * y]);
363-
if (!isSoft)
364-
{
365-
alphaPixel = 255 - alphaPixel;
366-
}
367-
368-
maskPixels[x + width * y] = Color.argb(alphaPixel, Color.red(color),
369-
Color.green(color), Color.blue(color));
363+
alphaPixel = 255 - alphaPixel;
370364
}
365+
366+
maskPixels[pixelIdx] = Color.argb(alphaPixel, Color.red(color), Color.green(color),
367+
Color.blue(color));
371368
}
372369
masked.setPixels(maskPixels, 0, width, 0, 0, width, height);
373370

library/src/main/java/com/tom_roush/pdfbox/pdmodel/graphics/image/SampledImageReader.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,11 @@ public static Bitmap getStencilImage(PDImage pdImage, Paint paint) throws IOExce
7171
int[] alpha = new int[width * height];
7272
mask.getPixels(alpha, 0, width, 0, 0, width, height);
7373

74-
for (int y = 0; y < height; y++)
74+
for (int pixelIdx = 0; pixelIdx < width * height; pixelIdx++)
7575
{
76-
for (int x = 0; x < width; x++)
76+
if (Color.red(alpha[pixelIdx]) == 255)
7777
{
78-
if (Color.red(alpha[x + width * y]) == 255)
79-
{
80-
raster[x + width * y] = Color.TRANSPARENT;
81-
}
78+
raster[pixelIdx] = Color.TRANSPARENT;
8279
}
8380
}
8481
masked.setPixels(raster, 0, width, 0, 0, width, height);
@@ -236,15 +233,18 @@ private static Bitmap from8bit(PDImage pdImage)
236233
Bitmap raster = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
237234
int[] rasterPixels = new int[width * height];
238235
raster.getPixels(rasterPixels, 0, width, 0, 0, width, height);
239-
for(int y = 0; y < height; y++) {
240-
for(int x = 0; x < width; x++) {
241-
if(numComponents == 1) {
242-
int in = input.read();
243-
rasterPixels[x + width * y] = Color.argb(255, in, in, in);
244-
} else {
245-
rasterPixels[x + width * y] = Color.argb(255, input.read(), input.read(), input.read());
246-
}
247-
}
236+
for (int pixelIdx = 0; pixelIdx < width * height; pixelIdx++)
237+
{
238+
if (numComponents == 1)
239+
{
240+
int in = input.read();
241+
rasterPixels[pixelIdx] = Color.argb(255, in, in, in);
242+
}
243+
else
244+
{
245+
rasterPixels[pixelIdx] = Color.argb(255, input.read(), input.read(),
246+
input.read());
247+
}
248248
}
249249
raster.setPixels(rasterPixels, 0, width, 0 ,0, width, height);
250250

0 commit comments

Comments
 (0)