image quantization - lookup-tables

In Efford's cd there is a code for grayscale image quantization:
int n = 8 - numBits;//numBits will be taken as input
float scale = 255.0f / (255 >> n);
byte[] tableData = new byte[256];
for (int i = 0; i < 256; ++i)
tableData[i] = (byte) Math.round(scale*(i >> n));
LookupOp lookup =
new LookupOp(new ByteLookupTable(0, tableData), null);
BufferedImage result = lookup.filter(getSourceImage(), null);
return result;
I am trying to convert this code for 24 bit color image.
But dont know if I am correct?
my try:
int n = 24 - numBits;
float scale = 16777216.0f / (16777216 >> n);
byte[] tableData = new byte[16777216];
for (int i = 0; i < 16777216; ++i)
tableData[i] = (byte) Math.round(scale*(i >> n));
LookupOp lookup =
new LookupOp(new ByteLookupTable(0, tableData), null);
result = lookup.filter(img2, null);
//return result;
and this gives result inmage till numBits>=17, if numBits<17 then i get complete black image.
Am I doing it correctlly?
please help.
Thanks a lot. :)

That code quantizes only grayscale images, not color images. This means that it handles only one color channel at a time.
Besides, if you are doing 24bit -> 8bit, you probably want to construct a palette instead of simple quantization.

Related

Printing PDF doc to esc/pos Thermal printer

We are developing a POS APP using xamarin.forms, in that we need to print the receipt to an esc/pos thermal printer connected via LAN.
We have multi language support with the App, printing multiple language with the esc/pos commands by changing code page works perfectly.
But its working for some supported language only, for other language its printing garbage characters(unreadable ones).
so we thought of creating a pdf for the receipt and print that one. we tried to create the pdf and then convert to bitmap and then send to the printer by using esc pos commands, but its not printing anything.
public BitImage(String filename)
{
Java.IO.File file = new Java.IO.File(filename);
var pdfRenderer = new PdfRenderer(ParcelFileDescriptor.Open(file, ParcelFileMode.ReadOnly));
PdfRenderer.Page page = pdfRenderer.OpenPage(0);
Bitmap bmp = Bitmap.CreateBitmap(page.Width, page.Height, Bitmap.Config.Argb8888);
page.Render(bmp, null, null, PdfRenderMode.ForPrint);
load(bmp);
}
private void load(Bitmap bmp)
{
int w = bmp.Width;
int h = bmp.Height;
int bw = (w + 7) / 8;
if (bw > 255)
bw = 255;
int bh = h / 8;
if (bh > 24)
{
bh = 24;
}
initData(bw * 8, bh * 8);
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
if (bmp.GetPixel(x, y) == Color.Black)
setPixel(x, y);
}
}
}
private void initData(int w, int h)
{
width = w;
height = h;
pitch = h / 8;
data = new byte[w * pitch];
}
private void setPixel(int x, int y)
{
if (x >= width || y >= height)
{
return;
}
int mask = (0x0080 >> (y % 8));
data[(x * pitch) + (y / 8)] |= (byte)mask;
}
public void PrintData()
{
byte[] CMD_INIT = { 0x1B, 0x40 };
byte[] CMD_UPLOAD_IMAGE = { 0x1D, 0x2A, 0, 0 };
byte[] CMD_PRINT_IMAGE = { 0x1D, 0x2F, 0 };
byte[] CMD_CUT = { 0x1D, 0x56, 0x01 };
CMD_UPLOAD_IMAGE[2] = (byte)(width / 8);
CMD_UPLOAD_IMAGE[3] = (byte)(height / 8);
#region Print Via Lan
Socket pSocket = new Socket(SocketType.Stream, ProtocolType.IP);
pSocket.SendTimeout = 1500;
pSocket.Connect("192.168.15.168", 9100);
pSocket.Send(CMD_INIT);
pSocket.Send(CMD_UPLOAD_IMAGE);
pSocket.Send(data);
pSocket.Send(CMD_PRINT_IMAGE);
pSocket.Send(CMD_CUT);
pSocket.Close();
#endregion
}
Please help me, whether i am doing it in correct way?
or is there any better way to do the same?
You can use libraries like SkiaSharp to make Image/PDF from your data in any language and print them properly using any printer.
I've created a sample to demonstrate how to print images properly with ESC\POS printers in C#: GitHub code repo

How convert a raw image stored in a byte array to a rgb image with opencv and Java

i am working in the preview of a fingerprint scaner using id3Fingerprint sdk and OpenCV. If i just show the preview from the id3fingerprint sdk all is fine, but if i load it to a Mat object of OpenCV in order to draw some rectangles in the image then:
1.- The fingerprints are displayed in right form but the rectangles are displayed as lines or pixels in random x,y location.
2.- The rectangles are displayed in right form but the fingerprints are displayed "blured" (look the image attached).fingerprints are blured
I think, my problem is when i convert the raw grayscale image (a byte array from the id3fingerprint sdk) to a RGB or RGBA image.
private void showPreview2(FingerImage image){
int height = 750;
int width = 750;
int currentWidth = 0;
int currentHeight = 0;
try {
currentWidth = image.getWidth();
currentHeight = image.getHeight();
} catch (FingerException ex) {
Logger.getLogger(CallingID3Example.class.getName()).log(Level.SEVERE, null, ex);
}
byte[] pixels = image.getPixels();
Mat dest = new Mat();
Mat source = new Mat();
Mat source2 = null;
source2 = new Mat(currentWidth, currentHeight, CvType.CV_8UC1);
source2.put(0, 0, pixels);
MatOfByte pix = new MatOfByte();
Imgcodecs.imencode(".bmp", source2, pix);
source2.put(0, 0, pix.toArray());
Imgproc.cvtColor(source2, source, Imgproc.COLOR_GRAY2RGBA);
try {
int i=0;
for(FingerImage finger : image.getSegments()){
Scalar color;
color = new Scalar(0, 250,0);
FingerBounds bound = image.getSegmentBounds()[i];
Imgproc.rectangle(source, new Point(bound.topLeft.x, bound.topLeft.y), new Point(bound.bottomRight.x, bound.bottomRight.y), color, 3);
double[] pixelTest;
pixelTest = source.get(bound.topLeft.x, bound.topLeft.y);
i++;
}
} catch (FingerException ex) {
Logger.getLogger(CallingID3Example.class.getName()).log(Level.SEVERE, null, ex);
}
gc = canvas.getGraphicsContext2D();
WritableImage writableImage = loadImage(source);
imageView.setImage(writableImage);
}
private WritableImage loadImage(Mat matrix) {
// Encoding the image
MatOfByte matOfByte = new MatOfByte();
Imgcodecs.imencode(".bmp", matrix, matOfByte);
// Storing the encoded Mat in a byte array
byte[] byteArray = matOfByte.toArray();
// Displaying the image
InputStream in = new ByteArrayInputStream(byteArray);
BufferedImage bufImage = null;
try {
bufImage = ImageIO.read(in);
} catch (IOException ex) {
}
// Creating the Writable Image
WritableImage writableImage = SwingFXUtils.toFXImage(bufImage, null);
return writableImage;
}
Thanks for your answer.
You could try something like this:
// You need to know width/height of the image
int width = 0;
int height = 0;
byte[] imageSrc = null;//
// Convert 8bit greyscale byte array to RGBA byte array.
byte[] imageRGBA = new byte[imageSrc.length * 4];
int i;
for (i = 0; i < imageSrc.length; i++) {
imageRGBA[i * 4] = imageRGBA[i * 4 + 1] = imageRGBA[i * 4 + 2] = ((byte) ~imageSrc[i]);
// Invert the source bits
imageRGBA[i * 4 + 3] = -1;// 0xff, that's the alpha.
}
// Convert RGBA byte array to PNG
int samplesPerPixel = 4;
int[] bandOffsets = {0,1,2,3}; // RGBA order
byte[] bgraPixelData = new byte[width * height * samplesPerPixel];
DataBuffer buffer = new DataBufferByte(bgraPixelData, bgraPixelData.length);
WritableRaster raster = Raster.createInterleavedRaster(buffer, width, height, samplesPerPixel * width, samplesPerPixel, bandOffsets, null);
ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
System.out.println("image: " + image); // Should print: image: BufferedImage#<hash>: type = 0 ...
ImageIO.write(image, "PNG", new File(path));
Update
To draw rectangle on image:
BufferedImage image = ...
Graphics2D graph = img.createGraphics();
graph.setColor(Color.BLACK);
graph.fill(new Rectangle(x, y, width, height));
graph.dispose();
ImageIO.write(image, "PNG", new File(path));

OpenCl wrong values when reading from multiple GPU

I have a kernel function that only writes number to a __global int* c
To be specific it looks like this:
__kernel void Add1(__global int* c)
{
*c = 3;
}
and in host code I have allocated memory for C value:
cl_mem bufferC[deviceNumber]; // deviceNumber = 8
for(int i = 0; i< deviceNumber; i++){
bufferC[i] = clCreateBuffer(context[i], CL_MEM_WRITE_ONLY, sizeof(cl_int) * global_size, NULL, &error);
}
for(int i = 0; i< deviceNumber; i++){
error = clSetKernelArg(kernel[i], 0, sizeof(cl_mem), (void*)&bufferC[i]);
}
for(int i = 0; i< deviceNumber; i++){
error = clEnqueueReadBuffer(commandQueue[i], bufferC[i], CL_TRUE, 0, sizeof(cl_int) * global_size, &c[i], 0, NULL, NULL);
}
and I print it like:
for (size_t i = 0; i < deviceNumber; ++i)
{
std::cout<< "delta = " << c[i] << std::endl;
}
and output:
delta = 3
delta = 11165
delta = -1329524360
delta = 11165
delta = 0
delta = 0
delta = -1329520352
delta = 11165
so first value is ok, rest is sort of garbage, do you know what mistake I made writing it?
Of course it is only a partial code, but I think I pasted all the lines regarding that 'c' value. Global size is set to 1.
Well, my mistake was creating number of contexts but in argument I put one device instead of a array of them. But I found it by printing error codes in program - try to do that if you have some problems! Cheers

android hexToByteArray signed to unsigned

I've got the following function to make a conversion from a Hex String to a Byte array. Then, I calculate the Checksum:
private String CalcChecksum (String message) {
/**Get string's bytes*/
//byte[] bytes = DatatypeConverter.parseHexBinary(message.replaceAll("\\s","")).getBytes();
message = message.replaceAll("\\s","");
byte[] bytes = hexToByteArray(message);
byte b_checksum = 0;
for (int byte_index = 0; byte_index < bytes.length; byte_index++) {
b_checksum += bytes[byte_index];
}
int d_checksum = b_checksum; //Convert byte to int(2 byte)
int c2_checksum = 256 - d_checksum; //Hacer complemento a 2
String hexString = Integer.toHexString(c2_checksum); //Convertir el entero (decimal) a hexadecimal
return hexString;
}
public static byte[] hexToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
}
return data;
}
Making some test, for example for the hex value "e0", the hexToByteArray is getting the value "-32". So the final returning value in the CalcChecksum is "17a".
What I need is to get unsigned values in the hexToByteArray function. This is because i need to send the Checksum in a hexString to a MCU where the Checksum is calculated with unsigned values, so isntead of get the "-32" value, it gets "224" and the final hex value is "7a" instead of "17a".
i think that doing some kind of conversion like when the byte result is a negative value, do something like 255 + "negative value" + 1. This will convert "-32" into "224".
The problem is that i'm trying to do it, but i'm having some errors making the conversions between bytes, int, etc...
So, how could i do?
For the moment, I think that this can be the solution.
Just including in the CalcChecksum function the next code after int d_checksum = b_checksum;:
if (d_checksum < 0) {
d_checksum = 255 + d_checksum + 1;
}

MandelBrot set Using openCL

Trying to use the same code (sort of) as what I have used when running using TBB (threading building blocks).
I don't have a great deal of experience with OpenCL, but I think most of the main code is correct. I believe the errors are in the .cl file, where it does the math.
Here is my mandelbrot code in TBB:
Mandelbrot TBB
Here is my code in OpenCL
Mandelbrot OpenCL
Any help would be greatly appreciated.
I changed the code in the kernel, and it ran fine. My new kernel code is the following:
// voronoi kernels
//
// local memory version
//
kernel void voronoiL(write_only image2d_t outputImage)
{
// get id of element in array
int x = get_global_id(0);
int y = get_global_id(1);
int w = get_global_size(0);
int h = get_global_size(1);
float4 result = (float4)(0.0f,0.0f,0.0f,1.0f);
float MinRe = -2.0f;
float MaxRe = 1.0f;
float MinIm = -1.5f;
float MaxIm = MinIm+(MaxRe-MinRe)*h/w;
float Re_factor = (MaxRe-MinRe)/(w-1);
float Im_factor = (MaxIm-MinIm)/(h-1);
float MaxIterations = 50;
//C imaginary
float c_im = MaxIm - y*Im_factor;
//C real
float c_re = MinRe + x*Re_factor;
//Z real
float Z_re = c_re, Z_im = c_im;
bool isInside = true;
bool col2 = false;
bool col3 = false;
int iteration =0;
for(int n=0; n<MaxIterations; n++)
{
// Z - real and imaginary
float Z_re2 = Z_re*Z_re, Z_im2 = Z_im*Z_im;
//if Z real squared plus Z imaginary squared is greater than c squared
if(Z_re2 + Z_im2 > 4)
{
if(n >= 0 && n <= (MaxIterations/2-1))
{
col2 = true;
isInside = false;
break;
}
else if(n >= MaxIterations/2 && n <= MaxIterations-1)
{
col3 = true;
isInside = false;
break;
}
}
Z_im = 2*Z_re*Z_im + c_im;
Z_re = Z_re2 - Z_im2 + c_re;
iteration++;
}
if(col2)
{
result = (float4)(iteration*0.05f,0.0f, 0.0f, 1.0f);
}
else if(col3)
{
result = (float4)(255, iteration*0.05f, iteration*0.05f, 1.0f);
}
else if(isInside)
{
result = (float4)(0.0f, 0.0f, 0.0f, 1.0f);
}
write_imagef(outputImage, (int2)(x, y), result);
}
You can also find it here:
https://docs.google.com/file/d/0B6DBARvnB__iUjNSTWJubFhUSDA/edit
See this link. It's developed by #eric-bainville. The CPU code both native and with OpenCL is not optimal (it does not use SSE/AVX) but I think the GPU code may be good. For the CPU you can speed up the code quite a bit by using AVX and operating on eight pixels at once.
http://www.bealto.com/mp-mandelbrot.html

Resources