X

NV5 Geospatial Blog

Each month, NV5 Geospatial posts new blog content across a variety of categories. Browse our latest posts below to learn about important geospatial information or use the search bar to find a specific topic or author. Stay informed of the latest blog posts, events, and technologies by joining our email list!



From Image to Insight: How GEOINT Automation Is Changing the Speed of Decision-Making

From Image to Insight: How GEOINT Automation Is Changing the Speed of Decision-Making

4/28/2025

When every second counts, the ability to process geospatial data rapidly and accurately isn’t just helpful, it’s critical. Geospatial Intelligence (GEOINT) has always played a pivotal role in defense, security, and disaster response. But in high-tempo operations, traditional workflows are no longer fast enough. Analysts are... Read More >

Thermal Infrared Echoes: Illuminating the Last Gasp of a Dying Star

Thermal Infrared Echoes: Illuminating the Last Gasp of a Dying Star

4/24/2025

This blog was written by Eli Dwek, Emeritus, NASA Goddard Space Flight Center, Greenbelt, MD and Research Fellow, Center for Astrophysics, Harvard & Smithsonian, Cambridge, MA. It is the fifth blog in a series showcasing our IDL® Fellows program which supports passionate retired IDL users who may need support to continue their work... Read More >

A New Era of Hyperspectral Imaging with ENVI® and Wyvern’s Open Data Program

A New Era of Hyperspectral Imaging with ENVI® and Wyvern’s Open Data Program

2/25/2025

This blog was written in collaboration with Adam O’Connor from Wyvern.   As hyperspectral imaging (HSI) continues to grow in importance, access to high-quality satellite data is key to unlocking new insights in environmental monitoring, agriculture, forestry, mining, security, energy infrastructure management, and more.... Read More >

Ensure Mission Success With the Deployable Tactical Analytics Kit (DTAK)

Ensure Mission Success With the Deployable Tactical Analytics Kit (DTAK)

2/11/2025

In today’s fast-evolving world, operational success hinges on real-time geospatial intelligence and data-driven decisions. Whether it’s responding to natural disasters, securing borders, or executing military operations, having the right tools to integrate and analyze data can mean the difference between success and failure.... Read More >

How the COVID-19 Lockdown Improved Air Quality in Ecuador: A Deep Dive Using Satellite Data and ENVI® Software

How the COVID-19 Lockdown Improved Air Quality in Ecuador: A Deep Dive Using Satellite Data and ENVI® Software

1/21/2025

The COVID-19 pandemic drastically altered daily life, leading to unexpected environmental changes, particularly in air quality. Ecuador, like many other countries, experienced significant shifts in pollutant concentrations due to lockdown measures. In collaboration with Geospace Solutions and Universidad de las Fuerzas Armadas ESPE,... Read More >

1345678910Last
«May 2025»
SunMonTueWedThuFriSat
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567
10097 Rate this article:
3.3

Brute Force PNG Image Sizing

Anonym

Recently, I was working on a project that had some pretty strict requirements for the max size of the output .png file. This did not seem like a big deal initially, until I realized that it is extremely difficult to calculate the final size of a .png file prior to creating the image. Long story short, this led me to creating a brute force method for finding the optimal size of an output image.

As a side note, I know what you are thinking, “if it is so difficult, why don’t you just choose a couple of sizes, try those out and then create a linear model so that in the future you no longer have to deal with this?”  Well I tried it and it was a no-go. As you can see from figures 1 and 2 it is not a simple linear relationship, nor is it an easily predictable relationship. The blue lines in figures 1 and 2 represent the file’s size as compared to the number of pixels in the image; whereas the red line is a simple linear regression. It is possible to see a pretty distinct deviation from the trend line.

Figure 1

Figure 2

Back to the task at hand: the brute force method. The method is relatively simple:

  1. Save the image at its native size (if it is smaller than the max allowable size, you are done).
  2. Reduce the original image size by one half and check the file size.
    • If it is larger than the allowable size, take one quarter of the original image dimensions, or in other words, one half of the distance between the last computed value that was too large (i.e. 50% of the initial image size) and the last smallest computed value (the smallest image size has not been computed yet, since this is the first iteration so just set it to zero).
    • If it is smaller than the allowable size, take three quarters of the original file size, or one half the distance between the last largest image dimensions computed (in this case the original image dimensions) and the last smallest image dimensions computed (i.e. one half the original).
  3. Continue the pattern of taking one of the values either greater than or less than the halfway point that was just computed. Each time, make sure that the number of lines and samples is being computed using either integer or long values.
  4. After each iteration, check to see if the same image dimensions have already been tested and if so, that is your final image size and you have found the optimal solution.

The example below should shed a little bit more light on how this is being performed.

 ;Start the application

 e = ENVI()

 

 ;Open an input file

 File = Filepath('qb_boulder_msi', Subdir=['data'], $

   Root_Dir=e.Root_Dir)

 Raster = e.OpenRaster(File)

 

 ;Get the  task from the catalog ofENVITasks

 Task = ENVITask('ISODATAClassification')

 

 ;Define inputs

 Task.Input_Raster = Raster

 

 ;Run the task

 Task.Execute

 

 ;Pull out the new ISOData raster

 ISORaster = Task.OUTPUT_RASTER

 

 ;get the metadata

 metadata = ISORaster.Metadata

 

 ;get the information about the new file

 nb = ISORaster.nb

 Raster_ns = ISORaster.ns

 Raster_nl = ISORaster.nl

 

 ;set the filename for the output file

 output_file = 'C:\Output\PNG_Test.png'

 

 ;Set the desired output size in bytes

 output_size = 150000

 

 ;delete any old files with the same name

 FILE_DELETE, output_file,/ALLOW_NONEXISTENT

 

 ;Save the image out as our initial test

 

 ;Get the task from the catalog of ENVITasks

 ERTP_Task = ENVITask('ExportRasterToPNG')

 

 ;Define inputs

 ERTP_Task.INPUT_RASTER = ISORaster

 

 ;Define outputs

 ERTP_Task.OUTPUT_URI = output_file

 

 ;Run the task

 ERTP_Task.Execute

 

 ;Close the PNG Raster

 ERTP_Task.Output_Raster.close

 

 ;Get the new File Size

 file_size = ((file_info(output_file)).size) * 1.

 

 ;create a container for the maximum number of samples and lines

 max_ns = Raster_ns

 max_nl = Raster_nl

 

 ;create a container for the current number of samples and lines

 nl = Raster_nl

 ns = Raster_ns

 

 ;create a container for the minimum number of samples and lines

 min_ns = 0

 min_nl = 0

 

 ;Create a container for the 1D index value of the lower right corner

 ;of the image with regards to the maximum image size

 loc_1d = []

 

 ;check to make sure the image is currently too large

 if file_size gt output_size then begin

 

   ;check to see if the same image size has come up more than once.  if so

   ;then stop iterating

   while ((where(loc_1d eq (nl * Raster_ns +ns)))[0] eq -1do begin

 

     ;record the image width and height in 1D

     loc_1d = [loc_1d, nl * Raster_ns + ns]

 

     ;decide which side of the value should be divided in half

     if (file_size gt output_size) then side = 'right'

     if (file_size lt output_size) then side = 'left'

 

     case side of

 

       ;the image is too large and must be reduced in size

       'right' : begin

 

          ; determine the new size of the image (i.e.1/2 of the upper bound minus the current size)

          ns = max_ns - ((max_ns - min_ns)* .5)

          nl = max_nl - ((max_nl - min_nl)* .5)

 

          ; Delete the old image

          FILE_DELETE, output_file,/ALLOW_NONEXISTENT

 

          ; Shrink the original image

 

          ; Get the task from the catalog ofENVITasks

          DRR_Task=ENVITask('DimensionsResampleRaster')

 

          ; Define inputs

          DRR_Task.INPUT_RASTER =ISORaster

          DRR_Task.DIMENSIONS=[ns,nl]

 

          ; Run the task

          DRR_Task.Execute

 

          ns = DRR_Task.Output_Raster.ns

          nl = DRR_Task.Output_Raster.nl

 

          ; Get the task from the catalog ofENVITasks

          ERTP_Task = ENVITask('ExportRasterToPNG')

 

          ; Define inputs

          ERTP_Task.INPUT_RASTER =DRR_Task.Output_Raster

 

          ; Define outputs

          ERTP_Task.OUTPUT_URI =output_file

 

          ; Run the task

          ERTP_Task.Execute

 

          ; Close the Resampled Raster

          DRR_Task.Output_Raster.close

 

          ; Close the PNG raster

          ERTP_Task.OUTPUT_Raster.close

 

          ; Get the new File Size

          file_size = ((file_info(output_file)).size)* 1.

 

          ; Record the new dimensions as the upperbound

          max_ns = ns

          max_nl = nl

 

       end

 

       'left' : begin ; too small

 

          ; determine the new size of the image (i.e.1.5 of the upper bound minus the current size)

          ns = ((max_ns - min_ns)* 1.5) + max_ns

          nl = ((max_nl - min_nl)* 1.5 )+ max_nl

 

          ; Delete the old image

          FILE_DELETE, output_file,/ALLOW_NONEXISTENT

 

          ; Shrink the original image

 

          ; Get the task from the catalog ofENVITasks

          DRR_Task=ENVITask('DimensionsResampleRaster')

 

          ; Define inputs

          DRR_Task.INPUT_RASTER =ISORaster

          DRR_Task.DIMENSIONS=[ns,nl]

 

          ; Run the task

          DRR_Task.Execute

 

          ; Record the dimensions of the new image

          dims = size(test_img,/DIMENSIONS)

          ns = DRR_Task.OUTPUT_RASTER.ns

          nl = DRR_Task.OUTPUT_RASTER.nl

          ; Save the new image and test the size

 

          ; Get the task from the catalog ofENVITasks

          ERTP_Task = ENVITask('ExportRasterToPNG')

 

          ; Define inputs

          ERTP_Task.INPUT_RASTER =DRR_Task.Output_Raster

 

          ; Define outputs

          ERTP_Task.OUTPUT_URI =output_file

 

          ; Run the task

          ERTP_Task.Execute

 

          ; Close the Resampled Raster

          DRR_Task.Output_Raster.close

 

          ; Close the PNG raster

          ERTP_Task.OUTPUT_Raster.close

 

          ; Record the new file size

          file_size = ((file_info(output_file)).size)* 1.

 

          ; Record the old dimension as the lowerbound

          min_ns = max_ns

          min_nl = max_nl

 

          ; Record the new dimension as the upperbound

          max_ns = ns

          max_nl = nl

 

       end

     endcase

   endwhile

 endif

 

 ;Close the intial raster

  ISORaster.close


 
Please login or register to post comments.