unable to loop through data in c pos - c

I am new to POS programming using C language. I want to loop through the returned hex data and also print it to the screen after sending the APDU command and getting a response. Here is my main problem requirements.
First I elect the EMV Application using PSE method 1PAY.SYS.DD01
I read the record of the PSE which returns me the AID
I select the AID currently I'm using cards with VISA AIDs (A0 00 00 00 03 10 10 and A0 00 00 00 03 20 10)
3.I read the record of the AID interestingly for the first AID, it returns the magnetic stripe info without using GPO command first while the second one for some cards it requires them so I next get the GPO to process it
I then read the records from the card. The problem is I am outputting this byte info so its easy for me to track what's going on but the POS terminal I am using can only output a given number of characters on the screen. First I have space for 18 bytes, then I can have up to maximum of 35 bytes to display after clearing the screen everytime the user presses the arrow down button.
To do this, I used some variables below
int variab = 0,
offset = 18,
remainingBytes = apduResp.LenOut - 18,
limit = apduResp.LenOut,
AIDChooser = 0; // To track output data scroll
// option
if (apduResp.LenOut == 0)
{
offset = 0;
remainingBytes = 0;
limit = 0;
}
else if (apduResp.LenOut > 0)
{
int variab = 0,
offset = 18,
remainingBytes = apduResp.LenOut - 18,
limit = apduResp.LenOut,
AIDChooser = 0;
}
Then I put the code below in a loop that runs while the arrow down key is pressed I read all the data and this is what it is supposed to do
i) Read all response bytes and the length
ii) check if the remaining bytes are more than 35, add 35 to the loop offset and then print the next 35 up to the limit which is (offset + 35). and if the remaining bytes are less than 35, print them out and stop.
The problem is when the intial data length is 0, pressing the scroll button doesn't show subsequent data but if the initial response data is greater than zero, the function works as required, can anyone figure out what I'm doing wrong?
if (remainingBytes > 35)
{
limit = offset + 35;
for (i_sn = offset; i_sn < limit; i_sn++)
{
sn_display += sprintf(sn_display, "%02X ", `apduResp.DataOut[i_sn]);
TP_LcdPrintf(" %s", te);
}
offset = limit; // Change
// offset
remainingBytes = apduResp.LenOut - limit; // Reduce
// remaining bytes
}
else if (remainingBytes == 0)
{
TP_LcdPrintf(" %s", " No more data\n Press Cancel to\n return");
}
else if (remainingBytes > 0 && remainingBytes < 35)
{
for (i_sn = offset; i_sn < apduResp.LenOut; i_sn++)
{
sn_display += sprintf(sn_display, "%02X ", apduResp.DataOut[i_sn]);
TP_LcdPrintf(" %s", te);
}
offset = limit;
remainingBytes = apduResp.LenOut - limit;
}
////indent: Standard input:32: Error:Stmt nesting error.
}

… in the first block of code you have under #5, you have some variables you are initializing in the else part of an if statement that are declared, initialized, but then never used. So their values will not be "seen" outside of that if statement block because their scope is all inside else { ... } – lurker

Related

How do I read a byte (8 bit data) sent on one line from a thermometer?

I am converting the 1s and 0s (ups and downs on a pin) into relevant 8 bit data. The pin is expected to have 8 bits sent making a byte from another sort of computer.
I am currently working on making a char or array to take the 1s and 0s sent from a pin. I need this so I can transfer this data into something else in the form of number or char I received. A 1 is determined at a certain time and a 0 is determined if no 1 (high pulse) appears.
So far I have tried this:
char data = (0x00);
int valid = 0;
for(int i = 0; i <= 8; i++)
{
//Add 1 or 0 to array
while(pin==0)
{
delay(5,4); // 60ns
data << i = 0; // add 0 to char
valid = 1;
}
if(valid == 0)
{
data << i = 1; //add 1 to char
delay(5,4); // wait for 50 seconds
}
}
I thought shifting into the char in the binary sense (hexadecimal/binary) I could update the individual 1s and 0s. But I am getting errors saying this isnt a valid solution.
What should I do?

Aligning 8-bit Integer Array for Message Passing that Requires Long Alignment

I am currently using OpenMP on a processor with a NUMA architecture and using the User Dynamic Network (UDN) that the board provides to route packets from each thread to the master thread. The overall idea of the program is simple: parallelize the subtraction of two 8-bit integer arrays element-wise and store the results into an array (C[i] = A[i] - B[i]).
Due to the NUMA architecture of the processor I'm using, allocating the arrays and then putting a simple OpenMP for loop pragma results in very poor performance. One of the ways I have achieved better performance is to instead allocate arrays of equal size as private arrays to each thread, and have each thread just work on its private data that was allocated by that thread. The idea is to have each thread work on local to get around the overhead of fetching data from other cores.
While this results in a performance increase, I am trying to accumulate the data from each thread into one final thread that can be used by the main program outside of the parallel region. However, when using the UDN to pass messages around, one of the requirements according the data sheet is that the buffer being sent and the buffer used to receive the data must be long-aligned.
Here is the code I have:
int size = 6000;
int threads = 20;
if(tmc_udn_init(NULL) != 0)
{
printf("tmc_udn_init failure\n");
}
alloc_attr_t attrCfinal = ALLOC_INIT;
mspace mspCfinal = create_mspace_with_attr(0,0,&attrCfinal);
uint8_t *C_final = mspace_malloc(mspCfinal, sizeof(uint8_t)*(size*size));
#pragma omp parallel num_threads(threads)
{
int j;
int id = omp_get_thread_num();
if(tmc_cpus_set_my_cpu(id) < 0)
{
printf("tmc_cpus_set_my_cpu failure, thread = %d\n", id);
}
if(tmc_udn_activate() < 0)
{
printf("tmc_udn_activate() failure, threads = %d\n", id);
}
#pragma omp barrier
alloc_attr_t attrA = ALLOC_INIT;
alloc_attr_t attrB = ALLOC_INIT;
alloc_attr_t attrC = ALLOC_INIT;
alloc_set_home(&attrA, ALLOC_HOME_HERE);
alloc_set_home(&attrB, ALLOC_HOME_HERE);
alloc_set_home(&attrC, ALLOC_HOME_HERE);
mspace mspA = create_mspace_with_attr(0,0,&attrA);
mspace mspB = create_mspace_with_attr(0,0,&attrB);
mspace mspC = create_mspace_with_attr(0,0,&attrC);
uint8_t *A_priv = mspace_malloc(mspA, sizeof(uint8_t)*((size*size)/threads));
uint8_t *B_priv = mspace_malloc(mspB, sizeof(uint8_t)*((size*size)/threads));
uint8_t *C_priv = mspace_malloc(mspC, sizeof(uint8_t)*((size*size)/threads));
for(j=0; j<((size*size)/threads); j++)
{
A_priv[j] = 100;
B_priv[j] = omp_get_thread_num();
C_priv[j] = 0;
}
for(j=0; j<((size*size)/threads); j++)
{
C_priv[j] = A_priv[j] - B_priv[j];
}
if(omp_get_thread_num() == 0)
{
int k = 0;
int h = 0;
for(k=1; k<threads; k++)
{
int thread_num = tmc_udn1_receive();
for(h=0; h<((size*size)/threads)/100; h++)
{
tmc_udn0_receive_buffer(&C_final[((thread_num-1)*((size*size)/threads))+(h*100)], 100);
}
}
}
else
{
#pragma omp critical
{
DynamicHeader dest = tmc_udn_header_from_cpu(0);
tmc_udn_send_1(dest, UDN1_DEMUX_TAG, omp_get_thread_num());
int p = 0;
for(p=0; p<((size*size)/threads)/100; p++)
{
tmc_udn_send_buffer(dest, UDN0_DEMUX_TAG, &C_priv[p*100], 100);
}
}
}
}
Some notes about my code that might make it easier to look at:
The send/receive buffer only allows up to 126 words at a time, so I am doing 100 for now just to make everything easily divisible when sending chunks of each array at a time.
I know in my message passing/receiving that I am not including thread 0, this is something I am going to fix later after I figure this issue out, so I am excluding its results from the accumulates array C_final for now
The idea is to break the initial problem size of (6000*6000) into (6000*6000)/20 sized chunks (if I am using 20 threads, for example)
Then I want to send each thread's C array to the master thread and accumulate it into C_final
I send the thread number before I send the data so I can place the received data in the right position to make the final array in order of each thread's data (C_final = [Thread 1's data, Thread 2's data, ...])
So finally, my issue is that even though I can see that the data I am sending and receiving is correct by verifying it before I send it and verifying it when I receive it, because the the array I am sending is of uint8_t and not long, when I check it after all the results are received, I end up getting parts of the array with garbage data while other parts have the correct result. I tried making both C_final and C_priv longs instead of 8-bit integers and verified that the results are correct after receiving everything, but not when I have them as 8-bit integer arrays.
Unfortunately, for this application I need to have the arrays doing the computations as 8-bit integers. Also, I am going to be including the time it takes to accumulate all of the results from the threads into the final C_final array so I am trying to make sure the accumulation doesn't take too much time (so I don't want do something like copying the results of C_final into a long array and then send that new array).
Is there any way to alleviate this problem without just changing my C_priv arrays and C_final array into longs instead of 8-bit integers? Also, I looked into the source code of the message passing, and the functions look this:
// Receive a packet of words from UDN demux 1.
//
// #param buf A long-aligned buffer
// #param words The size of the buffer (in longs)
//
static __inline void
tmc_udn1_receive_buffer(void* buf, unsigned long words)
{
unsigned long i;
unsigned long* ptr = (unsigned long*)buf;
for (i = 0; i < words; i++)
ptr[i] = udn1_receive();
}
...
// Send a packet of words on the UDN
//
// #param dest The destination (with no length)
// #param tag The tag (e.g. UDN0_DEMUX_TAG)
// #param buf A long-aligned buffer
// #param words The size of the buffer (in longs). This function can
// send a maximum of 126 longs
//
static __inline void
tmc_udn_send_buffer(DynamicHeader dest, unsigned long tag,
const void* buf, unsigned long words)
{
unsigned long i;
const unsigned long* ptr = (const unsigned long*)buf;
__tmc_udn_send_header_with_size_and_tag(dest, words, tag);
for (i = 0; i < words; i++)
udn_send(ptr[i]);
}
Edit:
For some additional clarity, this is the proper output I am expecting if I were to read the the indexes of C_final after accumulation. These are read at the first index of where each thread placed it's data (I was using 30 threads here but the idea is the same. Also the last one is -1 since I am omitting the master's thread results for now and just placing all the other thread's data in C_final starting at 0):
C_final[0] = 99
C_final[1875000] = 98
C_final[3750000] = 97
C_final[5625000] = 96
C_final[7500000] = 95
C_final[9375000] = 94
C_final[11250000] = 93
C_final[13125000] = 92
C_final[15000000] = 91
C_final[16875000] = 90
C_final[18750000] = 89
C_final[20625000] = 88
C_final[22500000] = 87
C_final[24375000] = 86
C_final[26250000] = 85
C_final[28125000] = 84
C_final[30000000] = 83
C_final[31875000] = 82
C_final[33750000] = 81
C_final[35625000] = 80
C_final[37500000] = 79
C_final[39375000] = 78
C_final[41250000] = 77
C_final[43125000] = 76
C_final[45000000] = 75
C_final[46875000] = 74
C_final[48750000] = 73
C_final[50625000] = 72
C_final[52500000] = 71
C_final[54375000] = -1
However, this is the result I am getting:
C_final[0] = 99
C_final[1875000] = -16
C_final[3750000] = 97
C_final[5625000] = 96
C_final[7500000] = 95
C_final[9375000] = -16
C_final[11250000] = -16
C_final[13125000] = 92
C_final[15000000] = -16
C_final[16875000] = 90
C_final[18750000] = -16
C_final[20625000] = 88
C_final[22500000] = -16
C_final[24375000] = -16
C_final[26250000] = 85
C_final[28125000] = -16
C_final[30000000] = -16
C_final[31875000] = 82
C_final[33750000] = -16
C_final[35625000] = -16
C_final[37500000] = -16
C_final[39375000] = 78
C_final[41250000] = -16
C_final[43125000] = 76
C_final[45000000] = -16
C_final[46875000] = -16
C_final[48750000] = 73
C_final[50625000] = 72
C_final[52500000] = -16
C_final[54375000] = -16
As for which results are accurate and which results are not, that changes every time I run it. It is not always the same indexes that have the correct results. The incorrect numbers that can be seen also are not consistent.

C array assign & access

I'm writing C code in a PIC16F1824, and are using UART.
I had this for receiving:
for(int i = 0; i < 9; i++){
while(!PIR1bits.RCIF);
RX_arr[i] = RCREG;
while(PIR1bits.RCIF);
}
RX_arr is an array declared as int RX_arr[9];
RCREG is the UART receving register and is supposed to have
0xFF 86 00 00 00 00 00 00 47;
Question1:
When i = 1, RX_arr[0]'s value(0xFF in this case) also changes when RX_arr[1] = RCREG is executed(Both postion 0 and 1 have 0x86).
Later I found using this segment of code instead of the for loop above will successfully assign one byte into each position:
if(!RCSTAbits.FERR && !RCSTAbits.OERR){
RX_arr[0] = RCREG;
}
However, the byte saved is wrong, only the 0xFF is always correct, other bytes are some other values. I found the OERR bit is set, which indicates an overrun error(2 byte FIFO buffer is full before accessed). How can I receive all the bytes in RCREG?
Question2:
After I get the response in question1, I read the useful information in it, which is in byte 2 and 3, and I made a variable called data. In my case the data is a sampled temperature, and I want to collect 20 samples,and save them in an array called ppm_array. sum_ppm is supposed to be the sum of all 20 samples, and will add the new sampled temperature to it every time a new sample is collected. When I run sum_ppm += ppm_array[i](sum_ppm = 0, ppm_array[0] = 1616, and the rest of the positions are 0),I got sum_ppm = 4508160. Why isn't it 1616??? Am I adding the address of them?
data = RX_arr[2] * 256 + RX_arr[3];
ppm_array[i] = data;
sum_ppm += ppm_array[i]
Many thanks.

C reading file using ./a.out<filename and how to stop reading

In my class today we were assigned a project that involves reading in a file using the ./a.out"<"filename command. The contents of the file look like this
16915 46.25 32 32
10492 34.05 56 52
10027 98.53 94 44
13926 32.94 19 65
15736 87.67 5 1
16429 31.00 58 25
15123 49.93 65 38
19802 37.89 10 20
-1
but larger
My issue is that any scanf used afterwards is completely ignored and just scans in what looks like garbage when printed out, rather than taking in user input. In my actual program this is causing an issue with a menu that requires input.
How do I get the program to stop reading the file provided by the ./a.out"<"filename command?
also I stop searching at -1 rather than EOF for the sake of not having an extra set of array data starting with -1
ex
-1 0 0 0
in my real program the class size is a constant that is adjustable and is used to calculate class averages, I'd rather not have a set of 0's skewing that data.
#include <stdio.h>
int main(void)
{
int i = 0,j = 1,d,euid[200],num;
int tester = 0;
float hw[200],ex1[200],ex2[200];
while(j)
{
scanf("%d",&tester);
if( tester == -1)
{
j = 0;
}
else
{
euid[i] = tester;
}
scanf("%f",hw+i);
scanf("%f",ex1+i);
scanf("%f",ex2+i);
i++;
}
for(d = 0;d < 50;d++) /*50 because the actual file size contains much more than example*/
{
printf("euid = %d\n",euid[d]);
printf("hw = %f\n",hw[d]);
printf("ex1 = %f\n",ex1[d]);
printf("ex2 = %f\n",ex2[d]);
}
printf("input something user\n");
scanf("%d",&num);
printf("This is what is being printed out -> %d\n",num);
return 0;
}
I'm having the exact same problem. Tried every method I could find to eat the remaining input in the buffer, but it never ends.
Got it to work using fopen and fscanf, but the prof. said he prefers the code using a.out < filename
Turns out this is in fact not possible.

Getting Image size of JPEG from its binary

I have a lot of jpeg files with varying image size. For instance, here is the first 640 bytes as given by hexdump of an image of size 256*384(pixels):
0000000: ffd8 ffe0 0010 4a46 4946 0001 0101 0048 ......JFIF.....H
0000010: 0048 0000 ffdb 0043 0003 0202 0302 0203 .H.....C........
0000020: 0303 0304 0303 0405 0805 0504 0405 0a07 ................
0000030: 0706 080c 0a0c 0c0b 0a0b 0b0d 0e12 100d ................
I guess the size information mus be within these lines. But am unable to see which bytes give the sizes correctly. Can anyone help me find the fields that contains the size information?
According to the Syntax and structure section of the JPEG page on wikipedia, the width and height of the image don't seem to be stored in the image itself -- or, at least, not in a way that's quite easy to find.
Still, quoting from JPEG image compression FAQ, part 1/2 :
Subject: [22] How can my program extract image dimensions from a JPEG
file?
The header of a JPEG file consists of
a series of blocks, called "markers".
The image height and width are stored
in a marker of type SOFn (Start Of
Frame, type N). To find the SOFn
you must skip over the preceding
markers; you don't have to know what's
in the other types of markers, just
use their length words to skip over
them. The minimum logic needed is
perhaps a page of C code. (Some
people have recommended just searching
for the byte pair representing SOFn,
without paying attention to the marker
block structure. This is unsafe
because a prior marker might contain
the SOFn pattern, either by chance or
because it contains a JPEG-compressed
thumbnail image. If you don't follow
the marker structure you will retrieve
the thumbnail's size instead of the
main image size.) A profusely
commented example in C can be found in
rdjpgcom.c in the IJG distribution
(see part 2, item 15). Perl code
can be found in wwwis, from
http://www.tardis.ed.ac.uk/~ark/wwwis/.
(Ergh, that link seems broken...)
Here's a portion of C code that could help you, though : Decoding the width and height of a JPEG (JFIF) file
This function will read JPEG properties
function jpegProps(data) { // data is an array of bytes
var off = 0;
while(off<data.length) {
while(data[off]==0xff) off++;
var mrkr = data[off]; off++;
if(mrkr==0xd8) continue; // SOI
if(mrkr==0xd9) break; // EOI
if(0xd0<=mrkr && mrkr<=0xd7) continue;
if(mrkr==0x01) continue; // TEM
var len = (data[off]<<8) | data[off+1]; off+=2;
if(mrkr==0xc0) return {
bpc : data[off], // precission (bits per channel)
h : (data[off+1]<<8) | data[off+2],
w : (data[off+3]<<8) | data[off+4],
cps : data[off+5] // number of color components
}
off+=len-2;
}
}
 
I have converted the CPP code from the top answer into a python script.
"""
Source: https://stackoverflow.com/questions/2517854/getting-image-size-of-jpeg-from-its-binary#:~:text=The%20header%20of%20a%20JPEG,Of%20Frame%2C%20type%20N).
"""
def get_jpeg_size(data):
"""
Gets the JPEG size from the array of data passed to the function, file reference: http:#www.obrador.com/essentialjpeg/headerinfo.htm
"""
data_size=len(data)
#Check for valid JPEG image
i=0 # Keeps track of the position within the file
if(data[i] == 0xFF and data[i+1] == 0xD8 and data[i+2] == 0xFF and data[i+3] == 0xE0):
# Check for valid JPEG header (null terminated JFIF)
i += 4
if(data[i+2] == ord('J') and data[i+3] == ord('F') and data[i+4] == ord('I') and data[i+5] == ord('F') and data[i+6] == 0x00):
#Retrieve the block length of the first block since the first block will not contain the size of file
block_length = data[i] * 256 + data[i+1]
while (i<data_size):
i+=block_length #Increase the file index to get to the next block
if(i >= data_size): return False; #Check to protect against segmentation faults
if(data[i] != 0xFF): return False; #Check that we are truly at the start of another block
if(data[i+1] == 0xC0): #0xFFC0 is the "Start of frame" marker which contains the file size
#The structure of the 0xFFC0 block is quite simple [0xFFC0][ushort length][uchar precision][ushort x][ushort y]
height = data[i+5]*256 + data[i+6];
width = data[i+7]*256 + data[i+8];
return height, width
else:
i+=2; #Skip the block marker
block_length = data[i] * 256 + data[i+1] #Go to the next block
return False #If this point is reached then no size was found
else:
return False #Not a valid JFIF string
else:
return False #Not a valid SOI header
with open('path/to/file.jpg','rb') as handle:
data = handle.read()
h, w = get_jpeg_size(data)
print(s)
This is how I implemented this using js. The marker you are looking for is the Sofn marker and the pseudocode would basically be:
start from the first byte
the beginning of a segment will always be FF followed by another byte indicating marker type (those 2 bytes are called the marker)
if that other byte is 01 or D1 through D9, there is no data in that segment, so proceed to next segment
if that marker is C0 or C2 (or any other Cn, more detail in the comments of the code), thats the Sofn marker you're looking for
the following bytes after the marker will be P (1 byte), L (2 bytes), Height (2 bytes), Width (2 bytes) respectively
otherwise, the next two bytes followed by it will be the length property (length of entire segment excluding the marker, 2 bytes), use that to skip to the next segment
repeat until you find the Sofn marker
function getJpgSize(hexArr) {
let i = 0;
let marker = '';
while (i < hexArr.length) {
//ff always start a marker,
//something's really wrong if the first btye isn't ff
if (hexArr[i] !== 'ff') {
console.log(i);
throw new Error('aaaaaaa');
}
//get the second byte of the marker, which indicates the marker type
marker = hexArr[++i];
//these are segments that don't have any data stored in it, thus only 2 bytes
//01 and D1 through D9
if (marker === '01' || (!isNaN(parseInt(marker[1])) && marker[0] === 'd')) {
i++;
continue;
}
/*
sofn marker: https://www.w3.org/Graphics/JPEG/itu-t81.pdf pg 36
INFORMATION TECHNOLOGY –
DIGITAL COMPRESSION AND CODING
OF CONTINUOUS-TONE STILL IMAGES –
REQUIREMENTS AND GUIDELINES
basically, sofn (start of frame, type n) segment contains information
about the characteristics of the jpg
the marker is followed by:
- Lf [frame header length], two bytes
- P [sample precision], one byte
- Y [number of lines in the src img], two bytes, which is essentially the height
- X [number of samples per line], two bytes, which is essentially the width
... [other parameters]
sofn marker codes: https://www.digicamsoft.com/itu/itu-t81-36.html
apparently there are other sofn markers but these two the most common ones
*/
if (marker === 'c0' || marker === 'c2') {
break;
}
//2 bytes specifying length of the segment (length excludes marker)
//jumps to the next seg
i += parseInt(hexArr.slice(i + 1, i + 3).join(''), 16) + 1;
}
const size = {
height: parseInt(hexArr.slice(i + 4, i + 6).join(''), 16),
width: parseInt(hexArr.slice(i + 6, i + 8).join(''), 16),
};
return size;
}
If you are on a linux system and have PHP at hand, variations on this php script may produce what you are looking for:
#! /usr/bin/php -q
<?php
if (file_exists($argv[1]) ) {
$targetfile = $argv[1];
// get info on uploaded file residing in the /var/tmp directory:
$safefile = escapeshellcmd($targetfile);
$getinfo = `/usr/bin/identify $safefile`;
$imginfo = preg_split("/\s+/",$getinfo);
$ftype = strtolower($imginfo[1]);
$fsize = $imginfo[2];
switch($fsize) {
case 0:
print "FAILED\n";
break;
default:
print $safefile.'|'.$ftype.'|'.$fsize."|\n";
}
}
// eof
host> imageinfo 009140_DJI_0007.JPG
009140_DJI_0007.JPG|jpeg|4000x3000|
(Outputs filename, file type, file dimensions in pipe-delimited format)
From the man page:
For more information about the 'identify' command, point your browser to [...] http://www.imagemagick.org/script/identify.php.
Dart/Flutter port from a solution in this forum.
class JpegProps {
final int precision;
final int height;
final int width;
final int compression;
JpegProps._(this.precision, this.height, this.width, this.compression,);
String toString() => 'JpegProps($precision,$height,$width,$compression)';
static JpegProps readImage(Uint8List imageData) {
// data is an array of bytes
int offset = 0;
while (offset < imageData.length) {
while (imageData[offset] == 0xff) offset++;
var mrkr = imageData[offset];
offset++;
if (mrkr == 0xd8) continue; // SOI
if (mrkr == 0xd9) break; // EOI
if (0xd0 <= mrkr && mrkr <= 0xd7) continue;
if (mrkr == 0x01) continue; // TEM
var length = (imageData[offset] << 8) | imageData[offset + 1];
offset += 2;
if (mrkr == 0xc0) {
return JpegProps._(imageData[offset],
(imageData[offset + 1] << 8) | imageData[offset + 2],
(imageData[offset + 3] << 8) | imageData[offset + 4],
imageData[offset + 5],
);
}
offset += length - 2;
}
throw '';
}
}
Easy way to get width and heigh from a .jpg picture. Remove the EXIF and ITP information in the the file. Use "Save as" function in a view picture program (I used IrfanView or Pain Shop Pro). In the "Save as" get rid of EXIF, then save the file. The jpg file has always without EXIF the heigh at byte 000000a3 and 000000a4. The width are at 000000a5 and 000000a6
I use php
function storrelse_jpg($billedfil) //billedfil danish for picturefile
{
//Adresse for jpg fil without EXIF info !!!!!
// width is in byte 165 til 166, heigh is in byte 163 og 164
// jpg dimensions are with 2 bytes ( in png are the dimensions with 4 bytes
$billedfil="../diashow/billeder/christiansdal_teltplads_1_x.jpg"; // the picturefil
$tekst=file_get_contents($billedfil,0,NULL,165,2); //Read from 165 2 bytes - width
$tekst1=file_get_contents($billedfil,0,NULL,163,2);//Read from 163 2 bytes - heigh
$n=strlen($tekst); // længden af strengen
echo "Størrelse på billed : ".$billedfil. "<br>"; // Headline
$bredde=0; // width
$langde=0; // heigh
for ($i=0;$i<$n;$i++)
{
$by=bin2hex($tekst[$i]); //width-byte from binær to hex
$bz=hexdec($by);// then from hex to decimal
$ly=bin2hex($tekst1[$i]); // the same for length byte
$lz=hexdec($ly);
$bredde=$bredde+$bz*256**(1-$i);
$langde=$langde+$lz*256**(1-$i);
}
// $x is a array $x[0] er width and $x[1] er heigh
$x[0]=$bredde; $x[1]=$langde;
return $x;
}
A python solution based on "raw" CPP convert - https://stackoverflow.com/a/62245035/11807679
def get_jpeg_resolution(image_bytes: bytes,
size: int = None) -> Optional[Tuple[int, int]]:
"""
function for getting resolution from binary
:param image_bytes: image binary
:param size: image_bytes len if value is None it'll calc inside
:return: (width, height) or None if not found
"""
size = len(image_bytes) if size is None else size
header_bytes = (0xff, 0xD8, 0xff, 0xe0)
if not (size > 11
and header_bytes == struct.unpack_from('>4B', image_bytes)):
# Incorrect header or minimal length
return None
jfif_bytes = tuple(ord(s) for s in 'JFIF') + (0x0, )
if not (jfif_bytes == struct.unpack_from('5B', image_bytes, 6)):
# Not a valid JFIF string
return None
index = len(header_bytes)
block_length, = struct.unpack_from(">H", image_bytes, index)
index += block_length
while index < size:
if image_bytes[index] != 0xFF:
break
# Check that we are truly at the start
# of another block
if image_bytes[index + 1] == 0xC0:
# 0xFFC0 is the "Start of frame" marker
# which contains the file size
# The structure of the 0xFFC0 block is
# quite simple
# [0xFFC0][ushort length][uchar precision]
# [ushort x][ushort y]
height, width = struct.unpack_from(">HH", image_bytes, index + 5)
return width, height
else:
index += 2
# Skip the block marker
# Go to the next block
block_length, = struct.unpack(">H",
image_bytes[slice(index, index + 2)])
# Increase the file index to get to the next block
index += block_length
# If this point is reached then no size was found
return None

Resources