The question is related to (print) DPI of various images ( for eg. of jpeg or png ) format.
This question does NOT relate to SCREEN DPI or sizes of various Android devices. It is also NOT related to showing the Bitmap on the device in screen size.
This will convert the image resolution dots per inch to 300.
Uint8List resultBytes = provider.bytes;
print(resultBytes.toString());
var dpi = 300;
resultBytes[13] = 1;
resultBytes[14] = (dpi >> 8);
resultBytes[15] = (dpi & 0xff);
resultBytes[16] = (dpi >> 8);
resultBytes[17] = (dpi & 0xff);
print(resultBytes.toString());
String tempPath = (await getTemporaryDirectory()).path;
String imgName = "IMG" + DateTime.now().microsecondsSinceEpoch.toString()+".jpg";
File file = File('$tempPath/$imgName');
await file.writeAsBytes(resultBytes);
/**You will not be able to see the image in android local storage, so rewriting the file, using the code below will show you image in Pictures Directory of android storage. Note: ImageGallerySaver is plugin, just copy and paste the dependency and have a go.*/
final result1 = ImageGallerySaver.saveFile(file.path);
print(result1);
Related
I am storing an Image in the filesystem like:
FileImageOutputStream fos = new FileImageOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
And all images are stored correctly in the filesystem. (Also with correct aspect ratio with width and height!)
However, later, I am loading my image like:
File imgFile ...
FileImageInputStream stream = new FileImageInputStream(imgFile);
BufferedImage srcImage = ImageIO.read(stream);
And I want to get the width and height for my images like:
int actualHeight = srcImage.getHeight();
int actualWidth = srcImage.getWidth();
This works totally fine for images in landscape format.
However, for images in upfront format, the width and height is always swapped, so that the width is the height of the orginial image. So, e.g. I have an image that is 200x500 (width x height) and the two integers above are actualHeight = 200 and actualWidth = 500.
Am I missing something?
Most likely, your images are Exif images ("Exif-in-JPEG") from a digital camera/phone. For such images, the pixel data is often stored in the "natural" orientation of the sensor, which is always the same (usually landscape). For portrait images, the orientation is only stored in the Exif metadata, and the ImageIO JPEG plugin doesn't take this orientation into account.
Some cameras, like my Canon DSLR, has an option to do in-camera rotation to match the orientation, but this feature is typically disabled by default. This is obviously only a possible fix if you control the input images.
To fix this in the Java side, you hava some options. You already mentioned using Thumbnailator:
BufferedImage srcImage = Thumbnails.of(new FileInputStream(imgFile))
.scale(1)
.asBufferedImage();
Another option is to use EXIFUtilities from TwelveMonkeys (I'm the author of that library):
IIOImage image = EXIFUtilities.readWithOrientation(imgFile);
BufferedImage srcImage = (BufferedImage) image.getRenderedImage();
Or, if you don't need the other metadata for anything:
BufferedImage srcImage = (BufferedImage) EXIFUtilities.readWithOrientation(imgFile)
.getRenderedImage();
I am currently implementing Android PrintService, that is able to print PDFs via thermal printers. I managed to convert PDF to bitmap using PDFRenderer and I am even able to print the document.
The thing is, the document (bitmap) is not full page width.
I am receiving the document in 297x420 resolution and I am using printer with 58mm paper.
This is how I process the document (written in C#, using Xamarin):
// Create PDF renderer
var pdfRenderer = new PdfRenderer(fileDescriptor);
// Open page
PdfRenderer.Page page = pdfRenderer.OpenPage(index);
// Create bitmap for page
Bitmap bitmap = Bitmap.CreateBitmap(page.Width, page.Height, Bitmap.Config.Argb8888);
// Now render page into bitmap
page.Render(bitmap, null, null, PdfRenderMode.ForPrint);
And then, converting the bitmap into ESC/POS:
// Initialize result
List<byte> result = new List<byte>();
// Init ESC/POS
result.AddRange(new byte[] { 0x1B, 0x33, 0x21 });
// Init ESC/POS bmp commands (will be reapeated)
byte[] escBmp = new byte[] { 0x1B, 0x2A, 0x01, (byte)(bitmap.Width % 256), (byte)(bitmap.Height / 256) };
// Iterate height
for (int i = 0; i < (bitmap.Height / 24 + 1); i++)
{
// Add bitmapp commands to result
result.AddRange(escBmp);
// Init pixel color
int pixelColor;
// Iterate width
for (int j = 0; j < bitmap.Width; j++)
{
// Init data
byte[] data = new byte[] { 0x00, 0x00, 0x00 };
for (int k = 0; k < 24; k++)
{
if (((i * 24) + k) < bitmap.Height)
{
// Get pixel color
pixelColor = bitmap.GetPixel(j, (i * 24) + k);
// Check pixel color
if (pixelColor != 0)
{
data[k / 8] += (byte)(128 >> (k % 8));
}
}
}
// Add data to result
result.AddRange(data);
}
// Add some... other stuff
result.AddRange(new byte[] { 0x0D, 0x0A });
}
// Return data
return result.ToArray();
Current result looks like this:
Thank you all in advance.
There is no magic "scale-to-page-width" command in the ESC/POS command-set, you need to know the max width of your printer, available in the manual, and then you can:
Double the width and height for some image output commands -- You are using ESC *, which supports low-density, but height and width change in different ratios.
Render the PDF wider to begin with - match the Bitmap size to the printer page width, and not the PDF page width. The same problem is solved at PDFrenderer setting scale to screen
You can also simply stretch the image before you send it, if you are happy with the low quality. See: How to Resize a Bitmap in Android?
Aside, your ESC * implementation is incorrect. There are two bytes for the width- Check the ESC/POS manual for the correct usage, or read over the correct implementations in PHP or Python that I've linked in another question: ESC POS command ESC* for printing bit image on printer
I want to convert pictures using Java and OpenCV from RGB to GRAY
All extensions images work correctly and I take the gray image,
just if I make .GIF image (not moving) it's give me this error:
OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cv::cvtColor
the java code :
Mat scrImg = Highgui.imread(path);
Mat dstImg = new Mat(scrImg.rows(),scrImg.cols(),scrImg.type());
Imgproc.cvtColor(scrImg, dstImg, Imgproc.COLOR_RGB2GRAY);
private static BufferedImage Mat2BufferedImage(Mat matrix){
BufferedImage bimOut;
int type;
if(matrix.channels() == 1)
type = BufferedImage.TYPE_BYTE_GRAY;
else
type = BufferedImage.TYPE_3BYTE_BGR;
int dataLength = matrix.channels()*matrix.cols()*matrix.rows();
byte [] buffer = new byte[dataLength];
bimOut = new BufferedImage(matrix.cols(),matrix.rows(),type);
matrix.get(0,0,buffer);
final byte[] bimPixels = ((DataBufferByte) bimOut.getRaster().getDataBuffer()).getData();
System.arraycopy(buffer, 0, bimPixels, 0, buffer.length);
return bimOut;
}
According to the official documentation
Currently, the following file formats are supported:
Windows bitmaps - *.bmp, *.dib (always supported)
JPEG files - *.jpeg, *.jpg, *.jpe (see the Notes section)
JPEG 2000 files - *.jp2 (see the Notes section)
Portable Network Graphics - *.png (see the Notes section)
WebP - *.webp (see the Notes section)
Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm (always supported)
Sun rasters - *.sr, *.ras (always supported)
TIFF files - *.tiff, *.tif (see the Notes section)
OpenEXR Image files - *.exr (see the Notes section)
Radiance HDR - *.hdr, *.pic (always supported)
Raster and Vector geospatial data supported by Gdal (see the Notes section)
Apparently support is not included Because gif is a proprietary format.
http://answers.opencv.org/question/72134/cv2imread-cannot-read-gifs/
This question already has answers here:
Encode a series of Images into a Video
(4 answers)
Closed 8 years ago.
I would like to encode video from sequence of images with java only in my current android project. I mean without any use of external tools such as NDK.
Also is there any availability of java libraries for encoding video from sequence of images ?
You can use a pure java library called JCodec ( http://jcodec.org ). It contains a primitive yet working H.264 ( AVC ) encoder and a fully functioning MP4 ( ISO BMF ) muxer.
Here's a CORRECTED code sample that uses low-level API:
public void imageToMP4(BufferedImage bi) {
// A transform to convert RGB to YUV colorspace
RgbToYuv420 transform = new RgbToYuv420(0, 0);
// A JCodec native picture that would hold source image in YUV colorspace
Picture toEncode = Picture.create(bi.getWidth(), bi.getHeight(), ColorSpace.YUV420);
// Perform conversion
transform.transform(AWTUtil.fromBufferedImage(bi), yuv);
// Create MP4 muxer
MP4Muxer muxer = new MP4Muxer(sink, Brand.MP4);
// Add a video track
CompressedTrack outTrack = muxer.addTrackForCompressed(TrackType.VIDEO, 25);
// Create H.264 encoder
H264Encoder encoder = new H264Encoder(rc);
// Allocate a buffer that would hold an encoded frame
ByteBuffer _out = ByteBuffer.allocate(ine.getWidth() * ine.getHeight() * 6);
// Allocate storage for SPS/PPS, they need to be stored separately in a special place of MP4 file
List<ByteBuffer> spsList = new ArrayList<ByteBuffer>();
List<ByteBuffer> ppsList = new ArrayList<ByteBuffer>();
// Encode image into H.264 frame, the result is stored in '_out' buffer
ByteBuffer result = encoder.encodeFrame(_out, toEncode);
// Based on the frame above form correct MP4 packet
H264Utils.encodeMOVPacket(result, spsList, ppsList);
// Add packet to video track
outTrack.addFrame(new MP4Packet(result, 0, 25, 1, 0, true, null, 0, 0));
// Push saved SPS/PPS to a special storage in MP4
outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList));
// Write MP4 header and finalize recording
muxer.writeHeader();
}
You can download JCodec library from a project web site or via Maven, for this add the below snippet to your pom.xml:
<dependency>
<groupId>org.jcodec</groupId>
<artifactId>jcodec</artifactId>
<version>0.1.3</version>
</dependency>
[UPDATE 1] Android users can use something like below to convert Android Bitmap object to JCodec native format:
public static Picture fromBitmap(Bitmap src) {
Picture dst = Picture.create((int)src.getWidth(), (int)src.getHeight(), RGB);
fromBitmap(src, dst);
return dst;
}
public static void fromBitmap(Bitmap src, Picture dst) {
int[] dstData = dst.getPlaneData(0);
int[] packed = new int[src.getWidth() * src.getHeight()];
src.getPixels(packed, 0, src.getWidth(), 0, 0, src.getWidth(), src.getHeight());
for (int i = 0, srcOff = 0, dstOff = 0; i < src.getHeight(); i++) {
for (int j = 0; j < src.getWidth(); j++, srcOff++, dstOff += 3) {
int rgb = packed[srcOff];
dstData[dstOff] = (rgb >> 16) & 0xff;
dstData[dstOff + 1] = (rgb >> 8) & 0xff;
dstData[dstOff + 2] = rgb & 0xff;
}
}
}
I try to read (in a BufferedImage) a 14 or 16 bits image over 1 or 3 channels (grayscale or RGB). I precise, each color component of this image is stored on 14 or 16 bits.
My code (using Apache Sanselan / Imaging) read the image but each color component is truncated to 8 bits.
File f = new File("/tmp/a.tiff");
Map<String, ManagedImageBufferedImageFactory> params =
new HashMap<String, ManagedImageBufferedImageFactory>();
params.put(ImagingConstants.BUFFERED_IMAGE_FACTORY,
new ManagedImageBufferedImageFactory());
BufferedImage image = Imaging.getBufferedImage(file, params);
Could you provide me a code snippet ? I'm stuck for 6 hours and Google does not want to help me :-p
Okay ! I close my question by myself :-P
I finally found a jar of Java Advanced Imaging. JAI solved my problem.
The following code is able to load TIFF or BMP image of any numbers of components with any depth for each.
RenderedOp op = JAI.create("fileload", filename);
// gets the number of channels (R / RGB / RGBA)
channels = op.getColorModel().getNumColorComponents();
// gets the depth of each component (16 16 16)
depth = new int[channels];
for(int i=0; i<op.getColorModel().getNumColorComponents(); i++)
{
depth[i] = op.getColorModel().getComponentSize(i);
}
// gets the BufferedImage
image = op.getAsBufferedImage();
Thanks !!